Lexical Closure in J
If you want to know how to solve Paul Graham's accumulator generator challenge, then you are looking for the FAQ on that topic .
- you've read that page and
- you're familiar with J and
- you want a chuckle
then you've come to the right place. Read on.
This page has the same motivation as the FAQ on lexical closure, but answers it in a (abusively) different way.
Read the caveats. Then download the lexical closure script. Save it at jpath '~addons\lexicalclosure.ijs'. Then:
load '~addons\lexicalclosure.ijs' accGen=. 4 : 'x =. x + y' lexicalClosureOnRHA acc0 =. 0 accGen acc0 1 1 acc0 1 2 acc10 =. 10 accGen NB. Start with 10 acc10 78.5 88.5 100 accGen"0 i. 10 NB. Anonymous accumulator 100 101 103 106 110 115 121 128 136 145
In order to provide some redeeming value with this page, I present a generalization.
In combination with a the parameterized verb script I previously presented, we can have named local arguments whose values are preserved .
Using the following definition of the verb parameterizedVerb :
NB. Define a parameterized verb. A noun-define is used to create the default parameter table, NB. to enhance readability. parameterizedVerb =: (verb define) defineAndDefaultParams (makeParamTable noun define) filename = 'c:\short.log' max = 42 color = 'red' increment* = 0 NB. This is flagged, so its state is preserved across calls. ) smoutput LF,'=======' smoutput 'This is ordinal call #',":increment =. >: increment smoutput 'Logging to: ', filename smoutput 'Max is: ' , ": max if. color_is_default do. smoutput 'My favorite color is ',color else. smoutput 'Your favorite color is ',color end. smoutput '=======' )
The the following sentences result in the corresponding outputs:
NB. Use all the defaults parameterizedVerb '' ======= This is ordinal call #1 Logging to: c:\short.log Max is: 42 My favorite color is red ======= NB. Change the first parameter (filename). parameterizedVerb '\\server\share\app_logs\myapp.log' ======= This is ordinal call #2 Logging to: \\server\share\app_logs\myapp.log Max is: 42 My favorite color is red ======= NB. Change the first two parameters (filename & max) parameterizedVerb '\\server\share\app_logs\myapp.log';906 ======= This is ordinal call #3 Logging to: \\server\share\app_logs\myapp.log Max is: 906 My favorite color is red ======= NB. Change the specified parameter (color) parameterizedVerb _2 ]\ ;: 'color blue' ======= This is ordinal call #4 Logging to: c:\short.log Max is: 42 Your favorite color is blue ======= NB. Ditto - names are normalized before testing for equivalence (see normalizeNames, which can be changed to suit your needs). parameterizedVerb _2 ]\ ;: 'COLOR blue' ======= This is ordinal call #5 Logging to: c:\short.log Max is: 42 Your favorite color is blue ======= NB. Supply new default parameter table. NB. This will turn off the closure of x. stringToTabl =. (0&".`]@.(__&e.@:(__&".))&.>)@:(_2&(]\))@:(<;._1) ' filename f:\output.log max 999 color verdigris increment 0' parameterizedVerb&:stringToTabl ' max 1000' ======= This is ordinal call #1 Logging to: f:\output.log Max is: 10000 My favorite color is verdigris =======
- The verbs returned by defineAndDefaultParams are anonymous. You can't use the debug facility with them.
- The entire scheme for closure here is predicated upon J mapped files. Hence:
- Space for J mapped files has to be pre-allocated. Thus if you close names that grow across calls, you'll eventually get an allocation error.
- This won't work under Linux because I use 'winapi' to get a temporary file name.
- The mapped files aren't cleaned up automatically. Every time you run defineAndDefaultParams another file will be created (with a size proportional to n.). You'll need to clean these by hand.
- This is a cute, but really stupid, way to get closures. I'm abusing JMF. I don't expect you to use this seriously. Just use globals. Redefining defineAndDefaultParams to make this transparent (by storing the default LHA as a global in a special locale) is trivial.