posting code before words,

reduce2 =: (((&.>)/)(>@:))(@:(<"_1@:[ , <@:]))
reduce3 =: ((((&.>)/)\.)(>@:))(@:(<"_1@:[ , <@:]))

Rdot =: 2 : '>@:(u&.>(n aar 5!:0))@:(<"_1@:[ , <@:])'
Rdot1 =: 2 : '>@:(u&.>(n aar 5!:0))@:(<"_1@:[ ,~ <@:])'

+ reduce2
>@:(+&.>/)@:(<"_1@:[ , <@:])

  + Rdot '/'
>@:(+&.>/)@:(<"_1@:[ , <@:])
    + reduce2
>@:(+&.>/)@:(<"_1@:[ , <@:])


+ reduce3
>@:(+&.>/\.)@:(<"_1@:[ , <@:])
    + Rdot '/\.'
>@:(+&.>/\.)@:(<"_1@:[ , <@:])

They are grouped by equivalent use.  Rdot1 reverses the order, but the only 
point of that seems to use (Rdot1 '/\') instead of Rdot '/\.'  Rdot1 '/\' could 
easily have a reduce4 adverb "predefinition".


The first thing you seem to be missing is using just / instead of /\.  Its a 
much more common use.  The next point is that Ndot1 probably should use /\ 
instead of /\.



1 2 + Rdot'/'~  1 2 3 4
11 12
1 2 + Rdot'/\.'~  1 2 3 4
11 12
10 11
8  9
5  6
1  2
    1 2 + Rdot1'/\'~  1 2 3 4
1  2
2  3
4  5
7  8
11 12

Rdot1 isn't absolutely necessary because (u Rdot'/\.'~ |.) will produce all of 
the same items in reverse order.



I don't think any other use case makes sense.  And I don't see a monadic 
application making sense either.  A monad would just use / or /\. or /\ 
instead.  The other model is:


reducE =: 1 : (':'; 'o=. x for_i. y do. o =. o u i end.')

which is the same as u~ reduce2~


The next point to notice is that the pattern (adverb) (>@:)(@:(<"_1@:[ , <@:])) 
imposes a guarantee on its u argument to produce a consistent shape.  In terms 
of looking for special code, there's just 2 necessary patterns on the left:  
(&.>/) or (&.>/\.)

bit 1:  if / and /\. are the only practical uses of this, then the result can 
always be unboxed at the end.  because u&.>/ started with 2 boxes on.  If u 
wants to add "extra" box layers, then u can do so, and it is up to u to figure 
out a consistent interpretation.  Usually pretty straightforward, but I'd need 
to see a use case for bit1 "auto-boxing" that is diffucult to do in u.

imo bit0 is not needed, but bit 2 is / or /\. .  A 3rd conceivable use that may 
be too esoteric is instead of (<"_1@:[ , <@]) : 
<@(<\@:[ ,. <@]) or 
<@(<\.@:[ ,. <@])


this builds boxes of lists of boxes, and is different from the "core pattern" I 
described above.  What seems to actually be the core pattern is the 2:

((&.>)/)(>@:)(list of boxings adverb) 

((&.>)/\.)(>@:)(list of boxings adverb)

where the "list of boxings adverb" could be limited to:

@:(u(<"_1@:) , v(<@:)) and maybe
@:(u(<"_1@:) ,~ v(<@:))

u and v can maybe even be limited to [ ]

there's a similar pattern in ,&< ... We know that both sides (and that count = 
2) were homogeneous prior to their boxings. In the case of


(>@:)(list of boxings adverb)

we know that u (to left of this adverb) must create a homogeneous result (or 
error).  In addition to fold/scan operations, u can also be something like x&{ 
leaf.

in the context of fold/scan,

fold(initialstate, array, function) the u and v in the above pattern are 
initialstate and array.  As you know, the optimization potential is that they 
never have to be boxed.  The point of the rambling, is that there is a more 
general pattern in (>@:)(@:(boxing of 2 variables verb))

I'd recommend against putting an extra function parameter for twiddling 
(reversing) x or y.  I think its better for user to pretweak them, or they can 
write/use a modifier that adds the functionality.


about v,

your implementation I think means that it can only be a noun, and so I think 
the result would always have a compatible shape, and so no need to box it.  An 
alternative to a v parameter to function is special code for

(v {"_1 (bound N.)), and then consider {. {: # without the "_1 restriction.
(v {"1 _1 L:0 _ (bound N.)) might also solve the box/no box bit.


A problem with having a v embedded parameter in the modifier is that it may be 
a function of the data.  90%+ of the time, you will want all of it.  A 
selection formula might be (<@i.@#"_1 {"1 _1 leaf ]) even though the same 
(selection vector) value would most likely be generated for all items.  
Basically having a v parameter embedded in the modifier would mean instead of

v&{&.> u&.>/\. (<"_1 y) , <x

have

v&.> u&.>/\. (<"_1 y) , <x

This would let ] be a simple v parameter to get the full results.  In terms of 
optimization, you may not need to care whether # or {. is used.  The shape is 
not guaranteed linear either, so v may be much more complex than a noun 
argument to { .

The v parameter is obviously not needed for / version.  Seperate functions are 
good if you accept that both are useful.  But you can also look at it as 3 
function patterns

u  (((&.>)/)(>@:))(@:(boxing of 2 variables))  (reduce2)
u  reduce3(v&>@:)  NB. /\. version

u   reduce3(v&.>@:)

But for the latter 2, it may be better and simpler to do it through special 
code detection?  If you call either

(u reduce3)(v&.>@:)
or

v&.>@:(u reduce3)

then v can get "optimized within the main loop"


----- Original Message -----
From: Henry Rich <henryhr...@gmail.com>
To: Source forum <sou...@jsoftware.com>
Sent: Tuesday, August 2, 2016 8:43 PM
Subject: [Jsource] Proposal for new looping primitive x N.

As Marshall once noted, the biggest deficiency in J is looping over an 
array when you need a result from each iteration, and the calculation 
requires an initial value and some internal state. Your code looks like

result {"_1 f/\. array , initialstate

where each execution of f produces a result value plus the internal 
state to feed into the next iteration.  The problems are:
* the result is the entire array of internal state, which is more, maybe 
MUCH more than you need, since the final result needs only a portion of 
the state
* The state is probably not commensurate with a item of the array, so 
you end up boxing the initial state and the array items, which is very 
wasteful.

I propose a new primitive, call it N. (for insert).  N. is an adverb 
that produces a conjunction.  In (x N.), x specifies options for the 
processing, much as the right operand of u;.n does.

Definition:

[x] u (n N.) v y

where

u is the function to be applied
v is the selector to apply to the result of each execution of u, to 
produce the part saved in the final result
x is the (optional) initial value (if omitted, f is applied first 
between the last 2 items of y)
y is the argument array
n selects from several variants:
  bit 0=0  operation goes back to front
  bit 0=1  operation goes front to back, as if using &.|.
  bit 1=0  selected result from each iteration becomes one item of result
  bit 1=1  selected result from each iteration is boxed before becoming 
an item of result

Formal definition:
Ndot0 =: 2 : 0
v&{@> u&.>/\. (<"_1 y)
:
v&{@> u&.>/\. (<"_1 y) , <x
)
Ndot1 =: 2 : 0
v&{@> u&.>/\.&.|. (<"_1 y)
:
v&{@> u&.>/\.&.|. (<"_1 y) ,~ <x
)
Ndot2 =: 2 : 0
v&{&.> u&.>/\. (<"_1 y)
:
v&{&.> u&.>/\. (<"_1 y) , <x
)
Ndot3 =: 2 : 0
v&{&.> u&.>/\.&.|. (<"_1 y)
:
v&{&.> u&.>/\.&.|. (<"_1 y) ,~ <x
)

Ndot =: 1 : 0
assert. m e. i. 4
select. m
case. 0 do. Ndot0
case. 1 do. Ndot1
case. 2 do. Ndot2
case. 3 do. Ndot3
end.
)


I look forward to criticism of this proposal.

Henry Rich

----------------------------------------------------------------------
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