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
will refer to the latest XT encountered. Therefore, when a new word is being defined,
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
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
to display the counts of all the words. Recall that
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
which requires a sequence and an XT. This word will execute the provided XT on each element of the sequence.
		: reduce ( seq xt -- ) ~ { f }
				dup empty? -> drop exit |.
				dup head f
Next, we can use
to write a word
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
so that the issue mentioned in Step 3 can be avoided.


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
(you have come across this word in the earlier tutorial. Can you recall what it does?). What will happen if we just conveniently compile
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