Can you create a singleton in Julia? - julia

I know that Julia does not have OOP but that multiple dispatch enables similar ideas. Given how seemingly contentious the use of singletons are in Python, I am wondering if there is a similar idea Julia (i.e. a struct that can only be instantiated once).
I am wondering if there's a way to have the constructor keep track of the number of times an object was instantiated with a global var or something like that? Or it's altogether not be possible?

The main way people make singletons in Julia is to define an empty struct (which means that it has 0 size), and define methods that return information for it.
struct Singleton
end
data(::Singleton) = "whatever you want it to do"
etc.

From this book, a singleton can be defined as a type without fields:
struct MySingleton end
julia> MySingleton() === MySingleton()
true
You can also use Val, which can receive any value (of bit type):
julia> Val(1) === Val(1)
true
julia> Val(:foo) === Val(:foo)
true
using Val you can write something like this:
julia> do_something(::Val{:asymbol}) = println("foo")
julia> do_something(::Val{:anothersymbol}) = println("bar")
julia> do_something(s::String) = do_something(Val{Symbol(s)})
julia> do_something("asymbol")
foo
The definition of Val is:
struct Val{x} end
So, for a more clear readability of your code, you could define your own singleton type as, for example:
struct Command{x} end

Related

Julia Macro to Save the Overt form of a Function, and Define it

Some of the parameters to a simulation I am writing are functions. When the output is generated, I want to put the definition of these functional parameters in the output. I have in mind a macro that somehow saves the definition as a string, and then defines it. For example, here's what I do now:
borda_score_fn(p) = exp(1/p)
global g_borda_score_fn_string = "exp(1/p)"
And then I write g_borda_score_fn_string to my output. But this is really ugly!
What I would like to do is something like this:
#paramfn borda_score_fn(p) = exp(1/p)
And later be able to both call borda_score_fn(p), and have the form (i.e., "exp(1/p)") available for writing to my output log. (The string form might get stashed in a global dict, actually, they both could.)
I have tried many version of this, but can't get the right set of parses and calls to get it to work. Any help would be appreciated.
This may be a bit different than what you have in mind, but one perhaps "Julian" approach might be to have the function itself return the form string via multiple dispatch, rather than defining a whole new global variable just for that. For example, say we have a type
struct Form end
that we can use for dispatch, then we can write
borda_score_fn(p) = exp(1/p)
borda_score_fn(::Form) = "exp(1/p)"
which can then be retrieved just by calling the function with our type
julia> borda_score_fn(2)
1.6487212707001282
julia> borda_score_fn(Form())
"exp(1/p)"
That might actually be not bad on its own. But, if you want a macro to do both parts at once, then something along the lines of
macro paramfn(e)
name = esc(e.args[1].args[1])
str = string(e.args[2].args[2])
f = esc(e)
quote
$name(::Form) = $str
$f
end
end
would let you write
julia> #paramfn borda_score_fn(p) = exp(1/p)
borda_score_fn (generic function with 2 methods)
julia> borda_score_fn(1)
2.718281828459045
julia> borda_score_fn(Form())
"exp(1 / p)"
For completeness, here's how you can do it in a way more similar to your original approach, but more idiomatically than with a global variable:
julia> module FormOf
export formof, #paramfn
function formof end
macro paramfn(expr)
name = esc(expr.args[1].args[1])
form_str = string(expr.args[2].args[2])
quote
$(esc(expr))
$FormOf.formof(::typeof($name)) = $form_str
$name
end
end
end
Main.FormOf
julia> FormOf.#paramfn borda_score_fn(p) = exp(1/p)
borda_score_fn (generic function with 1 method)
julia> FormOf.formof(borda_score_fn)
"exp(1 / p)"
However, since it defines a new method of FormOf.formof, this only works in global scope:
julia> function bla()
FormOf.#paramfn fn(p) = exp(1/p)
fn(10) + 1
end
ERROR: syntax: Global method definition around REPL[45]:10 needs to be placed at the top level, or use "eval".
Stacktrace:
[1] top-level scope
# REPL[50]:1
#cbk's solution does not have this limitation.

Julia: Override method to add functionality

I would like to extend an abstract type's method in a concrete type.
I can do it with a new method but this introduces more complexity:
abstract type AbstractTask end
function complete(task::AbstractTask)
complete_concrete_task(task)
println("Done!")
end
struct Task <: AbstractTask
name::String
end
complete_concrete_task(task::Task) = println(task.name)
coding = Task("coding")
complete(coding)
In Python, I would use the super operator. Is there an equivalent in Julia?
Thanks in advance!
I would say that using dispatch the way you did introduces much less cognitive complexity than a call to super. But you can use invoke select methods of supertypes:
julia> abstract type AbstractTask end
julia> function complete(task::AbstractTask)
println("Done!")
end
complete (generic function with 1 method)
julia> struct Task <: AbstractTask
name::String
end
julia> complete(task::Task) = (println(task.name); invoke(complete, Tuple{AbstractTask}, task))
complete (generic function with 2 methods)
julia> coding = Task("coding")
Task("coding")
julia> complete(coding)
coding
Done!
Of course this requires you not to forget to add it to every subtype method, which is the additional complexity I mean.
The good thing is that invoke with a constant type parameter will be compiled away (or so I have read), so there's not even overhead from dispatch.

How to hard code struct variables in Julia?

