Thanks for the ideas, guys. New proposal below.
Let's keep the definition in explicit form, so that we can have more
readers involved.
u/\ has no place here: it requires u to be associative.
Definition:
[x] u F. v y
where
u is a verb to be applied repeatedly
v is a verb to apply to the result of each execution of u, to
produce the part saved in the final result, or [: to get the full result of
only the final execution of u
x is the (optional) initial value (if omitted, u is applied first
between the last 2 items of y)
y is the argument array
F. applies between items of y starting at the end, F: starts at the front. In
either case the x argument to u is the next item of y, and the y argument to u
is the initial value/state from previous execution.
Formal definition:
Fdot =: 2 : 0
cap =. [:
if. 'v' -:&(5!:1)&< 'cap' do.
u&:>/ (<"_1 y)
else.
v@> u&.>/\. (<"_1 y)
end.
:
cap =. [:
if. 'v' -:&(5!:1)&< 'cap' do.
u&:>/ (<"_1 y) , <x
else.
v@> u&.>/\. (<"_1 y) , <x
end.
)
Fcolon =: 2 : 0
cap =. [:
if. 'v' -:&(5!:1)&< 'cap' do.
u&:>/@|. (<"_1 y)
else.
v@> u&.>/\.&.|. (<"_1 y)
end.
:
cap =. [:
if. 'v' -:&(5!:1)&< 'cap' do.
u&:>/ (|. <"_1 y) , <x
else.
v@> u&.>/\.&.|. (<"_1 y) ,~ <x
end.
)
Example:
f =. ((i. , ]) >./)@:(({:@])`({.@])`[})
this takes x=list and y=index,value. It stores value into x at location index,
and returns the index and value of the largest atom in the resulting list.
(Yeah, it's a punk function.)
0 0 f Fdot (1&{) a =: 20 20 ?@$ 10099 99 99 99 99 99 99 99 99 99 99 99 99
99 99 99 99 99 99 96 0
The result is the list of the indexes that were encountered.
0 0 f Fdot [: a =: 20 20 ?@$ 100
2 99
The result is the result of the last execution only.
Henry Rich
On 8/3/2016 4:11 AM, 'Pascal Jasmin' via Source wrote:
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
----------------------------------------------------------------------
For information about J forums see http://www.jsoftware.com/forums.htm