Yep, that makes sense, thanks for showing the example. I already have 
another thread going on sorting out a "fetch" macro to introduce a local 
copy of the names in a type.

Out of interest, what is the "local" keyword for?

http://julia.readthedocs.org/en/latest/manual/variables-and-scoping/


On Thursday, June 12, 2014 1:39:19 PM UTC+8, Keno Fischer wrote:
>
> There is no plans for namespace support other than what's already in with 
> modules.
>
> I'll try to explain. Say you have a mutable 
> type foo
>     a::Int
>     b::Int
> end
>
> Then to modify it in a function you have to explicitly say
> function bar(f::foo)
> f.a = 2
> f.b = 3
> end
>
> etc., for it to modify my argument foo. I think it's way too easy to 
> refactor a function say
>
> function bar(f::foo)
> ... lots of stuff ...
> a = 2*f.a
> ... lots of stuff ...
> f.b*10*a
> end
>
> into 
>
> function bar(f::foo)
> using f
> ... lots of stuff ...
> a = 2*f.a
> ... lots of stuff ...
> b*10*a
> end
>
> because you want to immediately access b, but forgot that foo also has an 
> a field. In general in julia an assignment like
>
> var = value
>
> will almost never have effects outside it's current scope (var[idx] = and 
> var.field = are different). The only exception to this is if you write
>
>  function test()
> global var
> var = value
> end
>
> but as you can see that annotation is very explicit and limited. I would 
> be similarly opposed to a language feature that causes all variables in a 
> function to implicitly be global.
>
> As I said this isn't a concern in the immutable case because the 
> subsequent assignment would always override the original value and simple 
> assignments will not have effects outside the current scope. This can be 
> implemented with macros though.
>
> Hope that clarifies it,
> Keno
>
>
> On Thu, Jun 12, 2014 at 1:30 AM, Andrew Simper <[email protected] 
> <javascript:>> wrote:
>
>> Are namespaces going to be supported in julia? It would be the same 
>> mechanism as that, an order of preference to choose what a particular name 
>> is referring to, no more. So if julia is not going to support "using" on a 
>> namespace then I completely understand not wanting to support it on 
>> variables as I have suggested.
>>
>> I don't follow what you mean by "The mutable case has me worried. It 
>> introduces the possibility that an assingment (a simple one, not a setfield 
>> or getindex) actually has effects outside of the function which doesn't 
>> happen anywhere else in julia."
>>
>> Can you please provide an example to illustrate what you are worried 
>> about?
>>
>>
>> On Thursday, June 12, 2014 1:21:14 PM UTC+8, Keno Fischer wrote:
>>
>>> In my opinion, looking at that example this is way to magical. Plus the 
>>> general consensus is that you should only add syntax if it is something 
>>> extremely special that requires compiler support. For the non-mutable case, 
>>> that's not the case here. The mutable case has me worried. It introduces 
>>> the possibility that an assingment (a simple one, not a setfield or 
>>> getindex) actually has effects outside of the function which doesn't happen 
>>> anywhere else in julia. 
>>>
>>>
>>> On Thu, Jun 12, 2014 at 1:07 AM, Andrew Simper <[email protected]> 
>>> wrote:
>>>
>>>> The problem with using a macro is that you will always have to make a 
>>>> local copy of the data, if it was a language feature then then a mutable 
>>>> type could be passed in as the argument and the same non-obfuscated code 
>>>> could be used to update the state in place, which may be preferable 
>>>> depending on the situation.
>>>>
>>>> Here is another example from the Julia.org webpage:
>>>>
>>>> immutable Pixel
>>>>     r::Uint8
>>>>     g::Uint8
>>>>     b::Uint8
>>>> end
>>>>
>>>> function rgb2gray!(img::Array{Pixel})
>>>>     for i=1:length(img)
>>>>         p = img[i]
>>>>         v = uint8(0.30*p.r + 0.59*p.g + 0.11*p.b)
>>>>         img[i] = Pixel(v,v,v)
>>>>     end
>>>> end
>>>>
>>>> function rgb2gray2!(img::Array{Pixel})
>>>>     for i=1:length(img)
>>>>         using img[i]
>>>>         v = uint8(0.30*r + 0.59*g + 0.11*b)
>>>>         img[i] = Pixel(v,v,v)
>>>>     end
>>>> end
>>>>
>>>>
>>>>
>>>> On Thursday, June 12, 2014 12:30:05 PM UTC+8, Keno Fischer wrote:
>>>>
>>>>> I don't think it warrants syntax, but might be nice in a macro. I've 
>>>>> had cases where I just put my entire simulation state in a single object, 
>>>>> so I don't need to give 100s of parameters to every object. In that case 
>>>>> (where the object is more of a container than an abstraction), it might 
>>>>> be 
>>>>> nice to use. 
>>>>>
>>>>>
>>>>> On Thu, Jun 12, 2014 at 12:13 AM, Andrew Simper <[email protected]> 
>>>>> wrote:
>>>>>
>>>>>> So just to post again to make things clearer, right now algorithms 
>>>>>> tend to look pretty ugly and obfuscated since you have to prefix 
>>>>>> function 
>>>>>> arguments with the argument names using dot notation:
>>>>>>
>>>>>> function tick (state::SvfSinOsc, coef::SvfSinOscCoef)
>>>>>>     local v1::Float64 = coef.g0*state.ic1eq - coef.g1*state.ic2eq
>>>>>>     local v2::Float64 = coef.g1*state.ic1eq + coef.g0*state.ic2eq
>>>>>>     SvfSinOsc (2*v1 - state.ic1eq, 2*v2 - state.ic2eq)
>>>>>> end
>>>>>>
>>>>>>
>>>>>> This is a lot more readable to me, and it would be super useful to 
>>>>>> have a "using" type operation similar to namespace but it could run on 
>>>>>> variables instead, so that although writing the following is equivalent 
>>>>>> to 
>>>>>> what is above, it is much easier to see what is going on:
>>>>>>
>>>>>> function tick (state::SvfSinOsc, coef::SvfSinOscCoef)
>>>>>>     using state, coef
>>>>>>     local v1::Float64 = g0*ic1eq - g1*ic2eq
>>>>>>     local v2::Float64 = g1*ic1eq + g0*ic2eq
>>>>>>     SvfSinOsc (2*v1 - ic1eq, 2*v2 - ic2eq)
>>>>>> end
>>>>>>
>>>>>> What are peoples opinions on this? Would anyone else find it useful?
>>>>>>
>>>>>>
>>>>>>
>>>>>> On Friday, June 6, 2014 3:17:31 PM UTC+8, Andrew Simper wrote:
>>>>>>>
>>>>>>> In implementations where you want named data, I've noticed that the 
>>>>>>> algorithm gets obfuscated by lots of variable names with dots after 
>>>>>>> them. 
>>>>>>> For example, here is a basic analog model of a state variable filter 
>>>>>>> used 
>>>>>>> as a sine wave generator:
>>>>>>>
>>>>>>> immutable SvfSinOscCoef
>>>>>>>     g0::Float64
>>>>>>>     g1::Float64
>>>>>>> end
>>>>>>> immutable SvfSinOsc
>>>>>>>     ic1eq::Float64
>>>>>>>     ic2eq::Float64
>>>>>>> end
>>>>>>> function SvfSinOscCoef_Init (;freq=1.0, sr=44100.0)    
>>>>>>>     local g::Float64 = tan (2pi*freq/sr)
>>>>>>>     local g0 = 1.0/(1.0+g^2)
>>>>>>>     SvfSinOscCoef (g0,g*g0)
>>>>>>> end
>>>>>>> function SvfSinOsc_Init (startphase::Float64)
>>>>>>>     SvfSinOsc (cos(startphase), sin(startphase))
>>>>>>> end
>>>>>>>
>>>>>>> But the tick function looks a bit messy:
>>>>>>>
>>>>>>> function tick (state::SvfSinOsc, coef::SvfSinOscCoef)
>>>>>>>     local v1::Float64 = coef.g0*state.ic1eq - coef.g1*state.ic2eq
>>>>>>>     local v2::Float64 = coef.g1*state.ic1eq + coef.g0*state.ic2eq
>>>>>>>     SvfSinOsc (2*v1 - state.ic1eq, 2*v2 - state.ic2eq)
>>>>>>> end
>>>>>>>
>>>>>>>
>>>>>>> It would be really cool if there was a way to shorthand the syntax 
>>>>>>> of this to something like the following, which is a lot more readable:
>>>>>>>
>>>>>>> function tick (state::SvfSinOsc, coef::SvfSinOscCoef)
>>>>>>>     using s, c
>>>>>>>     local v1::Float64 = g0*ic1eq - g1*ic2eq
>>>>>>>     local v2::Float64 = g1*ic1eq + g0*ic2eq
>>>>>>>     SvfSinOsc (2*v1 - ic1eq, 2*v2 - ic2eq)
>>>>>>> end
>>>>>>>
>>>>>>>
>>>>>>> Lots of algorithms have arguments with the same type, but even then 
>>>>>>> you could still specify using just the most used argument, but if it 
>>>>>>> doesn't help make things more clear or isn't useful then people don't 
>>>>>>> have 
>>>>>>> to use it at all.
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> Another pattern that would be nice to handle cleanly is: fetch state 
>>>>>>> to local, compute on local, store local to state. I have written code 
>>>>>>> that 
>>>>>>> generates code to handle this since it is such a pain to keep 
>>>>>>> everything in 
>>>>>>> sync, but if there was some way to automate this at the language level 
>>>>>>> then 
>>>>>>> it would really rock, so here is an example of the longhand way, which 
>>>>>>> isn't too bad for this example, but just imagine if there are 20 or so 
>>>>>>> variables, and you are writing multiple tick functions:
>>>>>>>
>>>>>>> type SvfSinOsc
>>>>>>>     ic1eq::Float64
>>>>>>>     ic2eq::Float64
>>>>>>> end
>>>>>>>
>>>>>>> function tick (state::SvfSinOsc, coef::SvfSinOscCoef)
>>>>>>>     local ic1eq::Float64 = state.ic1eq
>>>>>>>     local ic2eq::Float64 = state.ic2eq
>>>>>>>     for i = 1:100
>>>>>>>         # compute algorithm using local copies of state.ic1eq and 
>>>>>>> state.ic2eq
>>>>>>>     end
>>>>>>>     state.ic1eq = ic1eq
>>>>>>>     state.ic2eq = ic2eq
>>>>>>>     return state
>>>>>>> end
>>>>>>>
>>>>>>>
>>>>>>> I have a feeling that macros may be able to help out here to result 
>>>>>>> in something like:
>>>>>>>
>>>>>>> function tick (state::SvfSinOsc, coef::SvfSinOscCoef)
>>>>>>>     @fetch state
>>>>>>>     for i = 1:100
>>>>>>>         # compute iterative algorithm using local copies of 
>>>>>>> state.ic1eq and state.ic2eq
>>>>>>>     end
>>>>>>>     @store state
>>>>>>>     return state
>>>>>>> end
>>>>>>>
>>>>>>> But I'm not sure how to code such a beast, I tried something like:
>>>>>>>
>>>>>>>  macro fetch(obj::SvfSinOsc)
>>>>>>>     return quote
>>>>>>>         local ic1eq = obj.ic1eq
>>>>>>>         local ic2eq = obj.ic2eq
>>>>>>>     end
>>>>>>> end
>>>>>>>
>>>>>>> macro store(obj::SvfSinOsc)
>>>>>>>     return quote
>>>>>>>         obj.ic1eq = ic1eq
>>>>>>>         obj.ic2eq = ic2eq
>>>>>>>     end
>>>>>>> end
>>>>>>>
>>>>>>> dump(osc)
>>>>>>> macroexpand (:(@fetch osc))
>>>>>>> macroexpand (:(@store osc))
>>>>>>>
>>>>>>> SvfSinOsc 
>>>>>>>   ic1eq: Float64 1.0
>>>>>>>   ic2eq: Float64 0.0
>>>>>>>
>>>>>>>
>>>>>>> Out[28]: :($(Expr(:error, TypeError(:anonymous,"typeasse
>>>>>>> rt",SvfSinOsc,:osc))))
>>>>>>>
>>>>>>>
>>>>>>>  
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>
>>>
>

Reply via email to