Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Julia: Even-number datatype for functions

Tags:

julia

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.

like image 998
varantir Avatar asked Mar 03 '23 14:03

varantir


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

like image 120
François Févotte Avatar answered Mar 07 '23 05:03

François Févotte


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
like image 43
gggg Avatar answered Mar 07 '23 04:03

gggg