Thanks to all the contributors to this thread, esp. Dan Bron.
The question was stimulated by the need for an adverb which takes a state m,
some new information a, and updates the state for some function f. This is
such a common problem that it could be a candidate for special code, a
special train, or a primitive. However the simple adverb upd below performs
very well.
The example using + as an update function was merely used for illustration
and is of no particular interest.
My experiments show Dan is right in saying that his gu does not generalise.
The simple case used for illustration but with modified a gave the timings
below which seem comparable with Dan's. The Quintana seq function provides
the key ideas. I believe the upd adverb provides the best current solution
and will try that out with a range of much more complex updating functions
which modify and
change the shape of multidimensional arrays. The solutions showed how
significant some aspects of coding style are for performance.
I was surprised by the range of numbers observed in repetitions of test
comparisons. Roger is quite right in saying we should not be too concerned
about relatively close performance figures. The best alternatives have
ranged over ratios from about 0.8 to 1.4 in repetitions of the same code for
small data sets. Clearly some careful statistical analysis would be
required to make confident assertions about performance differences in that
range.
The remainder of this post just summarises my comparisons using information
from the thread:
Note 'An update adverb'
The following adverb seems to do precisely what is required. It
uses ideas from several of the contributions. It uses suffix to exploit
calculation order
)
upd =: 1 : 0
:
|. u&.> /\. (|. <"_1 x),<y
)
NB. My original explicit form using control structures
recf=: 1 : 0
:
s =. y
r =. ,:s
for_i.
i. # x
do. s =. (i{x) u s
r =. r,s
end.
r
)
NB. the Quintana adverb
seq =: ((&.>) /) (@:((|.@:[) , (<@:]))) (>@:)
NB. Requires boxed items in left argument, hence
bron0 =: (+ seq f. ~ <"_1 )~
NB. Dan's second solution
ug =. 2 : '[: >@:({."1) (2&(u&.>/@:{. , }.)^:(1 < #)^:n @: (;
<"_1@:|.)~)'
bron1 =: + ug a: f.
NB. test utilities
ts =: 6!:2,7!:2
NB. string noun to array
stoa =: 3 : '> < ;._2 y'
compare =: 3 : 0
tlist =. stoa y
tims =. ts"1 tlist
t=. 0{"1 tims
m =. <./t
mi =. {. t i. m
(tlist,.' '),.' ',.": tims % "1 _ mi{tims
)
NB. Some tests
tests =: 0 : 0
a + upd m
a bron1 m
a [EMAIL PROTECTED] m
a + recf m
(<"0 a) + seq m
a bron0 m
)
NB. set nouns used as arguments
a =: +:>: i.500
m =: i. 2 2
compare tests
a + upd m 1 1
a bron1 m 144.77 21.9665
a [EMAIL PROTECTED] m 44.6661 0.469405
a + recf m 7.00055 0.113579
(<"0 a) + seq m 1.09524 0.26907
a bron0 m 1.07225 0.256915
a =: +: >: i.5000
compare tests
a + upd m 1 1
a bron1 m 1397.39 230.132
a [EMAIL PROTECTED] m 413.078 0.504823
a + recf m 6.18148 0.147159
(<"0 a) + seq m 1.04003 0.292697
a bron0 m 1.24939 0.291521
----------------------------------------------------------------------
For information about J forums see http://www.jsoftware.com/forums.htm