如何在Julia中以元编程方式定义部分拷贝构造函数?

时间:2016-09-02 19:26:13

标签: metaprogramming julia

Gadfly有一个漂亮的宏,可以为一些大型类型生成一个复制构造函数和可选的参数构造函数:

# Generate large types where each field has a default value to which it's
# initialized.

macro varset(name::Symbol, table)
    @assert table.head == :block
    table = table.args

    names = Any[]
    vars = Any[]
    parameters = Any[]
    parameters_expr = Expr(:parameters)

    for row in table
        if isa(row, Expr) && row.head == :line
            continue
        end

        if isa(row, Symbol)
            var = row
            typ = :Any
            default = :nothing
        elseif row.head == :tuple
            @assert 2 <= length(row.args) <= 3
            var = row.args[1]
            typ = row.args[2]
            default = length(row.args) > 2 ? row.args[3] : :nothing
        else
            error("Bad varset systax")
        end

        push!(names, var)
        push!(vars, :($(var)::$(typ)))
        push!(parameters, Expr(:kw, var, default))
        parameters_expr = Expr(:parameters, parameters...)
    end

    new_with_defaults = Expr(:call, :new, names...)

    ex =
    quote
        type $(name)
            $(vars...)

            function $(name)($(parameters_expr))
                $(new_with_defaults)
            end

            # shallow copy constructor
            function $(name)(a::$(name))
                b = new()
                for name in fieldnames($(name))
                    setfield!(b, name, getfield(a, name))
                end
                b
            end
        end

        function copy(a::$(name))
            $(name)(a)
        end
    end

    esc(ex)
end

我想添加一个部分复制构造函数,它允许您提供一个对象和一些部分参数。它将复制提供的对象并仅覆盖您提供的字段。

我怎样才能定义如下内容?伪代码肥胖型:

function $(name)(a::$(name), $(parameters_expr))
            b = new(a)
            for name in names
                if getfield(b, name) != default
                    setfield!(b, name, new_val)
                end
            end
        end

0 个答案:

没有答案