Julia: Even-number datatype for functions

Viewed 180

I have about 50 functions which should consume only even positive numbers. Right now I am checking each time with an "if" whether the number put in is zero or not:

function grof(x::Int)
    if (x % 2) == 0
        println("good")
    else
        throw("x is not an even number!!!!!!!!!!!!! Stupid programmer!")
    end
end

Ideally, I would like to have a datatype which produces this automatically, i.e.

function grof(x::EvenInt)
    println("good")  
end

However, I am not able to produce this datatype by my own since I am unable to understand the documentary. Thanks for your help!

Best, v.

2 Answers

I don't think creating a type is warranted in such a situation: I would simply @assert that the condition is verified at the beginning of the function(s). (Funnily enough, checking the whether a number is even is the example that was chosen in the documentation to illustrate the effect of @assert)

For example:

julia> function grof(x::Int)
           @assert iseven(x) "Stupid programmer!"
           println("good")
       end
grof (generic function with 1 method)

julia> grof(2)
good

julia> grof(3)
ERROR: AssertionError: Stupid programmer!
Stacktrace:
 [1] grof(::Int64) at ./REPL[5]:2
 [2] top-level scope at REPL[7]:1




EDIT: If you really want to create a type enforcing such a constraint, it is possible. The way to do this would be to

  1. create a type (possibly subtyping one of the Number abstract types; maybe Signed)
  2. define an inner constructor ensuring that such a type cannot hold an odd value

A very simple example to build upon would be along the lines of:

# A wrapper around an even integer value
struct EvenInt
    val :: Int

    # inner constructor
    function EvenInt(val)
        @assert iseven(val)
        new(val)
    end
end

# Accessor to the value of an EvenInt
val(x::EvenInt) = x.val

# A method working only on even numbers
grof(x::EvenInt) = println("good: $(val(x)) is even")

You'd use this like so:

julia> x = EvenInt(42)
EvenInt(42)

julia> grof(x)
good: 42 is even

julia> y = EvenInt(1)
ERROR: AssertionError: iseven(val)
Stacktrace:
 [1] EvenInt(::Int64) at ./REPL[1]:5
 [2] top-level scope at REPL[6]:1

but note that you can't do anything on EvenInts yet: you need to either unwrap them (using val() in this case), or define operations on them (a task which can be vastly simplified if you make EvenInt a subtype of one of the abstract number types and follow the relevant interface).

All integers multiplied by two are even, so redefine your function to take half the number it currently takes.

function grof2(halfx::Int)
       x=2*halfx
       println("good")
end
Related