It seems that the local keyword is a bit of a language kludge to me, since 
it is implied in most cases, apart from stating the new scope in the form 
of a for loop etc. It would seem more natural and consistent to me to add 
the local keyword in front of all variables you want to be local in scope, 
and everyting else is global. This line of reasoning I'm sure has already 
been argued to death, and obviously having an implicit local was decided to 
be best.

An ideal use case to me would be to write be able to write an algorithm at 
the REPL using globals, but then easily wrap that up in a function that 
takes a single type that contains all the globals that were used in the 
algorithm. You could copy and paste the same global code, then stick a 
"using this" in front of it and it would all work great.

Oh well, perhaps julia isn't for me, I'm just too used to not being forced 
to use dots everywhere to access stuff in "this".  

On Thursday, June 12, 2014 1:59:56 PM UTC+8, Andrew Simper wrote:
>
> 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 <andrew...@gmail.com> 
>> 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 <andrew...@gmail.com> 
>>>> 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 <andrew...@gmail.com> 
>>>>>> 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