very cool.  To help people understand it, the requirements for the template are 
that it is an implicit definition, and that it parses ok, and also that it is a 
verb (modifiers don't play well as gerunds).

with that in mind, here are some verbs to make things a bit easier:

substit  =: [^:(__-:])L:_ 0
substit2 =: substit"_1 _~
mktemplate =: 1 : '{. u f. `'''''

One useful "verb" that requires 3 arguments, and has special code as an adverb 
is power residue &|@^

(3&|@^) will raise x to the y power and then take the residue to 3.  Basically 
Dan's code allows to fix these verbs.  Once you have created your template 
implicit verb

powmod3 =: __&|@^ mktemplate substit2  3

   powmod3`:6
3&|@^

Dan, is there a way to make multiple substitutions, ie. for this template:

(__ + __&|@^) mktemplate  NB. could it substitute 2 seperate nouns from y?



Also are verbs (modifiers?) substitutable?

In terms of other examples,

Here is a class that wraps around Jqt 's new timer functionality.  There is 
only one global timer callback available, and so assuming the possibility that 
more than one routine would like to be run, without knowing that any other 
routine has been set, this could work: (not tested extensively)

Its not gerunds, but it was was pretty straight forward to write.  The class 
accumulates the sequence of callbacks into the callback variable (in add 
variation), and tells the timer to run them all.


cocurrent 'timer'
callback =: ]

set=: 4 : 0 NB. x is explicit code to run/string.  y is miliseconds interval
if. y do.
callback =: (3 : x)
sys_timer_z_=: callback f. "_
wd 'timer ',":y
else.
wd 'timer 0'
sys_timer_z_=: ]
end.
EMPTY
)
add =: 4 : 0
if. y do.
callback =: (callback f.)`(3 : x)
sys_timer_z_=: callback"_ `:0
wd 'timer ',":y
else.
wd 'timer 0'
sys_timer_z_=: ]
end.
EMPTY
)

________________________________
From: Dan Bron <j...@bron.us>
To: programm...@jsoftware.com 
Sent: Thursday, February 20, 2014 2:39:49 PM
Subject: [Jprogramming] Generating code from templates


There was a question on StackOverflow today on generating constant
functions from the items of an array. As in, 100 200 300 <==>
100"_`(200"_)`(300"_) . 

As a more general question, how can we specify code templates and then use
them to dynamically produce gerunds for later execution? *

Here's one idiom I've found useful in such situations:

   substit  =: [^:(__-:])L:_ 0

   template =: __"_               NB. The template; note the __ 
   TEMPLATE =: {. template f.`''  NB. Atomic rep of template

   GERUND =: TEMPLATE substit"_1 _~ 100 * 1 + i.3 

   GERUND`:6
(100"_) (200"_) 300"_

  GERUND@.0
100"_

  GERUND@.2 'hello'
300

The basic idea is to "fill in the blanks" in the template with the inputs.
Here, the blank is __ (negative infinity), so we look for that in the
gerund template, and when we find it, we replace it with the input. I kind
of like how the verb does this: first, we only bother looking at level 0
(because __ is unboxed, so it will never appear above level 0), and
second, the verb is passive until __ is detected (because ^:(]-:__) is
^:0, i.e. "do nothing and just return the RHA" until then).

One possible issue is what we use to denote "blank". If we're going to
allow users to pass in any gerund, then he could potentially want to
include __ as part of the code to be produced, rather than replaced. There
are a couple possible ways to address that limitation. First, we could use
a value which a user is very unlikely to want to produce (as opposed to
replace), i.e. _. :

   substit  =: [^:(1-:128!:5@])L:_ 0
   SPARTA =: ({.   _."_   `'') substit"_1 _~  300
   SPARTA`:6
300"_

Or, we could define substit as an adverb (adjective), which takes the
"blank" as an argument:

   Substit =: (-:&) (@]) ([^:) (L:_ 0)

   substit =: 'blank' Substit
   substit 
[^:(-:&'blank'@])L:_ 0

   ; , ((< {. 'blank'&;`'') substit~&.> ;:'fill in the blanks' )`:0 '!'
fill!in!the!blanks!

But if we do that, we have to start wondering about the 0 in L:_ 0 ,
because the user's "blank" might be boxed, and therefore have L.>0 . Of
course, we could fix this up by making the L: dynamic:

   Substit  =: adverb : '[^:(m-:])L:(_,L.m)'

   NOTNULL  =: ({. ~:&a:` '')  a: Substit~  <'#N/A#'
   NOTNULL`:6
~:&(<'#N/A#')

But it might be more fun to go meta-meta:

   (({. substit f.`'') substit~ _999)`:6
[^:(_999 -: ])L:_ 0

Here, define the "standard" blank to be __, and then let the user change it
by using substit  :)  

Anyway, thought I'd share, and see if anyone else has useful tools for
manipulating J code (metaprogramming).

-Dan

*  For a recent example of where such metaprogramming might be useful, or
convenient, see the postscript of:

  http://www.jsoftware.com/pipermail/programming/2013-December/034373.html

Other examples can be found with a forum archive search for the string L:0 _
----------------------------------------------------------------------
For information about J forums see http://www.jsoftware.com/forums.htm
----------------------------------------------------------------------
For information about J forums see http://www.jsoftware.com/forums.htm

Reply via email to