Check if a type implements an interface in Julia - 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?

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.

Can you create a singleton in 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

porting python class to Julialang

I am seeing that Julia explicitly does NOT do classes... and I should instead embrace mutable structs.. am I going down the correct path here?? I diffed my trivial example against an official flux library but cannot gather how do I reference self like a python object.. is the cleanest way to simply pass the type as a parameter in the function??
Python
# Dense Layer
class Layer_Dense
def __init__(self, n_inputs, n_neurons):
self.weights = 0.01 * np.random.randn(n_inputs, n_neurons)
self.biases = np.zeros((1, n_neurons))
def forward(self, inputs):
pass
My JuliaLang version so far
mutable struct LayerDense
num_inputs::Int64
num_neurons::Int64
weights
biases
end
function forward(layer::LayerDense, inputs)
layer.weights = 0.01 * randn(layer.num_inputs, layer.num_neurons)
layer.biases = zeros((1, layer.num_neurons))
end
The flux libraries version of a dense layer... which looks very different to me.. and I do not know what they're doing or why.. like where is the forward pass call, is it here in flux just named after the layer Dense???
source : https://github.com/FluxML/Flux.jl/blob/b78a27b01c9629099adb059a98657b995760b617/src/layers/basic.jl#L71-L111
struct Dense{F, M<:AbstractMatrix, B}
weight::M
bias::B
σ::F
function Dense(W::M, bias = true, σ::F = identity) where {M<:AbstractMatrix, F}
b = create_bias(W, bias, size(W,1))
new{F,M,typeof(b)}(W, b, σ)
end
end
function Dense(in::Integer, out::Integer, σ = identity;
initW = nothing, initb = nothing,
init = glorot_uniform, bias=true)
W = if initW !== nothing
Base.depwarn("keyword initW is deprecated, please use init (which similarly accepts a funtion like randn)", :Dense)
initW(out, in)
else
init(out, in)
end
b = if bias === true && initb !== nothing
Base.depwarn("keyword initb is deprecated, please simply supply the bias vector, bias=initb(out)", :Dense)
initb(out)
else
bias
end
return Dense(W, b, σ)
end
This is an equivalent of your Python code in Julia:
mutable struct Layer_Dense
weights::Matrix{Float64}
biases::Matrix{Float64}
Layer_Dense(n_inputs::Integer, n_neurons::Integer) =
new(0.01 * randn(n_inputs, n_neurons),
zeros((1, n_neurons)))
end
forward(ld::Layer_Dense, inputs) = nothing
What is important here:
here I create an inner constructor only, as outer constructor is not needed; as opposed in the Flux.jl code you have linked the Dense type defines both inner and outer constructors
in python forward function does not do anything, so I copied it in Julia (your Julia code worked a bit differently); note that instead of self one should pass an instance of the object to the function as the first argument (and add ::Layer_Dense type signature so that Julia knows how to correctly dispatch it)
similarly in Python you store only weights and biases in the class, I have reflected this in the Julia code; note, however, that for performance reasons it is better to provide an explicit type of these two fields of Layer_Dense struct
like where is the forward pass call
In the code you have shared only constructors of Dense object are defined. However, in the lines below here and here the Dense type is defined to be a functor.
Functors are explained here (in general) and in here (more specifically for your use case)

Julia: non-destructively update immutable type variable

