You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Python-side conversion of string doesn't preserve equality #717
I think what is going wrong is that juliacall.convert wraps the string in an AnyValue even though it doesn't have to.
Where is jl.String actually doesn't:
In : type(juliacall.convert(jl.String, "a"))
Out: juliacall.AnyValue
In : type(jl.String("a"))
Out: str
And AnyValue does not overload equality.
In contrast other similar types return wrapper types that do.
In : type(juliacall.convert(jl.Float64, 1.5))
Out: juliacall.RealValue
In : juliacall.convert(jl.Float64, 1.5) == 1.5
Out: True
In : type(juliacall.convert(jl.Bool, True))
Out: juliacall.IntegerValue
In : juliacall.convert(jl.Bool, True) == True
Out: True
Yes this behaviour is as designed but isn't very ergonomic as you've spotted.
jl.String(...) returns a Python str because calling a Julia value automatically converts the result to a Python value.
juliacall.convert(...) returns a Julia wrapper AnyValue (or a.subtype) because you are asking for something with a particular Julia type so it only makes sense to return a Julia value.
In JuliaCall v1, the first point above will change - most operations on wrapped Julia values (such as function calling) will return wrapped Julia values. This mirrors how Py works and is much more predictable - in particular it's much easier to tell what will be a plain Python value and what will be a Julia value.
You can try out the v1 branch to get a preview of this.
Yes, I think this will be much clearer.
Explict julia objects that I can convert in post-processing to python objects will be less confusing.
E.g. i realised that it is very hard to construct a Pair to pass to a julia function that explictly takes a Pair (not a tuple).
Since jl.Pair(x,y) gets auto converted into a tuple
Activity
cjdoris commentedon Nov 12, 2025
Yes this behaviour is as designed but isn't very ergonomic as you've spotted.
jl.String(...)returns a Pythonstrbecause calling a Julia value automatically converts the result to a Python value.juliacall.convert(...)returns a Julia wrapperAnyValue(or a.subtype) because you are asking for something with a particular Julia type so it only makes sense to return a Julia value.In JuliaCall v1, the first point above will change - most operations on wrapped Julia values (such as function calling) will return wrapped Julia values. This mirrors how
Pyworks and is much more predictable - in particular it's much easier to tell what will be a plain Python value and what will be a Julia value.You can try out the v1 branch to get a preview of this.
Closing as this is intentional behaviour.
oxinabox commentedon Nov 13, 2025
Yes, I think this will be much clearer.
Explict julia objects that I can convert in post-processing to python objects will be less confusing.
E.g. i realised that it is very hard to construct a
Pairto pass to a julia function that explictly takes aPair(not a tuple).Since
jl.Pair(x,y)gets auto converted into atuple