I have a Julia struct:
struct WindChillCalc
location::Tuple;
w_underground_url::String;
WindChillCalc(location, wug) = new(location, w_underground_url);
end
How do I hard code w_underground_url to contain "someString" upon the constructor of WindChillCalc being called?
Try something like below
struct testStruct
x::Real
y::String
testStruct(x,y) = new(x,"printThis")
end
test = testStruct(1,"")
test2 = testStruct(2,"")
println(test.y)
println(test2.y)
It prints "printThis" for any object.
Just write for example:
struct WindChillCalc{T}
location::T;
w_underground_url::String;
WindChillCalc(location::T) where {T <: NTuple{2, Real}} =
new{T}(location, "some string");
end
and now Julia automatically creates a concrete type for you:
julia> WindChillCalc((1, 2.5))
WindChillCalc{Tuple{Int64,Float64}}((1, 2.5), "some string")
Note that I have restricted the type of the parameter to be a two element tuple where each element is a Real. You could of course use another restriction (or use no restriction).
With this approach your code will be fast as during compile time Julia will know exact types of all fields in your struct.

How to define a constant in Julia struct

I want to define a struct:
struct unit_SI_gen
x::Float32
const c = 2.99792458e8
speed(x)=c*x
end
However, it raise an error :
syntax: "c = 2.99792e+08" inside type definition is reserved
I know I cant use struct as class in python, but I can not find how to solve this problem.
How to define a constant in struct ?
Given I agree with what was said above about normal usage of struct in Julia, it is actually possible to define what was requested in the question using an inner constructor:
struct unit_SI_gen{F} # need a parametric type to make it fast
x::Float32
c::Float64 # it is a constant across all unit_SI_gen instances
speed::F # it is a function
function unit_SI_gen(x)
c = 2.99792458e8
si(x) = c*x
new{typeof(si)}(x, c, si)
end
end
I second #Tasos's comment, you should probably make yourself familiar with Julia's structs first. The relevant part of the documentation is probably here.
Since you declared your struct as struct (in contrast to mutable struct) it is immutable and hence all (immutable) fields of the struct are constants in the sense that they can't be changed.
julia> struct A
x::Int
end
julia> a = A(3)
A(3)
julia> a.x = 4
ERROR: type A is immutable
Stacktrace:
[1] setproperty!(::A, ::Symbol, ::Int64) at .\sysimg.jl:19
[2] top-level scope at none:0
Note, that they get their unchangeable value in the construction process and not in the struct definition.
Also, methods should generally live outside of the struct definition.

Check if a type implements an interface in Julia

How to check that a type implements an interface in Julia?
For exemple iteration interface is implemented by the functions start, next, done.
I need is to have a specialization of a function depending on wether the argument type implements a given interface or not.
EDIT
Here is an example of what I would like to do.
Consider the following code:
a = [7,8,9]
f = 1.0
s = Set()
push!(s,30)
push!(s,40)
function getsummary(obj)
println("Object of type ", typeof(obj))
end
function getsummary{T<:AbstractArray}(obj::T)
println("Iterable Object starting with ", next(obj, start(obj))[1])
end
getsummary(a)
getsummary(f)
getsummary(s)
The output is:
Iterable Object starting with 7
Object of type Float64
Object of type Set{Any}
Which is what we would expect since Set is not an AbstractArray. But clearly my second method only requires the type T to implement the iteration interface.
my issue isn't only related to the iteration interface but to all interfaces defined by a set of functions.
EDIT-2
I think my question is related to
https://github.com/JuliaLang/julia/issues/5
Since we could have imagined something like T<:Iterable
Typically, this is done with traits. See Traits.jl for one implementation; a similar approach is used in Base to dispatch on Base.iteratorsize, Base.linearindexing, etc. For instance, this is how Base implements collect using the iteratorsize trait:
"""
collect(element_type, collection)
Return an `Array` with the given element type of all items in a collection or iterable.
The result has the same shape and number of dimensions as `collection`.
"""
collect{T}(::Type{T}, itr) = _collect(T, itr, iteratorsize(itr))
_collect{T}(::Type{T}, itr, isz::HasLength) = copy!(Array{T,1}(Int(length(itr)::Integer)), itr)
_collect{T}(::Type{T}, itr, isz::HasShape) = copy!(similar(Array{T}, indices(itr)), itr)
function _collect{T}(::Type{T}, itr, isz::SizeUnknown)
a = Array{T,1}(0)
for x in itr
push!(a,x)
end
return a
end
See also Mauro Werder's talk on traits.
I would define a iterability(::T) trait as follows:
immutable Iterable end
immutable NotIterable end
iterability(T) =
if method_exists(length, (T,)) || !isa(Base.iteratorsize(T), Base.HasLength)
Iterable()
else
NotIterable()
end
which seems to work:
julia> iterability(Set)
Iterable()
julia> iterability(Number)
Iterable()
julia> iterability(Symbol)
NotIterable()
you can check whether a type implements an interface via methodswith as follows:
foo(a_type::Type, an_interface::Symbol) = an_interface ∈ [i.name for i in methodswith(a_type, true)]
julia> foo(EachLine, :done)
true
but I don't quite understand the dynamic dispatch approach you mentioned in the comment, what does the generic function looks like? what's the input & output of the function? I guess you want something like this?
function foo(a_type::Type, an_interface::Symbol)
# assume bar baz are predefined
if an_interface ∈ [i.name for i in methodswith(a_type, true)]
# call function bar
else
# call function baz
end
end
or some metaprogramming stuff to generate those functions respectively at compile time?

Resources