Absolutely – I didn't want to get into correct/incorrect when I implemented
@with but I definitely think the

@with Foo::(a, b)

syntax is preferable. I think I'll disable the type syntax, add support for
indexing and then send a PR to see if there's any chance of having it in
Base.

(Personally I think the type syntax could be acceptable if used very
sparingly and only where it has significant benefit – e.g. for a very large
config object that's used in many places. But I do agree that such a
construct wouldn't be best placed in Base.)


On 13 June 2014 15:25, Stefan Karpinski <[email protected]> wrote:

> 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