Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

julia

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"?

like image 322
sam81 Avatar asked Mar 16 '23 03:03

sam81


2 Answers

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}.

like image 111
Scott Jones Avatar answered Apr 26 '23 23:04

Scott Jones


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)
like image 37
IainDunning Avatar answered Apr 27 '23 01:04

IainDunning