Let's say there is a type
immutable Foo
x :: Int64
y :: Float64
end
and there is a variable foo = Foo(1,2.0). I want to construct a new variable bar using foo as a prototype with field y = 3.0 (or, alternatively non-destructively update foo producing a new Foo object). In ML languages (Haskell, OCaml, F#) and a few others (e.g. Clojure) there is an idiom that in pseudo-code would look like
bar = {foo with y = 3.0}
Is there something like this in Julia?
This is tricky. In Clojure this would work with a data structure, a dynamically typed immutable map, so we simply call the appropriate method to add/change a key. But when working with types we'll have to do some reflection to generate an appropriate new constructor for the type. Moreover, unlike Haskell or the various MLs, Julia isn't statically typed, so one does not simply look at an expression like {foo with y = 1} and work out what code should be generated to implement it.
Actually, we can build a Clojure-esque solution to this; since Julia provides enough reflection and dynamism that we can treat the type as a sort of immutable map. We can use fieldnames to get the list of "keys" in order (like [:x, :y]) and we can then use getfield(foo, :x) to get field values dynamically:
immutable Foo
x
y
z
end
x = Foo(1,2,3)
with_slow(x, p) =
typeof(x)(((f == p.first ? p.second : getfield(x, f)) for f in fieldnames(x))...)
with_slow(x, ps...) = reduce(with_slow, x, ps)
with_slow(x, :y => 4, :z => 6) == Foo(1,4,6)
However, there's a reason this is called with_slow. Because of the reflection it's going to be nowhere near as fast as a handwritten function like withy(foo::Foo, y) = Foo(foo.x, y, foo.z). If Foo is parametised (e.g. Foo{T} with y::T) then Julia will be able to infer that withy(foo, 1.) returns a Foo{Float64}, but won't be able to infer with_slow at all. As we know, this kills the crab performance.
The only way to make this as fast as ML and co is to generate code effectively equivalent to the handwritten version. As it happens, we can pull off that version as well!
# Fields
type Field{K} end
Base.convert{K}(::Type{Symbol}, ::Field{K}) = K
Base.convert(::Type{Field}, s::Symbol) = Field{s}()
macro f_str(s)
:(Field{$(Expr(:quote, symbol(s)))}())
end
typealias FieldPair{F<:Field, T} Pair{F, T}
# Immutable `with`
for nargs = 1:5
args = [symbol("p$i") for i = 1:nargs]
#eval with(x, $([:($p::FieldPair) for p = args]...), p::FieldPair) =
with(with(x, $(args...)), p)
end
#generated function with{F, T}(x, p::Pair{Field{F}, T})
:($(x.name.primary)($([name == F ? :(p.second) : :(x.$name)
for name in fieldnames(x)]...)))
end
The first section is a hack to produce a symbol-like object, f"foo", whose value is known within the type system. The generated function is like a macro that takes types as opposed to expressions; because it has access to Foo and the field names it can generate essentially the hand-optimised version of this code. You can also check that Julia is able to properly infer the output type, if you parametrise Foo:
#code_typed with(x, f"y" => 4., f"z" => "hello") # => ...::Foo{Int,Float64,String}
(The for nargs line is essentially a manually-unrolled reduce which enables this.)
Finally, lest I be accused of giving slightly crazy advice, I want to warn that this isn't all that idiomatic in Julia. While I can't give very specific advice without knowing your use case, it's generally best to have fields with a manageable (small) set of fields and a small set of functions which do the basic manipulation of those fields; you can build on those functions to create the final public API. If what you want is really an immutable dict, you're much better off just using a specialised data structure for that.
There is also setindex (without the ! at the end) implemented in the FixedSizeArrays.jl package, which does this in an efficient way.

constrain argument to be in a set of values in Julia function signature

Is there a way in Julia to specify that a function argument can take one of a set of values through type annotations? For example, let's say I have function foo which accepts a single argument
function foo(x::String)
print(x)
end
the argument x can only be a String. Is there a way to further constrain it in the function signature so that it can only be for example one of the strings "right", "left", or "center"?
In Julia, the motto should be "There's a type for that!".
One way of handling this would be to create a type with a constructor that only allows the values you want (and possibly stores them in a more efficient manner).
Here is one example:
const directions = ["left", "right", "center"]
immutable MyDirection
Direction::Int8
function MyDirection(str::AbstractString)
i = findnext(directions, str, 1)
i == 0 && throw(ArgumentError("Invalid direction string"))
return new(i)
end
end
Base.show(io::IO, x::MyDirection) = print(io, string("MyDirection(\"",directions[x.Direction],"\")"))
function foo(x::MyDirection)
println(x)
end
function foo(str::AbstractString)
x = MyDirection(str)
println(x)
end
test = MyDirection("left")
foo(test)
foo("right")
Note: my example is written with Julia 0.4!
Edit:
Another approach would be to use symbols, such as :left, :right, and :center,
instead of strings.
These have the advantage of being interned (so that they can be compared simply by comparing their address), and they can also be used directly for type parameters.
For example:
immutable MyDirection{Symbol} ; end
function MyDirection(dir::Symbol)
dir in (:left, :right, :center) || error("invalid direction")
MyDirection{dir}()
end
MyDirection(dir::AbstractString) = MyDirection(symbol(dir))
That will let you do things like:
x = MyDirection("left")
which will create an immutable object of type MyDirection{:left}.
No, it is not. That would be dispatching on values, which isn't possible in Julia.
I'm not sure what your actual application is, but there are some possibly-appropriate workarounds to this, e.g.
abstract Sam81Args
type ArgRight <:Sam81Args end
type ArgLeft <:Sam81Args end
type ArgCenter <:Sam81Args end
function foo{T<:Sam81Args}(x::Type{T})
println(T)
end
foo(ArgCenter)

Resources