Keno's example showed how a simple error like forgetting that you had
assigned to `a` would cause problems, but it's even worse – that's just a
matter of making an error about the current state of the program. It's
worse than that though: if someone adds a field to a type that is used
*anywhere* with such a `using` construct, that code becomes incorrect. The
fundamental problem with this construct is that it makes it locally
impossible to reason about what it means when you access or assign a
binding. Let's say I have this code:

function foo(x::Bar)
  using x
  a = b + 1

end


What does this mean? b could be a global variable or a field of x; a could
be a local variable or a field of x. Without knowing the structure of Bar,
we can't know. In Julia, we never does this: you can always tell the
meaning of code from purely local syntactic analysis. The code may be wrong
– you might try to access or assign a field that doesn't exist, but there
is only one thing your code could mean. For the same exact reasons, I
wouldn't accept a macro that simulates this into base – it has the exact
same problems. The only way to make this acceptable is if can be locally
disambiguated what the code means. You could, for example, do something
like this:

function foo(x::Bar)

  using x: a, b

  a = b + 1

end


Now you can immediately tell that `a` and `b` are both fields of `x` and
not global or local variables (not by accident, this is independent of the
definition of Bar).


On Thu, Jun 12, 2014 at 7:40 AM, Jameson Nash <[email protected]> wrote:

> > Having the local keyword like it is makes most sense to me, but I
> suppose it isn't a big deal to me that if you don't explicitly specify
> local you could be referring to something outside the current scope, which
> is the case with for loops.
>
> Javascript does this. It also has the "using" block that you describe (see
> "with"). They are probably the worst (mis)features in the entire language.
> In the latest version of javascript, it has finally been removed, to the
> relief of javascript programmers everywhere:
> https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions_and_function_scope/Strict_mode
> .
>
> I would be interested in having a language feature akin to visual basic's
> with block, since it is only a trivial source transform to annotate each
> `.` with the result of the expression in the nearest `with` block.
> function f(A)
>   with A
>     .c = .a + .b
>   end
> end
> However, since this only saves a one character, it really isn't worthwhile.
> function f(A)
>   Z = A
>   Z.c = Z.a + Z.b
> end
>
>
> On Thu, Jun 12, 2014 at 6:14 AM, Mike Innes <[email protected]>
> wrote:
>
>> Ok, managed to have a quick go at this – source with some examples:
>>
>> https://gist.github.com/one-more-minute/668c5c7cdd8fd8b81d35
>>
>> Currently it does nothing to avoid the issue Keno pointed out, but in
>> principle you could throw an error when the mutating version is used
>> without explicit types.
>>
>> If there's any interest in having this in Base you're welcome to it,
>> otherwise I'll probably just clean it up and store it in Lazy.jl.
>>
>>
>> On Thursday, 12 June 2014 09:44:30 UTC+1, Andrew Simper wrote:
>>>
>>> Brilliant Mike! This is exactly what I was after, I just want a way to
>>> write shorthand names for things within a scope, and the @with macro does
>>> just that :) In the example I posted I split the coefficients away from the
>>> state so that only the state needs to be returned, I think this is good for
>>> efficiency. I'll have a play with @with and see how I go. Passing in names
>>> (Typename), isn't a problem, since when a new name is added there is no
>>> duplication in doing this.
>>>
>>> Keno, sorry for not understanding that this is probably what you meant
>>> when you said this would be best off done by using macros, I didn't think
>>> of enclosing the entire algorithm in a macro.
>>>
>>> On Thursday, June 12, 2014 4:21:58 PM UTC+8, Mike Innes wrote:
>>>>
>>>> FWIW – putting to one side the question of whether or not this is a
>>>> good idea – it would be possible to do this without new language syntax.
>>>> However, you'd have to either pass a type hint or be explicit about the
>>>> variables you want:
>>>>
>>>> e.g.
>>>>
>>>> function tick(state::SvfSinOsc, coef::SvfSinOscCoef)
>>>>   @with state::SvfSinOsc, coef::SvfSinOsc
>>>>   # or
>>>>   @with state (ic1eq, ic2eq) coef (g0, g1)
>>>>
>>>>   lv1 = g0*ic1eq - g1*ic2eq
>>>>   lv2 = g1*ic1eq + g0*ic2eq
>>>>   SvfSinOsc(2*v1 - ic1eq, 2*v2 - ic2eq)
>>>> end
>>>>
>>>> This would work in the non-mutating case by calling names() on the type
>>>> and making appropriate variable declarations.
>>>>
>>>> You could then go further and implement
>>>>
>>>> function tick(state::SvfSinOsc, coef::SvfSinOscCoef)
>>>>   @with state (ic1eq, ic2eq) coef (g0, g1) begin
>>>>
>>>>     lv1 = g0*ic1eq - g1*ic2eq
>>>>     lv2 = g1*ic1eq + g0*ic2eq
>>>>     SvfSinOsc(2*v1 - ic1eq, 2*v2 - ic2eq)
>>>>   end
>>>> end
>>>>
>>>> Which would walk over the expression, replacing `a` with `Foo.a`.
>>>> However, it would be tricky to implement this correctly since you'd have to
>>>> be aware of variable scoping within the expression.
>>>>
>>>> I may implement the non-mutating version of this at some point – it
>>>> seems like it could be useful.
>>>>
>>>>
>>>> On Thursday, 12 June 2014 08:21:42 UTC+1, Andrew Simper wrote:
>>>>>
>>>>> On Thursday, June 12, 2014 2:16:30 PM UTC+8, Andrew Simper wrote:
>>>>>>
>>>>>> 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.
>>>>>>
>>>>>
>>>>> Having the local keyword like it is makes most sense to me, but I
>>>>> suppose it isn't a big deal to me that if you don't explicitly specify
>>>>> local you could be referring to something outside the current scope, which
>>>>> is the case with for loops.
>>>>>
>>>>
>

Reply via email to