As a diversion today, I added "color tab completion" to the Factor environment. I even made the color names render with their assigned color value:
Tuesday, September 18, 2012
We've known for awhile that the Factor user interface is a little bit slow when displaying tables with many rows. I wasn't sure this was a big problem until a detailed bug report was filed (thanks @k7f!) that pointed out the opengl.gl vocabulary (with over 2,000 symbols in it) was "virtually unscrollable".
After poking around at the profiler output, I noticed that some UI gadgets had "baseline alignment" support which was used in the layout process. Some of these calculations were quite expensive and could easily be cached.
After a few changes, and introducing the concept of an "aligned gadget" which provides a mechanism to cache these alignment calculations, the original test case is almost 10 times as responsive as before!
This is available in the master branch on Github.
Monday, September 10, 2012
Function "annotations" are a feature that many languages support. They may take various forms such as decorators in Python or class and method annotations in Java -- having direct (like Python) or no direct (like Java) effect on the code it annotates. Factor has some similar features that I'll demonstrate below.
We can define a simple word to use in this example (that adds
2 to its input):
: foo ( x -- n ) 2 + ;
Using the tools.annotations vocabulary, we can attach a "watch" annotation that prints the inputs and outputs of a word when it is called:
IN: scratchpad \ foo watch
If you print the word definition, you can see how it was modified:
IN: scratchpad \ foo see USING: math tools.annotations.private ; IN: scratchpad : foo ( x -- n ) \ foo entering 2 + \ foo leaving ;
You can call this word (either directly, or indirectly by calling another word which calls it) and see its inputs and outputs. A nice feature of this is that the UI lets you click on these values and see more detail (particularly useful if they are tuples or more complex objects):
IN: scratchpad 3 foo --- Entering foo x 3 --- Leaving foo n 5
You can stop watching a word by calling "reset" on it (or right-clicking on its definition in the UI and choosing "reset") to remove all of its annotations. Currently, a word can only be annotated once.
IN: scratchpad \ foo reset
In addition to "watching", you can also use annotations to track the total running time of a word:
IN: scratchpad \ foo add-timing IN: scratchpad 0 10,000 [ foo ] times . 20000 IN: scratchpad word-timing. foo 0.000594456
It also supports arbitrary annotations, such as adding "before" and "after" logic:
IN: scratchpad \ foo [ "hi" print ] [ "bye" print ] [ surround ] 2curry annotate IN: scratchpad 3 foo . hi bye 5
These annotations can be pretty powerful and were even used to build our code coverage tool.