# Export enum

**URL:** <https://discourse.julialang.org/t/export-enum/5396>\
**Category:** General Usage\
**Tags:** enum\
**Created:** [August 15, 2017, 8:29pm UTC](https://discourse.julialang.org/t/export-enum/5396 "2017-08-15T20:29:31Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![babaq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/babaq/32/891_2.png) [@babaq](https://discourse.julialang.org/u/babaq)\
**Post date:** [August 15, 2017, 8:29pm UTC](https://discourse.julialang.org/t/export-enum/5396/1 "2017-08-15T20:29:31Z")

</div>

Hi

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`?

Alex

---

<div class="post-metadata">

**Author:** ![cstjean](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/cstjean/32/1444_2.png) [@cstjean](https://discourse.julialang.org/u/cstjean)\
**Post date:** [August 15, 2017, 9:00pm UTC](https://discourse.julialang.org/t/export-enum/5396/2 "2017-08-15T21:00:37Z")

</div>

Here’s a macro that does it:

```julia
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

```

---

<div class="post-metadata">

**Author:** ![babaq](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/babaq/32/891_2.png) [@babaq](https://discourse.julialang.org/u/babaq)\
**Post date:** [August 16, 2017, 6:43am UTC](https://discourse.julialang.org/t/export-enum/5396/3 "2017-08-16T06:43:22Z")

</div>

this macro is great, should be included in the base. thanks sharing.

---

<div class="post-metadata">

**Author:** ![mathieu17g](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/mathieu17g/32/34938_2.png) [@mathieu17g](https://discourse.julialang.org/u/mathieu17g)\
**Post date:** [November 11, 2021, 8:26am UTC](https://discourse.julialang.org/t/export-enum/5396/4 "2021-11-11T08:26:31Z")

</div>

In order to deal with the case where you specify the value of each instances, you may use:

```julia
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

```

---

<div class="post-metadata">

**Author:** ![Marius\_Kruger](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/marius_kruger/32/904_2.png) [@Marius\_Kruger](https://discourse.julialang.org/u/Marius_Kruger)\
**Post date:** [December 27, 2024, 10:00pm UTC](https://discourse.julialang.org/t/export-enum/5396/5 "2024-12-27T22:00:37Z")

</div>

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.

```julia
@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

```

---

<div class="post-metadata">

**Author:** ![Eventine](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/eventine/32/215272_2.png) [@Eventine](https://discourse.julialang.org/u/Eventine)\
**Post date:** [July 23, 2025, 2:06pm UTC](https://discourse.julialang.org/t/export-enum/5396/6 "2025-07-23T14:06:35Z")

</div>

Still this only working for symbols, not expression. Gemini gave me out this. Don’t know how correct it is, for me is working:

````julia
"""
    @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

````
