Stream: helpdesk (published)

Topic: Non-polluting `@auto` macro


view this post on Zulip Mosè Giordano (Apr 01 2022 at 19:28):

auto is everyone's favourite (modern) C++ keyword. Now that we have typed globals, it'd be cool to be able to type @auto x = 2 to get the expression x::Int = 2. Probably not much useful here, but it may be useful in cases where the right-hand side has a much more complex type.

I quickly cooked this macro:

macro auto(ex)
    ex.head !== :(=) && throw(ArgumentError("@auto: `$(ex)` is not an assigment expression."))
    return :( x = $(esc(ex.args[2])); $(esc(ex.args[1]))::typeof(x) = x )
end

but it has the issue that it pollutes the current scope with a gensym'ed variable (x in the body of the macro). if you're wondering why doing

x = $(esc(ex.args[2])); $(esc(ex.args[1]))::typeof(x) = x

instead of

$(esc(ex.args[1]))::typeof($(esc(ex.args[2]))) = $(esc(ex.args[2]))

that's to avoid evaluating twice the right-hand side of the assignment expression, which may be costly and/or have side effects.

is there a way to avoid avoid polluting the namespace with the extra name? I thought about doing

let
    x = $(esc(ex.args[2]))
    global $(esc(ex.args[1]))::typeof(x) = x
end

but that wouldn't work in local scope (like inside a function), which would be nice to retain.

I feel like someone else may have done this macro before

view this post on Zulip chriselrod (Apr 01 2022 at 19:35):

What's the problem with polluting the namespace with gensymed variable names?

I'd been meaning to write a version of this macro that walks the following expression, applying the assert to all assignments.
Would be nice to write @auto function, for example.

view this post on Zulip jar (Apr 01 2022 at 20:00):

In Julia I'd like a more specific name than auto since, unlike in C++, the pre-identifier position isn't assumed to be a type. eg @infertype, @infer, ...

view this post on Zulip Mason Protter (Apr 01 2022 at 20:22):

I like @stable

view this post on Zulip Christopher Rowley (Apr 01 2022 at 20:22):

Is

x = foo()
x::typeof(x)

valid Julia (I'm on my phone)?

view this post on Zulip Mason Protter (Apr 01 2022 at 20:22):

Yes, but that's just an assert, not a promise that the type won't change

view this post on Zulip Christopher Rowley (Apr 01 2022 at 20:24):

Or

x = foo()
x::typeof(x) = x

?

view this post on Zulip Mason Protter (Apr 01 2022 at 20:26):

@Mosè Giordano

julia> macro auto(ex)
           ex.head !== :(=) && throw(ArgumentError("@auto: `$(ex)` is not an assigment expression."))
           quote
               local x = $(esc(ex.args[2]))
               $(esc(ex.args[1]))::typeof(x) = x
           end
       end

The local keyword is what you want I think


Last updated: Oct 02 2023 at 04:34 UTC