Actually, a slightly better form might be:

@generated function modify_field{g}(x, ::Type{Val{g}}, v)
    F = fieldnames(x)
    D = Any[:(x.$f) for f in F]
    D[F .== g] = :v
    Expr(:call, :call, x, D...)
end

This avoids the need to call symbol (I don't know if this could be a 
problem, but it does seem safer).

On Tuesday, 2 June 2015 10:00:39 UTC+1, Simon Byrne wrote:
>
> You could use the eltype function, but having thought more about it, I 
> think it might be easier (and more general) if you operate on the objects 
> instead of the container. Something like:
>
> @generated function modify_field{g}(x, ::Type{Val{g}}, v)
>     F = fieldnames(x)
>     D = Any[:(x.$f) for f in F]
>     D[F .== g] = :v
>     Expr(:call, symbol(x), D...)
> end
>
> macro modify_field!(ex)
>     ex.head == :(=) && ex.args[1].head == :(.) || error("Invalid usage of 
> @modify_field! macro")
>     lhs, v = ex.args
>     x, g = lhs.args
>     :($(esc(x)) = modify_field($(esc(x)), Val{$g}, $v))
> end
>
> Note that modify_field doesn't actually change anything (it creates a new 
> instance), the re-assignment is done by the macro, e.g.:        
>
> immutable Immut
>     intfld::Int
>     isadded::Bool
> end
>
> Y = [Immut(i,false) for i = 1:10]
> for i = 1:5
>     @modify_field! Y[i].isadded = true
> end
> Y
>
> This also allows you to use it without an array
>
> y = Immut(1,false)
> @modify_field! y.isadded = true
> y
>
> That said, I haven't done any profiling to compare speed.
>
> -Simon
>
>
> On Tuesday, 2 June 2015 03:24:51 UTC+1, [email protected] wrote:
>>
>> Simon,
>>
>> Sorry to follow up so quickly on my own post, but I'm not able to figure 
>> out how to use generated functions for this purpose.  Consider:
>>
>>    modifyField!(a,k,Val{:isadded}, true)
>>
>> The generated-function routine modifyField! needs to know the base type 
>> of a.  In other words, there exists some base type, say Immut, such that a 
>> is an array of Immut's or a dict of Immut's or some other container, and 
>> :isadded is one of the fields of Immut.  (The generator function 
>> modifyField! needs to know about Immut in order to enumerate all of its 
>> other  fields).
>>
>> I don't see how to determine this base type within the generator.  Say, 
>> for example, that the type of a is Array{Immut,1}.  I was hoping that one 
>> of the following introspective calls would work:
>>
>>     methodswith(typeof(a), setindex!, false)
>>     methodswith(typeof(a), setindex!, true)
>>
>> but neither worked -- the first did not return any methods, whereas the 
>> second returned a huge list of methods without any clear winner.  Another 
>> possibility might be:
>>
>>     code_typed(getindex, (typeof(a), typeof(k))
>>
>> but I didn't know how to analyze this output for the general case; it 
>> seems like determining the return value of getindex is as hard as the 
>> halting problem!
>>
>> Thanks,
>> Steve
>>
>>
>> On Monday, June 1, 2015 at 5:57:19 PM UTC-4, Simon Byrne wrote:
>>>
>>> That's some impressive metaprogramming. In v0.4, you should be able to 
>>> do this without the "maker" functions, using generated functions
>>>
>>> http://julia.readthedocs.org/en/latest/manual/metaprogramming/#generated-functions
>>>
>>> As far as an interface goes, I would suggest a macro, e.g. so that the 
>>> user could write something like
>>>
>>> @modify! a[i].field = new
>>>
>>>
>>> On Monday, 1 June 2015 03:09:29 UTC+1, [email protected] wrote:
>>>>
>>>> Following up on an earlier discussion that I started in this newsgroup, 
>>>> I have written a small package that provides a routine to modify a field 
>>>> of 
>>>> an immutable object in the case that the object is inside a container. 
>>>>  Please refer to:
>>>>
>>>> https://github.com/StephenVavasis/Modifyfield.jl 
>>>> <https://www.google.com/url?q=https%3A%2F%2Fgithub.com%2FStephenVavasis%2FModifyfield.jl&sa=D&sntz=1&usg=AFQjCNEMQeocqbzVy4CBDgPjAQNZhmq8Fg>
>>>>
>>>> Feedback is welcome.
>>>>
>>>>
>>>>

Reply via email to