Юлия: Тип данных четного числа для функций - PullRequest
4 голосов
/ 09 апреля 2020

У меня около 50 функций, которые должны использовать только положительные числа. Прямо сейчас я каждый раз проверяю «если», является ли введенное число нулевым или нет:

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

В идеале, я хотел бы иметь тип данных, который производит это автоматически, то есть

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

Однако я не могу самостоятельно создать этот тип данных, так как не могу понять документальный фильм . Спасибо за вашу помощь!

Best, v.

Ответы [ 2 ]

3 голосов
/ 10 апреля 2020

Все целые числа, умноженные на два, четные, поэтому переопределите вашу функцию, чтобы взять половину числа, которое она в настоящее время занимает.

function grof2(halfx::Int)
       x=2*halfx
       println("good")
end
3 голосов
/ 09 апреля 2020

Я не думаю, что создание типа оправдано в такой ситуации: я бы просто @assert подтвердил, что условие проверено в начале функции (ей). (Как ни странно, проверка того, является ли число четным, является примером, выбранным в документации для иллюстрации эффекта @assert)

Например:

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

РЕДАКТИРОВАТЬ: Если вы действительно хотите создать тип, обеспечивающий такое ограничение, это возможно. Способ сделать это -

  1. создать тип (возможно, подтипить один из Number абстрактных типов; возможно, Signed)
  2. определить внутренний конструктор, гарантирующий, что такой тип не может содержать нечетное значение

Очень простой пример, на котором можно основываться, будет выглядеть следующим образом:

# 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")

Вы бы использовали это так:

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

но учтите, что вы ничего не можете сделать на EvenInt с: вам нужно либо развернуть их (в данном случае используя val()), либо определить операции над ними (задача, которая может быть очень упрощается, если вы сделаете EvenInt подтипом одного из типов абстрактных чисел и будете следовать соответствующему интерфейсу).

...