how to return a new instance in julia - struct

how can I return a new instance from a struct within a function in Julia?
function generateField(type, default, description, max, min)
return Field{type}(default,description,min,max)
end
I have a struct called Field. I just used Java logic hier and it did not work for sure :)
struct Field{T}
type::T
default::T
description::String
min::T
max::T
function Field{T}(description,min,max) where {T}
new{T}(description, min, max)
end
end

Just use deepcopy(obj) - it will make a copy of your struct object (assuming this is what you need):
julia> mutable struct Field2{T<:Real}
a::T
b::Vector{Float64}
end
julia> x = Field2{Int}(5,[4.5])
Field2{Int64}(5, [4.5])
julia> y = deepcopy(x)
Field2{Int64}(5, [4.5])
julia> y == x
false
Note that x and y point to different variables and hence x == y yields false. To compare by value one would need to iterate over all struct fields.
For this struct a function generating it could be defined as :
function f(a::T, b::Vector{Float64}) where T <: Real
return Field2{T}(a,b)
end
And used as:
julia> f(1//2, [3.5])
Field2{Rational{Int64}}(1//2, [3.5])
Finally, note that the function generating an object can have the same name as its type - in that case you are generating new constructor:
julia> Field2(a::T) where T<:Real = Field2{T}(a,Int[]);
julia> Field2(2)
Field2{Int64}(2, Float64[])

Related

Pythonic way to check returned value for None

I'm looking for a pythonic way for the code below.
Function foo() may return an int or "None" and in that case "None" should be replaced by a default value.
I doubt that this can't be simplified and reduced to a one-liner, I just don't know how to do it ^^
def foo() -> int:
# code
x = foo()
x = 0 if x is None else x
That is plenty Pythonic and concise (2 lines). The only way to reduce it to 1 line is to use the walrus operator:
x = 0 if (x := foo()) is None else x
# ^ assigns foo() to x and ^ x is reused here
#^but x is ultimately reassigned here
you can use or operator. If the first argument resolves to False, second one is assigned. Example:
x = foo() or default_value
The issue with that is, if foo() will return 0 for example, default value will be assigned

Deriving equality for Julia structs with mutable members

In the Julia code below, we have equality not working for T{BigInt}, due to BigInt being a mutable struct. == is explicitly defined by BigInt for themselves, however.
julia> struct T{X}
x :: X
end
julia> T{Int64}(1) == T{Int64}(1), T{Int64}(1) === T{Int64}(1)
(true, true)
julia> T{BigInt}(1) == T{BigInt}(1), T{BigInt}(1) === T{BigInt}(1)
(false, false)
julia> T{BigInt}(1).x == T{BigInt}(1).x, T{BigInt}(1).x === T{BigInt}(1).x
(true, false)
Is there a way to either:
autogenerate an == for these sorts of structs which just recurses == on each field,
or have immutable versions of mutable structs as members (as with const in C++), other than using an immutable equivalent to BigInt?
My goal is to avoid boilerplate in a package with a large number of such structs.
This should work:
function my_equals(a::S, b::S) where S
for name in fieldnames(S)
if getfield(a, name) != getfield(b, name)
return false
end
end
return true
end
I tried overloading == via
import Base.==
function ==(a::S, b::S) where S
for name in fieldnames(S)
if getfield(a, name) != getfield(b, name)
return false
end
end
return true
end
That has the intended behavior, but (unsurprisingly) seems to break things (i.e. you can't even call exit() after redefining == like that).
If you want to use ==, then you could have all your custom structs inherit from some abstract type, like this:
abstract type Z end
struct T{X} <: Z
x::X
end
struct S{X} <: Z
x::X
y::X
end
import Base.==
function ==(a::V, b::V) where V <: Z
for name in fieldnames(V)
if getfield(a, name) != getfield(b, name)
return false
end
end
return true
end
Then you can use
julia> T{BigInt}(1) == T{BigInt}(1)
true
julia> S{BigInt}(2, 5) == S{BigInt}(2, 5)
true
julia> T{BigInt}(1) == T{BigInt}(2)
false
julia> S{BigInt}(2, 5) == S{BigInt}(2, 3)
false
That doesn't interfere with existing ==.

Julia: Create AbstractArray with Constraints on Values

I'm working on a Julia project which requires matrices to satisfy a trace-one constraint. To avoid checking if matrices are trace-one at inputs and outputs of numerous functions, I'd like to create a new data structure which implicitly contains this constraint.
In my working example, I've defined a struct TraceOne which throws an error if the trace is not equal to one.
struct TraceOne
M :: Matrix{Complex{Float64}}
TraceOne(M) = (tr(M) == 1) ? new(M) : throw(DomainError(M, "Matrix M is not trace-one."))
end
A = TraceOne([0.1 0.5;0.3 0.9])
However, I would like to avoid accessing the trace-one matrix with a key, A.M returns [0.1 0.5;0.3 0.9].
Alternatively, I've tried to create a struct which is a SubType of an AbstractMatrix, but I can't get the values of the AbstractMatrix to initialize properly.
struct TraceOne2 <: AbstractMatrix{Complex{Float64}}
M :: Matrix{Complex{Float64}}
Base.size(T::TraceOne2) = size(T.M)
Base.getindex(T::TraceOne2, I::Vararg{Int,2}) = getindex(T.M, size(T.M)...)
Base.setindex!(T::TraceOne2, v, I::Vararg{Int,2}) = (T.M[I] = v)
TraceOne2(M) = (tr(M) == 1) ? new(M) : throw(DomainError(M, "Matrix M is not trace-one."))
end
B = TraceOne2([0.1 0.5;0.3 0.9])
When I run this code, I find that B is [0.9 0.9;0.9 0.9]. All elements of B are initialized to the value of the (2,2), the index of the input array.
How should I modify struct TraceOne2 ... end such that the resulting matrix B is initialized as [0.1 0.5;0.3 0.9]?
Change this functions from:
Base.getindex(T::TraceOne2, I::Vararg{Int,2}) = getindex(T.M, size(T.M)...)
Base.setindex!(T::TraceOne2, v, I::Vararg{Int,2}) = (T.M[I] = v)
to:
Base.getindex(T::TraceOne2, I::Vararg{Int,2}) = getindex(T.M, I...)
Base.setindex!(T::TraceOne2, v, I::Vararg{Int,2}) = (T.M[I...] = v)

number as an object, or storing properties of a number

in designing an algebraic equation modelling system, I had this dilemma: we cannot associate properties to a number, if I turn the number to a table with a field "value" for example, I can overload arithmetic operators, but not the logic operator since that only works when both operands have same metatable, while my users will compare "x" with numbers frequently.
For example, here is a minimal equation solver system:
x = 0
y = 0
eq1 = {function() return 2*x + 3*y end, rhs = 1 }
eq2 = {function() return 3*x + 2*y end, rhs = 2 }
p = {{x,y},{eq1, eq2}}
solve(p)
The "solve()" will process table "p" to get all coefficients of the equation system and rhs. However, it is essential, a user can associate properties to "x" and "y", for example, lower bound, upper bound. I tries using table,
x = {val=0, lb=0, ub=3}
y = {val=1,lb=3,ub=5}
....
and write metamethods for "x" and "y" such that arithmetic operating will act on x.val and y.val. However, in a scripting environment, we also need to compare "x" with numbers, i.e., "if x>0 then ...". And I stuck here. An ugly solution is to ask users to use x.val, y.val everywhere in modelling the equation and scripting. Does anyone here has similar need to associate properties to a number, and the number can still be used in arithmetic/logic operations?
Something like this could work:
x = {val = 10}
mt = {}
mt.__lt = function (op1, op2)
if (type(op1) == 'table') then a = op1.val else a = op1 end
if (type(op2) == 'table') then b = op2.val else b = op2 end
return a < b
end
setmetatable(x, mt)
print(x < 5) -- prints false
print(x < 15) -- prints true
print(x < x) -- prints false
print(5 < x) -- prints true
Of course, you would write similar methods for the other operators (__add, __mul, __eq and so on).
If you'd rather not use type()/reflection, you can use an even dirtier trick that takes advantage of the fact that unary minus is well, unary:
mt = {}
mt.__unm = function (num) return -(num.val) end
mt.__lt = function (a, b) return -(-a) < -(-b) end
This is rather simple if you have access to the debug library, do you?
debug.setmetatable(0, meta)
meta will be the metatable of ALL numbers. This will solve your logical overloading problem.
However if you would prefer assigning properties to numbers, there is a way you could do this, I wrote a quick example on how one would do so:
local number_props = {
{val="hi"},
{val="hi2"}
}
debug.setmetatable(0,{__index=function(self,k)return number_props[self][k]end})
print((1).val, (2).val)

Groovy: same parameters, different results

In the below code, x.test() returns [1,2].
So y = [1,2].
Yet f([1,2]) prints 1, but f(y) prints 2.
How do I write f(y) so it prints 1?
Perversely, f(z) prints 1, even though z = y.
def f = { Object... args -> println args.size(); };
class Test { Object[] test() { return [1,2]; } }
def x = new Test();
def y = x.test();
def z = [1,2];
f([1,2]); // 1
f(y); // 2
f(z); // 1
The problem is that y and z, while they appear to be the same, are actually of different types. y is an Object[] while z is an ArrayList<Integer>. Groovy handles arrays and lists differently, automatically coercing the former into a varargs parameter list, but not the latter.
println y.getClass(); // class [Ljava.lang.Object
println z.getClass(); // class java.util.ArrayList
As for a solution to your problem, either change your test() to return a List instead of an array:
class Test { List test() { return [1,2]; } }
or manually coerce the array into a list when you pass it to f:
f(y as List); // 1
The expression [1,2] in Groovy denotes an ArrayList with two members, Integer.valueOf(1) and Integer.valueOf(2). Thus when you call f([1,2]) Groovy creates a single-element array containing this ArrayList as its only item, and passes that array as the closure argument.
But x.test() is declared to return Object[] so the [1,2] ArrayList will be converted to a two element Object[] by the return. Thus y is already an Object[] and does not need to be boxed up in a varargs array to be passed to f.
You need to turn y back into a list, either by changing the return type of test() or by saying
f(y as List)
Conversely, you can use the spread operator
f(*z) // 2
which will extract the elements of the ArrayList and pass them as individual arguments to the call (which will then be packaged up into a varargs array as usual).
y is an instance of [Ljava.lang.Object whereas [1,2] and z are of instance of ArrayList
The Array has the size() == 2 and the ArrayLists count as one argument, but they contain two elements
Groovy does some type converting for you ;)

Resources