I have a composite type foo with one field F that is supposed to store the result of a call to ldltfact().
mutable struct foo
F::Base.SparseArrays.CHOLMOD.Factor{Float64}
end
How do I preallocate memory for F to store the result, when I later call:
A = rand(4,4)
A = sparse(A*A')
foo.F = ldltfact(A)
Related
I have the following mutable struct:
mutable struct foo
x::Vector{String}
# other field(s)...
# constructor(s)
end
I would like to create an object from this struct and edit it like the following:
bar = foo() # or some other constructor
push!(bar.x, "a")
# Do some stuff...
push!(bar.x, "b")
# Do some more stuff...
push!(bar.x, "c")
To do this, what is the best constructor for foo?
P.S. I have tried the following constructors:
foo() = new()
If I use this and do push!(bar.x, "a"), I get an UndefRefError. I could initialize bar.x outside (like bar.x = []), but I really want to avoid this.
I have also tried:
foo() = new([])
With this, I can do the push operations without a problem. However, if I have many other other fields in the struct that are also vectors, I would have to do this:
mutable struct foo
x::Vector{String}
y::Vector{String}
z::Vector{String}
w::Vector{String}
# maybe dozens more...
foo() = new([], [], [], [], ...) # kind of ugly and wastes time to type
end
Is this the best there is?
You can do:
julia> mutable struct Foo
x::Vector{String}
Foo() = new(String[])
end
julia> Foo()
Foo(String[])
However, for your scenario the most convenient would be Base.#kwdef:
Base.#kwdef mutable struct FooB
x::Vector{String} = String[]
y::Vector{String} = String[]
end
Now of course you can do:
julia> FooB()
FooB(String[], String[])
However other methods are available too:
julia> methods(FooB)
# 3 methods for type constructor:
[1] FooB(; x, y) in Main at util.jl:478
[2] FooB(x::Vector{String}, y::Vector{String}) in Main at REPL[9]:2
[3] FooB(x, y) in Main at REPL[9]:2
So you could do:
julia> FooB(;y=["hello","world"])
FooB(String[], ["hello", "world"])
There's one alternative that is quite concise and almost as fast as writing out the inputs:
struct Foo # Typenames should be uppercase
x::Vector{String}
y::Vector{String}
z::Vector{String}
w::Vector{String}
Foo() = new((String[] for _ in 1:4)...) # using a generator and splatting
# Foo() = new(ntuple(_->String[], 4)...) # also possible
end
I'm studying Standard ML and one of the exercices I have to do is to write a function called opPairs that receives a list of tuples of type int, and returns a list with the sum of each pair.
Example:
input: opPairs [(1, 2), (3, 4)]
output: val it = [3, 7]
These were my attempts, which are not compiling:
ATTEMPT 1
type T0 = int * int;
fun opPairs ((h:TO)::t) = let val aux =(#1 h + #2 h) in
aux::(opPairs(t))
end;
The error message is:
Error: unbound type constructor: TO
Error: operator and operand don't agree [type mismatch]
operator domain: {1:'Y; 'Z}
operand: [E]
in expression:
(fn {1=1,...} => 1) h
ATTEMPT 2
fun opPairs2 l = map (fn x => #1 x + #2 x ) l;
The error message is: Error: unresolved flex record (need to know the names of ALL the fields
in this context)
type: {1:[+ ty], 2:[+ ty]; 'Z}
The first attempt has a typo: type T0 is defined, where 0 is zero, but then type TO is referenced in the pattern, where O is the letter O. This gets rid of the "operand and operator do not agree" error, but there is a further problem. The pattern ((h:T0)::t) does not match an empty list, so there is a "match nonexhaustive" warning with the corrected type identifier. This manifests as an exception when the function is used, because the code needs to match an empty list when it reaches the end of the input.
The second attempt needs to use a type for the tuples. This is because the tuple accessor #n needs to know the type of the tuple it accesses. To fix this problem, provide the type of the tuple argument to the anonymous function:
fun opPairs2 l = map (fn x:T0 => #1 x + #2 x) l;
But, really it is bad practice to use #1, #2, etc. to access tuple fields; use pattern matching instead. Here is a cleaner approach, more like the first attempt, but taking full advantage of pattern matching:
fun opPairs nil = nil
| opPairs ((a, b)::cs) = (a + b)::(opPairs cs);
Here, opPairs returns an empty list when the input is an empty list, otherwise pattern matching provides the field values a and b to be added and consed recursively onto the output. When the last tuple is reached, cs is the empty list, and opPairs cs is then also the empty list: the individual tuple sums are then consed onto this empty list to create the output list.
To extend on exnihilo's answer, once you have achieved familiarity with the type of solution that uses explicit recursion and pattern matching (opPairs ((a, b)::cs) = ...), you can begin to generalise the solution using list combinators:
val opPairs = map op+
In the Julia documentation for SortedSet, there is a reference to "ordering objects", which can be used in the constructor. I'm working on a project where I need to implement a custom sort on a set of structs. I'd like to use a functor for this, since there is additional state I need for my comparisons.
Here is a somewhat simplified version of the problem I want to solve. I have two structs, Point and Edge:
struct Point{T<:Real}
x::T
y::T
end
struct Edge{T<:Real}
first::Point{T}
second::Point{T}
end
I have a Point called 'vantage', and I want to order Edges by their distance from 'vantage'. Conceptually:
function edge_ordering(vantage::Point, e1::Edge, e2::Edge)
d1 = distance(vantage, e1)
d2 = distance(vantage, e2)
return d1 < d2
end
Are "ordering objects" functors (or functor-ish)? Is there some other conventional way of doing this sort of ordering in Julia?
An Ordering object can contain fields, you can store your state there. This is an example of a Remainder Ordering which sort integers by it's remainder:
using DataStructures
struct RemainderOrdering <: Base.Order.Ordering
r::Int
end
import Base.Order.lt
lt(o::RemainderOrdering, a, b) = isless(a % o.r, b % o.r)
SortedSet(RemainderOrdering(3), [1,2,3]) # 3, 1, 2
I'm not sure how it is related to functors, so I may misunderstand your question. This is an alternative implementation that defines an Ordering functor. I made explanations in comments.
using DataStructures
import Base: isless, map
struct Foo # this is your structure
x::Int
end
struct PrimaryOrdered{T, F} # this is the functor, F is the additional state.
x::T
end
map(f::Base.Callable, x::T) where {T <: PrimaryOrdered} = T(f(x.x)) # this makes it a functor?
isless(x::PrimaryOrdered{T, F}, y::PrimaryOrdered{T, F}) where {T, F} =
F(x.x) < F(y.x) # do comparison with your additional state, here I assume it is a closure
const OrderR3 = PrimaryOrdered{Foo, x -> x.x % 3} # a order that order by the remainder by 3
a = OrderR3(Foo(2))
f(x::Foo) = Foo(x.x + 1) # this is a Foo -> Foo
a = map(f, a) # you can map f on a OrderR3 object
a == OrderR3(Foo(33)) # true
a = map(OrderR3 ∘ Foo, [1, 2, 3])
s = SortedSet(a)
map(x->x.x, s) # Foo[3, 1, 2]
As always, an MWE is important for a question to be understood better. You can include a piece of code to show how you want to construct and use your SortedSet, instead of the vague "state" and "functor".
The sorting is based on the method isless for the type. So for instance if you have a type in which you want to sort on the b field. For instance you can do
struct Foo{T}
a::T
b::T
end
Base.:isless(x::T,y::T) where {T<:Foo} = isless(x.b,y.b)
s=[Foo(1,2),Foo(2,-1)]
res=SortedSet(s)
#SortedSet(Foo[Foo(2, -1), Foo(1, 2)],
#Base.Order.ForwardOrdering())
Tuples are also sorted in order, so you can also use
sort(s,by=x->(x.b,x.a)) to sort by b,thena without having to define isless for the type.
How could I create variables from keys and values of a dictionary? Is the following extract (like PHP) possible?
julia> d = Dict(
"key1" =>111,
"key2" =>222,
"key3" =>333
);
julia> extract(d)
julia> key1, key2, key3
(111,222,333)
k = collect(keys(d))
v = collect(values(d))
Both keys and values return iterators.
collect then produces an array.
But note that you often do not need to do this and can just iterate through the dictionary using
for (k, v) in d
It is possible to introduce new variables into the global scope with eval:
julia> x = 1
1
julia> function testeval()
eval(:(x = 5))
return x
end
testeval (generic function with 1 method)
julia> testeval()
5
julia> x # the global x has changed!
5
An extract function could look like this:
julia> function extract(d)
expr = quote end
for (k, v) in d
push!(expr.args, :($(Symbol(k)) = $v))
end
eval(expr)
return
end
julia> extract(d)
julia> key1, key2, key3
(111,222,333)
Note that every module has its own global scope. Therefore, this will introduce the variables into the scope of the module where the extract function is defined, i.e., into the Main module if defined at the REPL as in the example.
You should be very careful when using eval and first consider other approaches, e.g, the ones mentioned by David P. Sanders and Dan Getz.
To declare a new composite type, we use the following syntax
type foo
a::Int64
b::Int64
end
and instantiate like such
x = foo(1,3)
Is there some way to have type attributes that always just a function of other attributes? For example, is there some way to do the following (which is invalid syntax)...
type foo
a::Int64
b::Int64
c = a + b
end
My current workaround is just to define a function which calculates c and returns an instance of the type, like so...
type foo
a::Int64
b::Int64
c::Int64
end
function foo_maker(a, b)
return foo(a, b, a+b)
end
Is there a more elegant solution? Possibly one that can be contained within the type definition?
EDIT - 3/7/14
With Cristóvão's suggestion in mind, I've ended up declaring constructors like the following to allow for keyword args and attributes calculated upon instantiation
# Type with optional keyword argument structure
type LargeType
# Declare all the attributes in order up top
q::Int64
w::Int64
e::Int64
r::Int64
t::Int64
y::Int64
a::Number
b::Number
c::Number
# Declare Longer constructor with stuff going on in the body
LargeType(;q=1,w=1,e=1,r=1,t=1,y=1) = begin
# Large Constructor Example
a = round(r^t - log(pi))
b = a % t
c = a*b
# Return new instance with correctly ordered arguments
return new(q,w,e,r,t,y,a,b,c)
end
end
println(LargeType(r=2,t=5))
Try this:
julia> type foo
a::Int64
b::Int64
c::Int64
foo(a::Int64, b::Int64) = new(a, b, a+b)
end
julia> foo(1,2)
foo(1,2,3)
julia> foo(4,5,6)
no method foo(Int64, Int64, Int64)
However, that won't prevent one from manually changing a, b or c and rendering c inconsistent. To prevent that, if it presents no other problems, you can make foo immutable:
julia> immutable foo
...
There isn't any way to do this currently, but there might be in the future:
https://github.com/JuliaLang/julia/issues/1974