JuliaLang / Compat.jl

Compatibility across Julia versions
Other
145 stars 117 forks source link

`@constfield` for `const` fields? #800

Open Seelengrab opened 1 year ago

Seelengrab commented 1 year ago

Hi!

I have this in one of my packages:

"""
    @constfield foo::Int

A macro providing compatibility for `const` fields in mutable structs.
Gives a `const` `Expr` if supported, otherwise is a noop and just returns the field.
"""
macro constfield(ex::Expr)
        (ex.head == Symbol("::") && length(ex.args) == 2) || throw(ArgumentError("`@constfield` only supports expressions of the form `field::Type`!"))
    ex = esc(ex)
    if VERSION < v"1.8"
        ex
    else
        Expr(:const, ex)
    end
end

and wanted to ask whether there's interest to have this macro in Compat? It's used like this:

struct Foo
     @constfield foo::Int
end

The idea is to have a noop (if unsupported) replacement for const foo::Int in struct definitions.

Seelengrab commented 1 year ago

Come to think of it, the argument checking out so allow raw symbols as well :thinking: So this additional version would be needed too:

macro constfield(ex::Symbol)
    ex = esc(ex)
    if VERSION < v"1.8"
        ex
    else
        Expr(:const, ex)
    end
end
MilesCranmer commented 2 months ago

I wonder if this could be handled with Compat.@compat whenever it wraps a struct?

martinholters commented 2 months ago

I wonder if this could be handled with Compat.@compat whenever it wraps a struct?

That would be nice, but doesn't work because const fields don't even parse:

julia> :(mutable struct Foo
       const bar
       end)
ERROR: syntax: expected assignment after "const"

(That's julia v1.6.) So there's no way of getting them into the argument of @compat.

Seelengrab commented 2 months ago

Yeah, that's why I ultimately ended up with the @const-per-field macro that's a no-op on <1.8.