JuliaInterop/MathLink.jl

Extracting values from arbitrary MathLink.WExpr

Closed this issue · 8 comments

Hi:

Is there a way to parse outputs like these into julia?

W"Association"(W"Rule"("baseSalary", W"Quantity"(220000, "USDollars")), W"Rule"("position", "F"))

Thanks,
Gani -

Hi. Can you clarify a bit here. What would be the corresponding Mathematica code?

Sorry, yes! I was playing with a toy Association and here is one example.
a=weval(W`chingAssociation = Association["team" -> "HOU", "lastName" -> "Ching", "firstName" -> "Brian", "position" -> "F", "baseSalary" -> Quantity[220000, "USDollars"], "guaranteedSalary" -> Quantity[220000, "USDollars"], "year" -> DateObject[{2007}, "Year", "Gregorian", -5.\`]]; c=chingAssociation[[{"baseSalary","position"}]]`)

Output

W"Association"(W"Rule"("baseSalary", W"Quantity"(220000, "USDollars")), W"Rule"("position", "F"))

Thanks!

sorry, I should have made it clearer. I would like the output (22000,"F") if that is possible.
thx!

Hi, the behavior you are describing is not the same as the matiamatica behaviour so it would be unwise to implement it.

In[1]:= chingAssociation=Association["team"->"HOU","lastName"->"Ching","firstName"->"Brian","position"->"F","baseSalary"->Quantity[220000,"USDollars"],"guaranteedSalary"->Quantity[220000,"USDollars"]]
Out[1]= <|team->HOU,lastName->Ching,firstName->Brian,position->F,baseSalary->$ 220000,guaranteedSalary->$ 220000|>
In[2]:= c=chingAssociation[[{"baseSalary","position"}]]
Out[2]= <|baseSalary->$ 220000,position->F|>

you can howerver acces individual elements directly:

In[3]:= c["baseSalary"]
Out[3]= $ 220000
In[4]:= {c["baseSalary"], c["position"]}
Out[4]= {Quantity[220000, "USDollars"], "F"}

In Julia and MathLink this could be done by mapping the Association to a Julia dictionary

function WAssociationToDict(Asso::MathLink.WExpr)
    Wprint(Asso)
    if Asso.head != W"Association"
        error("Not an association")
    end
    D=Dict()
    for Rule in Asso.args
        if Rule.head != W"Rule"
            error("not a rule")
        end
        if length(Rule.args) != 2
            error("Bad rule")
        end
        D[Rule.args[1]]=Rule.args[2]
    end
    return D
end

Running the code could the look something like this:

julia> Ass = weval(W`Association["team" -> "HOU", "lastName" -> "Ching",  "firstName" -> "Brian", "position" -> "F",  "baseSalary" -> Quantity[220000, "USDollars"],  "guaranteedSalary" -> Quantity[220000, "USDollars"],  "year" -> DateObject[{2007}, "Year", "Gregorian", -5.]]`)
W"Association"(W"Rule"("team", "HOU"), W"Rule"("lastName", "Ching"), W"Rule"("firstName", "Brian"), W"Rule"("position", "F"), W"Rule"("baseSalary", W"Quantity"(220000, "USDollars")), W"Rule"("guaranteedSalary", W"Quantity"(220000, "USDollars")), W"Rule"("year", W"DateObject"(W"List"(2007), "Year", "Gregorian", -5.0)))

julia> D = WAssociationToDict(Ass)
Dict{Any, Any} with 7 entries:
  "baseSalary"       => W"Quantity"(220000, "USDollars")
  "guaranteedSalary" => W"Quantity"(220000, "USDollars")
  "year"             => W"DateObject"(W"List"(2007), "Year", "Gregorian", -5.0)
  "team"             => "HOU"
  "lastName"         => "Ching"
  "firstName"        => "Brian"
  "position"         => "F"

julia> D["year"]
W"DateObject"(W"List"(2007), "Year", "Gregorian", -5.0)

julia> D["team"]
"HOU"

julia> [D[x] for x in ["year","team"]]
2-element Vector{Any}:
 W"DateObject"(W"List"(2007), "Year", "Gregorian", -5.0)
 "HOU"

@gganapat: Would a function like WAssociationToDict be usefull?

Thanks to your tip, I learned that you can extract individual elements. So,

Ass.args[5].args[2].args[1] = 220000

It is now possible to extract arbitrary elements from the returned MathLink.WExpr object, which gives me a great sense of control! Thanks again!

Gani -

Hi @gganapat, I hope you will like this latest feature (W2Julia)that i have sneaked into the 0.5.3 (https://github.com/JuliaInterop/MathLink.jl/releases/tag/v0.5.3) release from today. It aims to convert MathLink objects to Julia style objects.

For instance it can convert the "Assumptions" to a dictionary. Below are some examples:

    @test W2Julia(W`{1,2,3}`) == [1,2,3]
    @test W2Julia(W`{1,a,3}`) == [1,W"a",3]
    @test W2Julia(W`{1,a,{1,2}}`) == [1,W"a",[1,2]]
    @test W2Julia(W`Association["team" -> "HOU", "lastName" -> "Ching"]`) == Dict( "team" => "HOU" , "lastName" => "Ching")
    @test W2Julia(W`Association["team" -> {1,2,3}, "lastName" -> "Ching"]`) == Dict( "team" => [1,2,3] , "lastName" => "Ching")
    @test W2Julia(W`{1,Association["team" -> {1,2,3}, "lastName" -> "Ching"]}`) == [1,Dict( "team" => [1,2,3] , "lastName" => "Ching")]

I think this closes the original query.

The function W2Julia is still quite limited, so if you find something that is missing (which is likely), please open a new ticket and I will fix it.