Application: Word Usage Counts

When you want to optimize the performance of a program, it is a common practice to find the most frequently used words and make them top priority. Hence, here we are writing a program to record the counts of all the self-defined words being used without redefining them.

Step 1

Create a hash called "counts" which stores the identities of the words to be defined and their respective number of counts.

		# constant counts
	

After the hash table is created, what do you think the key should be?

Step 2

Redefine the word
;
so that when a new word completes its compilation, it will initialize the counts value to be 0 for this word.
		: ; ` ; latestxt 0 counts #! ; immediate
	
latestxt
will refer to the latest XT encountered. Therefore, when a new word is being defined,
latestXT
is the XT of that word.

Step 3

Redefine the word
:
so that when your word runs, it will increment its value in the hash table "counts" by 1. Before implementing this function, don't forget that since the word
;
has been redefined, it will create an entry in the table "counts" for each word you define in this step. Therefore, you need to use
ALIAS
to backup the original definition of the word
;
into a new word.
		: this ( -- xt )
			latestxt ` literal
		; immediate

		: counts@
			counts #@
		;

		: counts! ( n -- )
			counts #!
		;

		: +counts ( xt -- )
			dup counts@ 1+ counts!
		;
		

		' ; alias ;; 		\ create the word ;; which has the original function of ;
		
		: ; ` ; latestxt 0 counts #! ; immediate

		: : : ` this ['] +counts compile, ;;
	
	

When a word consists of many actions, remember to break it into several parts to define some more words of these actions so that it will look simpler and more comprehensible to human

Step 4

Define a word
.COUNTS
to display the counts of all the words. Recall that
#KEYS
returns a sequence of all the keys in a hash and we need to use a loop to display the count value associated with each XT. First of all, we need to write a word
REDUCE
which requires a sequence and an XT. This word will execute the provided XT on each element of the sequence.
		: reduce ( seq xt -- ) ~ { f }
			begin
				dup empty? -> drop exit |.
				dup head f
				tail
			again
		;
	
Next, we can use
REDUCE
to write a word
.COUNTS
which displays all the count value of each XT.
		: .counts
			counts #keys
			[:
				{ k }
				k name? . "-->" . k counts #@ . cr	\ NAME? gets the word's name from XT
			;] reduce
		;
	
Make sure that the definitions in Step 4 are placed before words
:
and
;
so that the issue mentioned in Step 3 can be avoided.

Quiz

Question 1

In step 3, we redefine the word
:
instead of
;
. Why do we increment the count at the beginning of running a word instead of the end? Hint: under which circumstances a word cannot reach its end?



Question 2

In step 3, we used
THIS
(you have come across this word in the earlier tutorial. Can you recall what it does?). What will happen if we just conveniently compile
LATESTXT
into each word?



Question 3

Other than the frequency, the total duration of your words running in the program is also a key factor when you want to determine the performance. Hence, modify the example so that it records the total duration.



Next: Extending Smojo