Ok.. I have manage to convince myself that my earlier "cheating
hypothesis" was utterly false. (And, Jose has stated something
similar.)
One trick is to realize that most of the adverbs used in building hg
are not used directly, but instead are used for their atomic
representations. They are sub-trees being used to build up to the
whole.
Another trick is to realize that you do not actually need to fix their
definitions (using f.) for hg to work. There are production advantages
to fixed definitions (fixing avoids name collision issues), but when
trying to understand the code, that can get in the way.
But the big issue, for me, is understanding the instances of what we
might call "gerund execution adverbs". These are adverbs along the
lines of `u`v`w`(`:6) -- in other words, these are partially complete
gerunds which grab onto a verb (or another gerund, but usually we are
turning a verb into a gerund for this) and then executes the result as
a train.
Because these are fundamental to what's going on here, I think each of
these "gerund execution adverbs" deserves a descriptive name (at least
in the context of presentation - for production contexts such names
are not necessary). [But I'm not going to do that here, in this
message. I need to think more about that...]
So... how many "gerund execution adverbs" are contained in hg? Well,
we can look for instances of the body of the a5 adverb:
a5
`:6
... and, when we do that, we see perhaps 7 "gerund execution adverbs".
+/-:&(>ar'a5')S:(<:L.ar'a5')ar'hg'
7
(And, all but one of those is initially in gerund form. Only the top
level `:6 is initially an adverb.)
Still... let's run through what we see:
NB. a1 -------------------------------------
a1=: (@:[) ((<'&')`) (`:6)
When we display that, it looks like this (if you have been studying
the code, a lot of this will be familiar):
((@:[)(&`))(`:6)
And, when we test out how it works, we see this:
<a1
&(<@:[)
In other words, its result is an adverb.
It is not immediately clear the purpose for forming &(<@:[) instead of
just &< but changing the definition to ((<'&')`) (`:6) breaks hg (we
get a domain error trying to execute &_ which suggests that we might
be trying to extract the a1 argument from a containing gerund).
NB. a2 -------------------------------------
a2=: (`(<(":0);_)) (`:6)
a2
(`_)(`:6)
Basically, here, it looks like we are passing a dummy argument to
[presumably] a verb.
NB. av -------------------------------------
av=: ((ar'a0')`) (`(ar'a1')) (`(ar'a2') ) (`:6)
a0 was `''
And, when we look at AV, we see three instances of (`:6) - the one
which is included here directly, as well as the instances from a1 and
a2. So, looking at the test case (1 2 3 *: av), the first (outermost)
`:6 is executing the gerund
(ar'a0)`*:`(ar'a1)`(ar'a2')
To confirm that things work this way:
1 2 3 (*: av)
1 4 9
In other words the final adverb argument is not being consumed at this
stage. (That said, note that if you try to use J's trace facility to
explore even this much, it does not work, because J's current
implementation of linear representation does not properly handle the
gerunds used here.)
But, when we look at (*: av) we see that there's only one (`:6) remaining:
*:av
((`'')(&(*:@:[)))((`_)(`:6))
So, for some reason, a1's `:6 triggered - and, thinking about this,
when *: gets incorporated at the top level, the a1 gerund winds up
being complete (a1 is now a gerund with `:6 after it rather than an
adverb). So... this is an important concept: completed gerunds in a
`:6 train are evaluated right then and there, while incomplete "gerund
adverbs" wait for their turn.
NB. a3 -------------------------------------
aw=: < o ((0;1;0)&{::) NB. Fetching the atomic representation
a3=: (@: (aw f.)) ('av'f.)
Note: aw is a verb, not an adverb.
Note: a3 has `:6 because av has `:6 (actually, av has three of them).
Note: this is just a template for use in constructing a gerund.
Note: the verb which will be consumed by this instance of av is going
to be verb@:aw
We'll come back to this in a little bit.
NB. a6 -------------------------------------
a4=: "_
a6=: ((( ar'a4') ; ] ; ( ar'a3')"_) ('av'f.)) (`:6)
This is another "gerund template" - hg uses (ar'a6') and a6 does not
execute directly.
Also, while we're here, ...
a5=: `:6
Anyways... we can use a name in place of the ar of that name, and (as
long as this does not cause name collisions), it should execute just
the same. So, let's do that, bringing in the definition of hg also:
av=: ((<'a0')`) (`(<'a1')) (`(<'a2')) (`:6)
a3=: (@:aw)av
a6=: (('a4' ; ] ; 'a3'"_) av) (`:6)
hg=: `((<'a6')`(<'a5')) (`:6)
Now... if we take the test case
1 2 3 ((<'*:') ; ]) hg
1 4 9
And we strip out the numeric argument, and substitute in the
definition of hg (in parens), we can get a rough idea of how things
are structured:
(((<'*:') ; ]) (`((<'a6')`(<'a5')) (`:6)))
(a4((a0(&(((<'*:') ; ])@:aw@:[)))a2))a5
(And if we take out that top level (`:6) we can see how we got to this
point. Basically it's just the gerund formed from that test verb
argument, a6 and a5).
And, to verify that we are still on the right track here:
1 2 3 (((<'*:') ; ]) (`((<'a6')`(<'a5')) (`:6)))
1 4 9
So...
a4 is going to combine with 1 2 3 to form the verb 1 2 3"_ and...
actually, let's just try this:
1 2 3 (a4((a0(&(((<'*:') ; ])@:aw@:[)))a2))a5
1 4 9
(1 2 3"_((a0(&(((<'*:') ; ])@:aw@:[)))a2))a5
1 4 9
baby steps... but now we can strip out the a5 (which is another `:6)
to look at the gerund being formed:
1 2 3"_((a0(&(((<'*:') ; ])@:aw@:[)))a2)
┌────┬─────────┐
│┌──┐│┌─┬─────┐│
││*:│││0│1 2 3││
│└──┘│└─┴─────┘│
└────┴─────────┘
And we can strip out the a2 to see another intermediate stage:
1 2 3"_(a0(&(((<'*:') ; ])@:aw@:[)))
(,<(<,'"'),<(<(,'0');1 2 3),<(,'0');_)&(((<'*:') ; ])@:aw@:[)
And, at this point, we're past the stages where J's linear
representations are invalid, so we can work with what we are seeing
here:
((,<(<,'"'),<(<(,'0');1 2 3),<(,'0');_)&(((<'*:') ; ])@:aw@:[))a2
┌────┬─────────┐
│┌──┐│┌─┬─────┐│
││*:│││0│1 2 3││
│└──┘│└─┴─────┘│
└────┴─────────┘
((,<(<,'"'),<(<(,'0');1 2 3),<(,'0');_)&(((<'*:') ; ])@:aw@:[))a2 a5
1 4 9
Well.. mostly. Remember that a2 is a gerund evaluation adverb, and
it's linear rep is invalid, and to see what a2 is going to do with
this we'll have to go back to a2's definition and strip out the `:6
((,<(<,'"'),<(<(,'0');1 2 3),<(,'0');_)&(((<'*:') ; ])@:aw@:[))(`(<(":0);_))
The resulting gerund is a bit big but basically it's doing this:
((,<(<,'"'),<(<(,'0');1 2 3),<(,'0');_)&(((<'*:') ; ])@:aw@:[))_
┌────┬─────────┐
│┌──┐│┌─┬─────┐│
││*:│││0│1 2 3││
│└──┘│└─┴─────┘│
└────┴─────────┘
So... how?
Well, at the top level, this is an & expression - the left argument to
& is a gerund representing 1 2 3"_ and the right argument to & is a
gerund representing ((<'*:') ; ])@:aw@:[
But... the & here is "bind" (not compose), because gerunds are nouns.
So when _ is passed in as an argument, it gets ignored, and what we
are really doing is:
((<'*:') ; ])@:aw (1 2 3"_)`''
┌────┬─────────┐
│┌──┐│┌─┬─────┐│
││*:│││0│1 2 3││
│└──┘│└─┴─────┘│
└────┴─────────┘
aw pulls the noun out of the gerund for 1 2 3"_ and after that our
test verb runs against it.
Note that this also means that if our argument had been a verb instead
of 1 2 3, in this context we would have been using a gerund
representing that verb.
(And, as an aside, that & came from a1 via av. I'd explore that issue
here, but I think I have rambled on long enough for now.)
If anyone has managed to follow this up to this point, thanks for the
interest - and I'd like to challenge you to cast the useful bits of
what I have said here into a more digestible format.
Thanks,
--
Raul
Oh, p.s. - my hacked up version of Jose's code, with names handled
differently (not for production):
ar=: 5!:1@:<
a0=: `''
a1=: (@:[) ((<'&')`) (`:6)
a2=: (`(<(":0);_)) (`:6)
av=: ((<'a0')`) (`(<'a1')) (`(<'a2')) (`:6)
NB. Adverbing a monadic verb (adv)
assert 1 4 9 -: 1 2 3 *: av
aw=: < @: ((0;1;0)&{::) NB. Fetching the atomic representation
a3=: (@:aw)av
a4=: "_
a5=: `:6
a6=: (('a4' ; ] ; 'a3'"_) av) (`:6)
hg=: `((<'a6')`(<'a5')) (`:6)
assert 1 4 9 -: 1 2 3 ((<'*:') ; ]) hg
On Sun, Oct 22, 2017 at 2:22 PM, Raul Miller <[email protected]> wrote:
> Thinking about this further - I am not sure that a3 (and, thus a6)
> work quite like I had previously suggested. Or, maybe they do, but...
>
> Ok, let's start over:
>
...
> On Sat, Oct 21, 2017 at 4:43 PM, Erling Hellenäs
> <[email protected]> wrote:
>> Hi all !
>>
>> I do my best to understand this. Like Raul I name things. I created some
>> explanations. However, I didn't manage to understand how a3 and a6 works.
>> Maybe someone can help?
>>
>> My project:
>>
>> 9!:14''
>>
>> o=: @:
>>
>> ar=: 5!:1 @:<
>>
>> ar 'o'
>>
>> emptyGerund=: `''
>>
>> emptyGerund
>>
>> DoOnLeftArgAdverb=: (@:[) ((<'&')`) (`:6)
>>
>> +/ DoOnLeftArgAdverb
>>
>> InfinityAdverb=: (`(<(":0);_)) (`:6)
>>
>> %InfinityAdverb
>>
>> ExecuteDoOnLeftArgAdverbWithLeftArg=: ((ar'emptyGerund')`)
>> (`(ar'DoOnLeftArgAdverb')) (`(ar'InfinityAdverb') ) (`:6)
>>
>> 1 2 3 *: ExecuteDoOnLeftArgAdverbWithLeftArg
>>
>> FetchAtomicRepr=: < o ((0;1;0)&{::) NB. Fetching the atomic representation
>>
>> br=: 5!:2@:<
>>
>> f=: -@:-@-
>>
>> br 'f'
>>
>> FetchAtomicRepr br 'f'
>>
>> a3=: (@: (FetchAtomicRepr f.)) ('ExecuteDoOnLeftArgAdverbWithLeftArg' f.)
>>
>> RankInfinity=: "_
>>
>> +RankInfinity
>>
>> EvokeGerundTrain=: `:6
>>
>> (+/)`%`# EvokeGerundTrain 1 2 3
>>
>> a6=: ((( ar'RankInfinity') ; ] ; ( ar'a3')"_)
>> ('ExecuteDoOnLeftArgAdverbWithLeftArg'f.)) (`:6)
>>
>> hg=: `((ar'a6')`(ar'EvokeGerundTrain')) (`:6)
>>
>> 1 2 3 ((<'*:') ; ]) hg
>>
>> an=: <@:((,'0') (,&<) ]) NB. Atomizing words (monadic verb)
>>
>> an +`-`*`%
>>
>> AdverbToPackvuGerundWithAt=:< o ((('@:') ; < o |.)) o (('';1)&{::) hg
>>
>> (-`<) AdverbToPackvuGerundWithAt
>>
>> 3 (-`<) AdverbToPackvuGerundWithAt 2
>>
>> AdverbToPackReverseOrderGerundWithAt=: ([ , (<'@:') , ])/o |. o
>> (('';1)&{::)hg
>>
>> *:`-`%`+: AdverbToPackReverseOrderGerundWithAt
>>
>> *:`-`%`+: AdverbToPackReverseOrderGerundWithAt 5
>>
>> ConjunctionToExecuteVWithArgumentU=: ((an f.hg) (` (|. o ((('';1)&{::))hg))
>> (an f.hg))
>>
>> 1 2 3 ConjunctionToExecuteVWithArgumentU (+/)
>>
>>
>> The printout:
>>
>>
>> 9!:14''
>> j806/j64/windows/beta/BEST/Jx-patches/2017-10-06T14:44:47
>> o=: @:
>> ar=: 5!:1 @:<
>> ar 'o'
>> ┌──┐
>> │@:│
>> └──┘
>> emptyGerund=: `''
>> emptyGerund
>> `''
>> DoOnLeftArgAdverb=: (@:[) ((<'&')`) (`:6)
>> +/ DoOnLeftArgAdverb
>> &(+/@:[)
>> InfinityAdverb=: (`(<(":0);_)) (`:6)
>> %InfinityAdverb
>> 0
>> ExecuteDoOnLeftArgAdverbWithLeftArg=: ((ar'emptyGerund')`)
>> (`(ar'DoOnLeftArgAdverb')) (`(ar'InfinityAdverb') ) (`:6)
>> 1 2 3 *: ExecuteDoOnLeftArgAdverbWithLeftArg
>> 1 4 9
>> FetchAtomicRepr=: < o ((0;1;0)&{::) NB. Fetching the atomic
>> representation
>> br=: 5!:2@:<
>> f=: -@:-@-
>> br 'f'
>> ┌────────┬─┬─┐
>> │┌─┬──┬─┐│@│-│
>> ││-│@:│-││ │ │
>> │└─┴──┴─┘│ │ │
>> └────────┴─┴─┘
>> FetchAtomicRepr br 'f'
>> ┌─┐
>> │@│
>> └─┘
>> a3=: (@: (FetchAtomicRepr f.)) ('ExecuteDoOnLeftArgAdverbWithLeftArg' f.)
>> RankInfinity=: "_
>> +RankInfinity
>> +"_
>> EvokeGerundTrain=: `:6
>> (+/)`%`# EvokeGerundTrain 1 2 3
>> 2
>> a6=: ((( ar'RankInfinity') ; ] ; ( ar'a3')"_)
>> ('ExecuteDoOnLeftArgAdverbWithLeftArg'f.)) (`:6)
>> hg=: `((ar'a6')`(ar'EvokeGerundTrain')) (`:6)
>> 1 2 3 ((<'*:') ; ]) hg
>> 1 4 9
>> an=: <@:((,'0') (,&<) ]) NB. Atomizing words (monadic verb)
>> an +`-`*`%
>> ┌─────────────┐
>> │┌─┬─────────┐│
>> ││0│┌─┬─┬─┬─┐││
>> ││ ││+│-│*│%│││
>> ││ │└─┴─┴─┴─┘││
>> │└─┴─────────┘│
>> └─────────────┘
>> AdverbToPackvuGerundWithAt=:< o ((('@:') ; < o |.)) o (('';1)&{::) hg
>> (-`<) AdverbToPackvuGerundWithAt
>> <@:-
>> 3 (-`<) AdverbToPackvuGerundWithAt 2
>> ┌─┐
>> │1│
>> └─┘
>> AdverbToPackReverseOrderGerundWithAt=: ([ , (<'@:') , ])/o |. o
>> (('';1)&{::)hg
>> *:`-`%`+: AdverbToPackReverseOrderGerundWithAt
>> +:@:%@:-@:*:
>> *:`-`%`+: AdverbToPackReverseOrderGerundWithAt 5
>> _0.08
>> ConjunctionToExecuteVWithArgumentU=: ((an f.hg) (` (|. o
>> ((('';1)&{::))hg)) (an f.hg))
>> 1 2 3 ConjunctionToExecuteVWithArgumentU (+/)
>> 6
>>
>>
>> Cheers,
>>
>>
>> Erling Hellenäs
>>
>>
>>
>> On 2017-10-21 21:52, Erling Hellenäs wrote:
>>>
>>> My a2 name :)
>>>
>>> InfinityAdverb=: (`(<(":0);_)) (`:6)
>>>
>>> %InfinityAdverb
>>>
>>> 0
>>>
>>> /Erling
>>>
>>>
>>> On 2017-10-21 20:45, Raul Miller wrote:
>>>>
>>>> Here's one issue:
>>>>
>>>> 1 2 3 *: av
>>>> 1 4 9
>>>> load'debug/dissect'
>>>> dissect '1 2 3 *: av'
>>>> Syntax error: invalid sequence Noun Verb
>>>> Error snippet: 1 2 3 *: av
>>>>
>>>> But that's not a syntax error.
>>>>
>>>> And, for reference, here are two distinct implementations of av. First
>>>> an explicit approximation:
>>>>
>>>> LR=: 5!:5@<
>>>> LRA=:1 :0
>>>> (LR 'u'),' m'
>>>> )
>>>> AV=:1 :0
>>>> 1 :(u LRA)
>>>> )
>>>>
>>>> Second, a restatement of Jose's code (but with a few different names):
>>>>
>>>> ar=: 5!:1@:<
>>>> bGerund=: `''
>>>> Compose=: (@:[) ((<'&')`) (`:6)
>>>> a2=: (`(<(":0);_)) (`:6)
>>>> av=: ((ar'bGerund')`) (`(ar'Compose')) (`(ar'a2') ) (`:6)
>>>>
>>>> I am still trying to think up a good name for a2 - roughly speaking
>>>> it's a placeholder which winds up being ignored in the result of the
>>>> Compose verb. I was interested in what dissect had to show me about
>>>> the evaluation process here, but that's not relevant to this problem,
>>>> which you can see by replacing av with AV.
>>>>
>>>> #################################################
>>>>
>>>> That said, it's perhaps also interesting that trace is also buggy:
>>>>
>>>> trace '1 2 3 *: AV'
>>>> --------------- 5 Fork -------
>>>> 1 2 3
>>>> *:
>>>> AV
>>>> 1 2 3 *: AV
>>>> ==============================
>>>>
>>>> The problem seems to be an incomplete handling of locales. While trace
>>>> executes in the jtrace locale, the sentence it is executing comes from
>>>> a different locale (typically the base locale). This means that 4!:0
>>>> in movet treats AV as an undefined name (and, thus, a verb).
>>>>
>>>> A quick and dirty fix would be to add
>>>> coinsert 'base'
>>>> to the top of addons/general/misc/trace.ijs (right under
>>>> cocurrent'jtrace').
>>>>
>>>> This has two flaws but it's still better than nothing:
>>>>
>>>> (1) it won't work when trying to trace in another locale,
>>>> (2) it will still shadow base names with jtrace names.
>>>>
>>>> Problem 2 could be avoided by replacing uses of 4!:0 and ". with names
>>>> which are defined in the z locale (nc and do), and suffixing them with
>>>> locale references. Still not perfect (because relies on z), but
>>>> implementations which shadow z are already dubious.
>>>>
>>>> I have no idea about problem 1 - maybe documentation would be the best
>>>> solution there. (Another possibility would be to add feature to the
>>>> locale support, to detect locale of the caller - but I can't think of
>>>> any non-obfuscation uses of that feature. And, yes, ... I guess I
>>>> might have to include "making jtrace automatically work regardless of
>>>> the current locale of the global session" as obfuscation. I am not
>>>> sure about that...)
>>>>
>>>> #################################################
>>>>
>>>> Anyways, since this is getting long, I have reported two problems here:
>>>>
>>>> (1) An invalid "syntax error" in dissect
>>>> (2) A serious name resolution problem in trace
>>>>
>>>> Thanks,
>>>>
>>>
>>> ----------------------------------------------------------------------
>>> For information about J forums see http://www.jsoftware.com/forums.htm
>>
>>
>>
>> ----------------------------------------------------------------------
>> For information about J forums see http://www.jsoftware.com/forums.htm
----------------------------------------------------------------------
For information about J forums see http://www.jsoftware.com/forums.htm