# Macro to create struct according to existing variables' type and name

**URL:** <https://discourse.julialang.org/t/macro-to-create-struct-according-to-existing-variables-type-and-name/20793>\
**Category:** General Usage\
**Created:** [February 14, 2019, 5:06pm UTC](https://discourse.julialang.org/t/macro-to-create-struct-according-to-existing-variables-type-and-name/20793 "2019-02-14T17:06:44Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![vitreo12](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/vitreo12/32/4028_2.png) [@vitreo12](https://discourse.julialang.org/u/vitreo12)\
**Post date:** [February 14, 2019, 5:06pm UTC](https://discourse.julialang.org/t/macro-to-create-struct-according-to-existing-variables-type-and-name/20793/1 "2019-02-14T17:06:44Z")

</div>

Hello everyone,  
I was wondering if there was a way to define a macro `@define` that, given

```julia
let
a::Float64 = 0.5
b::Int64 = 1
@define MyStruct a b
end

```

would define a `struct MyStruct` with fields `a::Float64` and `b::Int64`, as much as the following code:

```julia
let
a::Float64 = 0.5
b::Int64 = 1
struct MyStruct
a::typeof(a)
b::typeof(b)
end
end

```

This would define a `MyStruct` which types are correctly represented as `svec(Float64, Int64)`.  
My naive approach to the macro is of text replacement, but it doesn’t work, as only the Symbols `a` and `b` are passed in, without any information about their types. The result is that the types of a defined struct always look like `svec(Any, Any)`

```julia
macro define(name, variables...)
    local variables_with_types = []
    for i = 1 : length(variables)
        local current_var_with_type = Symbol("$(variables[i])::typeof($(variables[i]))")
        push!(variables_with_types, current_var_with_type)
    end

    local struct_definition = quote 
        struct $name
            $(variables_with_types...)
        end
    end

    return esc(:($struct_definition))
end

```

Is there a way to achieve such task? Or must the macro be written in the form `@define MyStruct (a, Float64) (b, Int64)`?

---

<div class="post-metadata">

**Author:** ![rdeits](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rdeits/32/286_2.png) [@rdeits](https://discourse.julialang.org/u/rdeits)\
**Post date:** [February 14, 2019, 7:19pm UTC](https://discourse.julialang.org/t/macro-to-create-struct-according-to-existing-variables-type-and-name/20793/2 "2019-02-14T19:19:32Z")

</div>

> [@vitreo12](#):
>
> Is there a way to achieve such task? Or must the macro be written in the form `@define MyStruct (a, Float64) (b, Int64)` ?

No, and yes, in that order 🙂

Macros operate on _syntax_, not on values. The fact that the macro only sees the symbols `:a` and `:b` is by design. That’s what macros do: they take syntax and turn it into other syntax.

You could, if you really want, create a macro that outputs a call to `eval()` to define the struct based on the actual values (and thus, types) of `:a` and `:b` in whatever scope that macro was called in but…I really wouldn’t recommend it. There’s almost certainly a cleaner way to achieve whatever your actual goal is.

Perhaps if you can explain more about what your goal with this macro is, perhaps we can help you find a simpler way of achieving it.

---

<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:** [February 14, 2019, 7:34pm UTC](https://discourse.julialang.org/t/macro-to-create-struct-according-to-existing-variables-type-and-name/20793/3 "2019-02-14T19:34:24Z")

</div>

You can use a parametric struct to achieve a similar effect:

```julia
julia> using QuickTypes

julia> @qstruct_fp MyStruct(a, b)

julia> MyStruct(0.5, 1)
MyStruct{Float64,Int64}(0.5, 1)

```

---

<div class="post-metadata">

**Author:** ![vitreo12](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/vitreo12/32/4028_2.png) [@vitreo12](https://discourse.julialang.org/u/vitreo12)\
**Post date:** [February 14, 2019, 7:57pm UTC](https://discourse.julialang.org/t/macro-to-create-struct-according-to-existing-variables-type-and-name/20793/4 "2019-02-14T19:57:35Z")

</div>

Thank you for the answer. I am currently developing a package where I would like to provide an interface that looks like this:

```julia
@define MyObject begin
    a::Int64 = 2
    b::Float64 = 1.0
    whatever_variable::Float64 = 2.3
    c::AnotherObject = AnotherObject(whatever_variable)
        
    @new(a, b, c)
end

```

which should expand to (or equivalent):

```julia
struct MyObject
    a::Int64
    b::Float64
    c::CustomStruct

    function MyObject()
        a::Int64 = 2
        b::Float64 = 1.0
        whatever_variable::Float64 = 2.3
        c::AnotherObject = AnotherObject(whatever_variable)
        return new(a, b, c)
    end
end

```

There is no special need for me to have the user to provide the name of the struct. So, if it easier, the interface could just look like: `@define begin...end`

---

<div class="post-metadata">

**Author:** ![rdeits](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/rdeits/32/286_2.png) [@rdeits](https://discourse.julialang.org/u/rdeits)\
**Post date:** [February 14, 2019, 8:05pm UTC](https://discourse.julialang.org/t/macro-to-create-struct-according-to-existing-variables-type-and-name/20793/5 "2019-02-14T20:05:04Z")

</div>

Yes, that looks perfectly doable, since all of the information (i.e. the names and types of `a` and `b`) are contained within the input to the macro. In fact, it looks like what you’re trying to do is very close to what `Parameters.jl` already does: [https://github.com/mauro3/Parameters.jl](https://github.com/mauro3/Parameters.jl) Does that package fit your needs?

---

<div class="post-metadata">

**Author:** ![vitreo12](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/vitreo12/32/4028_2.png) [@vitreo12](https://discourse.julialang.org/u/vitreo12)\
**Post date:** [February 14, 2019, 8:17pm UTC](https://discourse.julialang.org/t/macro-to-create-struct-according-to-existing-variables-type-and-name/20793/6 "2019-02-14T20:17:07Z")

</div>

It definitely looks close to what I need. But how could I go about having extra variables that are used for the initialization of others (e.g. the `whatever_variable` in my previous example), without including them in the struct? Also, is there a way for me to abstract the keyword `struct` away from the macro, so that the user can just write `@define begin...end`? Sorry for the amount of questions, I am still a learner in the macros world 🙂
