I am defining an enum such as @enum myenum enumname1 enumname2 in a module using Julia 0.6. it seems I have to explicitly export both enum type name(myenum) and enum elements(enumname1,enumname2). I know this way is more explicit, but usually we want all elements of an enum type be exported too. is there a way to just do export myenum so that type name and all its elements be exported, or should this behavior be the default for export enum?
macro exported_enum(name, args...)
esc(quote
@enum($name, $(args...))
export $name
$([:(export $arg) for arg in args]...)
end)
end
@exported_enum fruit apple banana
In order to deal with the case where you specify the value of each instances, you may use:
julia> module A
macro exported_enum(T, syms...)
return esc(quote
@enum($T, $(syms...))
export $T
for inst in Symbol.(instances($T))
eval($(Expr(:quote, :(export $(Expr(:$, :inst))))))
end
end)
end
@exported_enum fruit apple=2 banana=3
end
Main.A
julia> using Main.A
julia> fruit
Enum fruit:
apple = 2
banana = 3
sorry for reviving this.
I got the macro to to support a begin end block (with comments)
(I had some help from the ai, as macro definition syntax is a bit of a black art)
eg.
@exported_enum MyEnum begin
#this is a
A
#this is b
B
end
macro exported_enum(name, args...)
if length(args) == 1 && args[1] isa Expr && args[1].head == :block
# Handle the begin ... end block syntax
block = args[1]
# Filter out comments from the block
enum_members = filter(x -> x isa Symbol, block.args)
return esc(quote
@enum $name begin
$(enum_members...)
end
export $name
$([:(export $arg) for arg in enum_members]...)
end)
else
# Handle the standard @enum syntax
return esc(quote
@enum($name, $(args...))
export $name
$([:(export $arg) for arg in args]...)
end)
end
end
Still this only working for symbols, not expression. Gemini gave me out this. Don’t know how correct it is, for me is working:
"""
@export_enum_members(EnumType)
Exports all instances (members) of a previously defined enum type from the current module.
This macro automates the process of writing individual `export` statements for each
member of an enum. It is particularly useful for enums with many members or for
maintaining a clean separation between definition and export logic.
Note: This macro only exports the enum's instances; it does **not** export the enum
type itself.
# Usage
First, define your enum as you normally would. Then, call the macro with the name
of the enum type.
```julia
# 1. Define the enum
@enum MyColor begin
RED
GREEN
BLUE
end
# 2. Export only its members using the macro
@export_enum_members MyColor
```
# Examples
#### Standard Use Case:
This is the intended use of the macro.
```julia
module MyDrawingApp
# Define the enum internally
@enum ToolType begin
PENCIL
BRUSH
ERASER
end
# Make the tools available to users, but keep the `ToolType` abstract.
# The user can use `PENCIL`, but not necessarily the type `ToolType`.
@export_enum_members ToolType
end
```
The macro call `@export_enum_members ToolType` automatically expands to the
following code during compilation:
```julia
export PENCIL
export BRUSH
export ERASER
```
#### Comparison with `@exported_enum`:
This macro differs from a combined-definition macro like `@exported_enum` in that
it provides more control by decoupling definition from exportation.
- Use `@exported_enum` when you always want to define and export an enum and all its members in one step.
- Use `@export_enum_members` when you have an existing enum and only want to export its members, potentially keeping the enum type itself private to the module.
# See Also
- `exported_enum`
- `@enum`: The built-in macro for creating enumerations in Julia.
- `export`: The keyword for defining a module's public API.
"""
macro export_enum_members(enum_type)
# This macro must be called after the enum is defined.
# We evaluate the enum_type symbol in the context of the module where
# the macro is called (__module__) to get the actual type object.
try
type_obj = Core.eval(__module__, enum_type)
# Check that we have a valid Enum
if !(type_obj isa DataType && supertype(type_obj) <: Enum)
return :(error($(string(enum_type)) * " is not a valid Enum type."))
end
# Get the list of instances (e.g., [PENCIL, BRUSH, ...])
instance_list = instances(type_obj)
# Create a list of export expressions, e.g., [:(export PENCIL), :(export BRUSH), ...]
export_expressions = [:(export $(Symbol(inst))) for inst in instance_list]
# Return the block of expressions, escaped to run in the caller's scope.
# The `...` splats the array of expressions into the quote block.
return esc(quote
$(export_expressions...)
end)
catch e
return :(error("Could not find enum type " * $(string(enum_type)) * ". It must be defined before calling @export_enum_members."))
end
end
"""
@exported_enum(name, args...)
Defines an enum and automatically exports both the enum type and all of its instances
from the current module.
This macro is a convenience wrapper around Julia's built-in `@enum` macro. It is designed
to reduce boilerplate code by eliminating the need to manually write `export` statements
for the enum type and each of its members.
# Usage
The macro is called with the same syntax as `@enum`, typically using a `begin ... end`
block.
```julia
@exported_enum MyEnum begin
ValueA = 1
ValueB = 2
ValueC
end
```
# Examples
Consider a module that needs to provide an enum as part of its public API.
#### Without the macro:
Without this macro, you must define the enum and then manually list the type and every single member in an `export` statement.
```julia
module MyModule
@enum MyEnum begin
ValueA = 1
ValueB = 2
ValueC
end
# Manual export statements are required, which can be verbose.
export MyEnum, ValueA, ValueB, ValueC
end
```
#### With the `@exported_enum` macro:
The macro handles the definition and all exports in a single, clean expression, making your code more concise and less error-prone.
```julia
module MyModule
@exported_enum MyEnum begin
ValueA = 1
ValueB = 2
ValueC
end
# No further export statements are needed for the enum.
end
```
The macro call above automatically expands to the following code during compilation:
```julia
@enum MyEnum begin
ValueA = 1
ValueB = 2
ValueC
end
export MyEnum
export ValueA
export ValueB
export ValueC
```
# See Also
- `export_enum_members`
- `@enum`: The built-in macro for creating enumerations in Julia.
- `export`: The keyword for defining a module's public API.
"""
macro exported_enum(name, args...)
# Helper function to extract the symbol name from an enum member definition.
# This correctly handles both `ValueA` and `ValueA = 1`.
function get_enum_symbol(arg)
if arg isa Symbol
return arg
elseif arg isa Expr && arg.head == :(=) && arg.args[1] isa Symbol
return arg.args[1]
else
return nothing # Ignore things like LineNumberNodes or comments
end
end
local enum_definition_args # The raw arguments for the @enum macro
local member_names # The clean symbols for the export list
if length(args) == 1 && args[1] isa Expr && args[1].head == :block
# Handle the `begin ... end` block syntax
block = args[1]
enum_definition_args = block
member_names = filter(!isnothing, [get_enum_symbol(arg) for arg in block.args])
else
# Handle the standard `@enum(name, ValueA, ValueB=2)` syntax
enum_definition_args = args
member_names = filter(!isnothing, [get_enum_symbol(arg) for arg in enum_definition_args])
end
# The @enum macro can take the block or the splatted args directly.
# We construct the appropriate call based on the syntax used.
enum_definition = if enum_definition_args isa Expr && enum_definition_args.head == :block
:(@enum $name $enum_definition_args)
else
:(@enum $name $(enum_definition_args...))
end
# We escape the final generated code block to ensure it is executed
# in the scope where the macro was called.
return esc(quote
$enum_definition
export $name
$([:(export $name) for name in member_names]...)
end)
end