Sorry, I thought you were combining two approaches rather than presenting an 
alternative, and misread your proposal as allocating a whole new array on each 
iteration (mixing map and concatenation).

map is just fine, it's growth-by-concatenation that's the bad idea (as your 
timing test shows).

--Tim

On Friday, October 17, 2014 12:23:59 PM Tamas Papp wrote:
> What does "better" mean in this context, style or speed? For me map is
> better style (but that is of course subjective), but it also appears to
> be in the range of push! with respect to speed within measurement noise
> and allocates less (unless I am using push! incorrectly):
> 
> function give_funs1(n)
>   funs = []
>   for i in 1:n
>     funs = [funs, () -> i]
>   end
>   funs
> end
> 
> function give_funs2(n)
>   map((i) -> (() -> i), 1:n)
> end
> 
> function give_funs3(n)
>   result = Any[]
>   for i in 1:n
>     push!(result, () -> i)
>   end
>   result
> end
> 
> @time give_funs1(100000);
> @time give_funs2(100000);
> @time give_funs3(100000);
> 
> julia> @time give_funs1(100000);
> elapsed time: 31.811824021 seconds (40187982672 bytes allocated, 69.98% gc
> time)
> 
> julia> @time give_funs2(100000);
> elapsed time: 0.018686499 seconds (7992040 bytes allocated)
> 
> julia> @time give_funs3(100000);
> elapsed time: 0.030754734 seconds (10890064 bytes allocated, 82.97% gc time)
> 
> Note that gc of course is idiosyncratic in this case and dominates the
> measurement, and can occur for both 2 and 3.
> 
> Best,
> 
> Tamas
> 
> On Fri, Oct 17 2014, Tim Holy wrote:
> > As for the accumulation, far better than either is to use push!.
> > 
> > --Tim
> > 
> > On Friday, October 17, 2014 09:48:49 AM Tamas Papp wrote:
> >> I am not sure if I understood the question, but if the purpose is to
> >> store the function you created before accumulating it in a list, you
> >> could use
> >> 
> >> function give_funs()
> >> 
> >>   funs = []
> >>   for i in 1:5
> >>   
> >>     newfun = () -> i
> >>     funs = [funs, newfun]
> >>   
> >>   end
> >>   funs
> >> 
> >> end
> >> 
> >> Also, accumulating the vector by concatenation may not be idiomatic in
> >> this case. A more compact way would be
> >> 
> >> function give_funs()
> >> 
> >>   map((i) -> (() -> i), 1:5)
> >> 
> >> end
> >> 
> >> Best,
> >> 
> >> Tamas
> >> 
> >> On Thu, Oct 16 2014, Evan Pu <[email protected]> wrote:
> >> > Consider this code:
> >> > 
> >> > function give_funs()
> >> > 
> >> >   funs = []
> >> >   for i in 1:5
> >> >   
> >> >     function newfun()
> >> >     
> >> >       i
> >> >     
> >> >     end
> >> >     funs = [funs, newfun]
> >> >   
> >> >   end
> >> >   funs
> >> > 
> >> > end
> >> > 
> >> > The intention is to create 5 functions and store them in a list called
> >> > "funs".
> >> > All the functions take no argument, and when the ith function is
> >> > called,
> >> > it
> >> > returns i.
> >> > 
> >> > However, when run...
> >> > funs1 = give_funs()
> >> > funs1[1]() # this should give 1, but instead it gives 5
> >> > funs1[2]() # this should give 2, but instead it gives 5 as well
> >> > 
> >> > This is problem goes away if I stop naming the function as "newfun" but
> >> > instead use ananymous functions like so:
> >> > funs = [funs, () -> i]
> >> > however in real code I would like to give it a name so to be more clear
> >> > what the function is suppose to compute
> >> > 
> >> > It seems that these functions are bound by their function names, and
> >> > since
> >> > they're all named "newfun", the compiler over-write the old ones
> >> > defined
> >> > earlier.
> >> > 
> >> > How should this be resolved?

Reply via email to