Advice for dealing with `struct` during development

I know this is an old thread, but I think the question not out-dated. I just stumbled across a blog with the following proposal

EDIT: I adapted the macro @kwredef to also include cases with typed structs.

macro redefinable(struct_def)
    struct_def isa Expr && struct_def.head == :struct || error("struct definition expected")
    if struct_def.args[2] isa Symbol
        name = struct_def.args[2]
        real_name = struct_def.args[2] = gensym(name)
    elseif struct_def.args[2].head == :<:
        name = struct_def.args[2].args[1]
        real_name = struct_def.args[2].args[1] = gensym(name)
    end
    esc(quote
        $struct_def
        $real_name.name.name = $(QuoteNode(name)) # fix the name
        $name = $real_name # this should be `const $name = $real_name`
    end)
end

This approach is somewhat similar to one of the approaches above in that it creates a true struct. The advantage is that the name is identical to the struct that you would normally define.
The only disadvantage could be that it creates a lot of structs and doesn’t check whether the new structure is identical to the old one. But for development purposes this shouldn’t be a problem. Also, the variable which holds the struct type could be overwritten.

I was about doing a similar thing for Base.@kwdef and borrowed some of this ideas:

macro kwredef(expr)
  expr = macroexpand(__module__, expr) # to expand @static
  expr isa Expr && expr.head === :struct || error("Invalid usage of @kwredef")
  expr = expr::Expr

  t = expr.args; n = 2
  if t[n] isa Expr && t[n].head === :<:
      t = t[n].args
      n = 1
  end
  curly = t[n] isa Expr && t[n].head === :curly
  if curly
      t = t[n].args
      n=1
  end

  T_old = t[n]
  t[n] = T_new = gensym(T_old)

  esc(quote
    Base.@kwdef $expr
    $T_old = $T_new
    $curly ? $T_new.body.name.name = $(QuoteNode(T_old)) : $T_new.name.name = $(QuoteNode(T_old)) # fix the name
  end)
end
1 Like