2017-06-01 4 views
2

Je peux déballer un tuple. J'essaye d'écrire une fonction (ou macro) qui décompacterait un sous-ensemble de ceux-ci d'une instance du constructeur de type Parameters(). Autrement dit, je sais comment faire:Julia: déballer dans le style

a,b,c = unpack(p::Parameters) 

Mais je voudrais faire quelque chose comme ceci:

b,c = unpack(p::Parameters, b,c) 

ou peut-être même plus paresseux:

unpack(p::Parameters, b, c) 

Ceci permet d'éviter l'écriture des choses comme:

function unpack_all_oldstyle(p::Parameters) 
    a=p.a; b=p.b; c=p.c; ... z=p.z; 
    return a,b,c,...,z 
end 

Il y a quelque chose mal avec mon approche, mais j'espère qu'il y a une solution. Dans le cas où le libellé de ma question ne m'avait pas éclairci, je suis totalement ignorant. Je l'ai lu déballer les points de suspension ici: how-to-pass-tuple-as-function-arguments

workspace() 

    "module UP tests Unpacking Parameters" 
    module UP 

    "this type declaration initiates a constructor function" 
    type Parameters 
     a::Int64 
     b::Int64 
     c::Int64 
    end 

    "this function sets default parameters and returns a tuple of default values" 
    function Parameters(; 
     a::Int64 = 3, 
     b::Int64 = 11, 
     c::Int64 = 101 
    ) 
     Parameters(a, b, c) 
    end 

    "this function unpacks all parameters" 
    function unpack_all(p::Parameters) 
     return p.a, p.b, p.c 
    end 

    "this function tests the unpacking function: in the body of the function one can now refer to a rather than p.a : worth the effort if you have dozens of parameters and complicated expressions to compute, e.g. type (-b+sqrt(b^2-4*a*c))/2/a instead of (-p.b+sqrt(p.b^2-4*p.a *p.c))/2/p.a" 
    function unpack_all_test(p::Parameters) 
     a, b, c = unpack_all(p) 
     return a, b, c 
    end 

    """ 
    This function is intended to unpack selected parameters. The first, unnamed argument is the constructor for all parameters. The second argument is a tuple of selected parameters. 
    """ 
    function unpack_selected(p::Parameters; x...) 
     return p.x 
    end 

    function unpack_selected_test(p::Parameters; x...) 
     x = unpack_selected(p, x) 
     return x 
    end 

    export Parameters, unpack_all, unpack_all_test, unpack_selected, unpack_selected_test 

    end 

    p = UP.Parameters() # make an instance 
    UP.unpack_all_test(p) 
    ## (3,11,101) ## Test successful 

    UP.unpack_selected_test(p, 12) 
    ## 12 ## intended outcome 

    UP.unpack_selected_test(p, b) 
    ## 11 ## intended outcome 

    UP.unpack_selected_test(p, c, b, a) 
    ## (101,11,3) ## intended outcome 

Répondre

6

Il existe déjà un: Parameters.jl.

julia> using Parameters 

julia> type Params 
      a::Int64 
      b::Int64 
      c::Int64 
     end 

julia> @unpack a, c = Params(1,2,3) 
Params(1,2,3) 

julia> a,c 
(1,3) 

julia> @with_kw type Params 
      a::Int64 = 3 
      b::Int64 = 11 
      c::Int64 = 101 
     end 
julia> @unpack c,b,a = Params() 
Params 
    a: Int64 3 
    b: Int64 11 
    c: Int64 101 


julia> c,b,a 
(101,11,3) 

BTW, vous pouvez fixer votre unpack_selected par:

unpack_selected(p::Parameters, fields...) = map(x->getfield(p, x), fields).

# note that, the selected field names should be Symbol here 
julia> unpack_selected(p, :b) 
(11,) 

julia> unpack_selected(p, :c, :b, :a) 
(101,11,3) 
+0

Je voudrais encore une fois faire une mise à jour pour votre édition: très utile pour avoir une explication sur la façon de réparer mon pseudo-code! Merci! – PatrickT