Генерация метода для каждого подтипа в модуле - PullRequest
3 голосов
/ 17 октября 2019

(перенесено от Джулии Слак для потомства)

скажем, у меня есть некоторые константы, такие как

const FooConst = 1
const BarConst = 2

, и у меня также есть некоторая структура

struct Foo end
struct Bar end

и яТеперь я хочу определить метод для каждой структуры для поиска этой константы

f(::Type{Foo}) = FooConst
f(::Type{Bar}) = BarConst

Как бы я достиг этого последнего блока с помощью метапрограммирования? По сути, я пытаюсь прикрепить Const к концу имени Struct и найти его в коде

...

... (это) работает за пределамимодуля, но в моем модуле константы не экспортируются. После того, как я импортирую свой модуль, f не может искать константы. MWE здесь:

module M
import InteractiveUtils: subtypes
export Foo, Bar, f

abstract type Super end
struct Foo <: Super end
struct Bar <: Super end

const FooConst = 1
const BarConst = 2

for T in subtypes(Super)
    @eval f(::Type{$T}) = $(Symbol(T, "Const"))
end

end # module

, а затем в моем REPL:

julia> using Main.M
julia> f(Foo)
ERROR: UndefVarError: Main.M.FooConst not defined
Stacktrace:
 [1] f(::Type{Foo}) at ./none:11
 [2] top-level scope at none:0

Однако я могу получить к нему прямой доступ:

julia> Main.M.FooConst
1

1 Ответ

4 голосов
/ 17 октября 2019

От Мэйсона Проттера о слабости Джулии:

Мейсон Проттер 14:26 @Sebastian Rollen Проблема была Symbol(T, "const"). Это фактически привело к расширению до Symbol("Main.Foo.FooConst") и Symbol("Main.Foo.BarConst") вместо Symbol("FooConst") и Symbol("BarConst") соответственно. Вы можете исправить это, используя Symbol(nameof(T), "Const"), как показано здесь:

module M
import InteractiveUtils: subtypes
export Foo, Bar, f

abstract type Super end
struct Foo <: Super end
struct Bar <: Super end

const FooConst = 1
const BarConst = 2

for T in subtypes(Super)
    @eval f(::Type{$T}) = $(Symbol(nameof(T), "Const"))
end

end # module

julia> using .M;  f(Foo)
1

julia> f(Bar)
2

Убедитесь, что перезапустите Julia перед запуском этого кода, иначе Julia продолжит использовать экспортированные функции из старой версии вашего модуля.

...