Yes, here's a bit more background for the techniques I used.

First, (4 : 0) simply returns a verb, generated from the following lines
of source. : is an ordinary conjunction, so the phrase
[ , 4 : 0 ^: (*@#@])
is syntactically no different from
[ , ,:@|. ^: (*@#@])
ignoring the lines that follow.

With that finished, the ^:(*@#@]) is acting as you say it does only in
the most literal sense. ^: does use the result of *@#@] to indicate how
many times to run the explicit verb 4 : 0... . However, the result of
*@#@] is always either zero or one. ] returns the right argument, then #
gives its length, a nonnegative integer, then * gives the sign of its
length, which is zero if the length was zero and one if the length was
positive. In this use case (a fairly common J idiom), ^: is read as "if"
and merely uses the boolean on the right to determine WHETHER to run the
verb on the left--if that boolean is one, it runs it once, and if it iz
zero, it does not run the verb at all. ^:(*@#@]) here is not replacing
recursion, since the same recursive call to af is still there (in the
tacit version it is a call to $:).

For an empty right argument, 4 : 0 ^: (*@#@]) does nothing--it just
returns the right argument. Note that x f^:g y is equivalent to (x&f)^:g
y, so if (g y) is 0, then (x&f) is run zero times and y is returned,
with x discarded. The overall result is the same as ([ , ]) or simply ,
. It appends the left argument (a number) to the right (an empty list)
to give a list containing only the left argument, that is, num. If on
the other hand y is not empty, then the full verb is run.


&.> is indeed a form of mapping and is often nicknamed "each"--the
standard library supports this definition, so each is defined to be &.>
in a J session. However, the interesting bit is that neither &. not >
have anything to do with mapping. Map in J is so much a part of the
language that it is not a function--it is a basic language feature.
Every verb in J comes with a description of how it should map called its
rank. I recommend chapter 6 of J for C programmers as an excellent
introduction to rank:

http://jsoftware.com/help/jforc/loopless_code_i_verbs_have_r.htm

Now, the reason &.> serves as a mapping adverb is that the rank of > is
0 (because > can only operate meaningfully on a single box). If > is
presented with a list, it automatically loops over it. Now for &. . This
is one of the tricky composition conjunctions without colons in J, in
the same family as @ and & . These verbs create another verb which has
the same rank as their right arguments, but otherwise equivalent
function to the same conjunction with a colon. Thus f&.> is the same as
f&.:> (more on that verb in a second) but with rank zero. This means the
verb f&.:> will be applied with rank zero--that is, mapped over its
argument in order to apply to scalars.

&.: is simply defined: f&.:g is equivalent to (f^:_1)@:g@:f , where
f^:_1 is f's inverse (e.g. the inverse of %: is *:). The inverse of >
(open) is < (box), so f&.:> is equivalent to <@:f@:> . This verb opens
its input, then applies f, then closes (well, puts back in a box) the
result. To all appearances, f has just acted inside the box. In this
sense, &.: provides a sort of mapping as well, and in fact I prefer to
think of it as "on the". This means f&.:> is "f on the open"; apply f to
the thing inside the box. Likewise, +:&.:^. means to "double the
logarithm", which is the same as squaring. This is essentially the same
English semantic that the word "under" is getting at.

One final note is that the arguments to f&.> do not have to be boxed,
since > on a non-box scalar doesn't do anything. In this use case, f&.>
is equivalent to <@:f"0 , "apply f to the elements, boxing f's results."

Marshall

On Tue, Feb 12, 2013 at 10:32:11PM +0000, Alex Giannakopoulos wrote:
> Marshall Lochbaum wrote:
> > [this version of]
> > af uses a bit refactoring to avoid having to write the case where y is
> empty...
> 
> Marshall I almost missed your post, just read it...
> I really like the way you use ^:  as a replacement for recursion, but I had
> NO IDEA that the syntax you have used was remotely possible.
> Really need some more coherent documentation...
> First off, prepending a value before the  4:0  ???  Wow.  OK I'll let that
> one ride...
> Next,  ^: (* @ # @ ])  after the 4:0  ???  Brilliant, I love it, but where
> is it documented? (pretty please)
> So the above is acts as a loop, telling it how many to perform the "power"
> operator, yes?  With any thing executable permitted as argument?  Very
> powerful.
> 
> Which brings me to my main point:  I suppose all the scoping problems
> arose  because I couldn't figure out how to express the mapping function,
> remember...
>   (map (lambda (x) (af (/ num x) (remel divisors x)))
> Now if you look at Marshall's code,  and also Raul's pretty little
> execution using the fork so handily
>   ;num; (num&% af divisors&remel)  &. > uniquefactors
> 
> Both are making use in some form of this idiom, which I have called "verb
> under unbox".
> It seems to facilitate the mapping somehow, but I am not totally clear how
> this is happening.
> It does seem powerful though, I tried a few things interactively.
> Any pointers to documentation for this, or any words of wisdom?
> 
> ===
> 
> I must say, up to now J has often impressed me, surprised me, or caused a
> little smile to be raised.
> However, working through this example and the helpful suggestions, I can
> say this is the first time I actually actively enjoyed it, i.e. without a
> feeling of repidation!
> Shurely shum mishtake.
> ----------------------------------------------------------------------
> 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