jw3126 / Setfield.jl

Update deeply nested immutable structs.
Other
167 stars 17 forks source link

How to operate on vectors? #82

Closed tamasgal closed 5 years ago

tamasgal commented 5 years ago

I need to create copies of Vectors of immutable structs and tried to use map and @set with lambdas but it does not seem to work. However, creating a named function and passing it to map works:

using Setfield

struct Foo
    a
    b
end

foos = [Foo(rand(2)...) for i in 1:10]
altered_foos = map(e -> @set e.a += 1, foos)

which gives

MethodError: no method matching (::getfield(Main, Symbol("##347#348")))()
Closest candidates are:
  #347(!Matched::Any) at In[155]:7

Stacktrace:
 [1] map(::getfield(Main, Symbol("##347#348"))) at ./abstractarray.jl:2154
 [2] top-level scope at In[155]:7

So I was wondering how to do such vectorised operations?

This one works fine but I'd like to be able to do it without declaring a new function:

alter(e) = @set e.a += 1
map(alter, foos)

giving

10-element Array{Foo,1}:
 Foo(1.6015062401479545, 0.7001473281193633) 
 Foo(1.8728986454851777, 0.7609571765576351) 
 Foo(1.9593289800175049, 0.16995722599790009)
 Foo(1.7336119886462003, 0.8280281391124831) 
 Foo(1.9496982610211004, 0.3067274287439916) 
 Foo(1.0507637853462313, 0.9850799605321925) 
 Foo(1.9948118412292621, 0.1927429759118071) 
 Foo(1.397385808962995, 0.6112439177338842)  
 Foo(1.526247545899711, 0.27195395425248403) 
 Foo(1.877792521332768, 0.18889451257875534) 
jw3126 commented 5 years ago

This has nothing to do with @set or vectors, but with the parser. Just add some parens to make clear that foos is not an argument of the macro:

julia> altered_foos = map(e -> @set(e.a += 1), foos)
10-element Array{Foo,1}:
 Foo(1.6176958141023454, 0.3878116659353461) 
 Foo(1.5538936455530625, 0.2978874484594669) 
 Foo(1.021292203475409, 0.713884428905962)   
 Foo(1.4367673447106937, 0.8425043609446288) 
 Foo(1.1680935435405346, 0.47500893921412546)
 Foo(1.4694724149539797, 0.10487020499341693)
 Foo(1.8587307634157302, 0.5589899822874727) 
 Foo(1.3008984188881783, 0.8409580699510877) 
 Foo(1.6341708040433869, 0.9045141471856328) 
 Foo(1.321901352224907, 0.9466203120046159)  
tamasgal commented 5 years ago

Ah thanks ;) and sorry for the noise!

jw3126 commented 5 years ago

Your welcome. It's a common gotcha when using macros in the middle of a line. I also fall for it every now and then.