Где "не подтип" в сигнатуре функции в Юлии - PullRequest
1 голос
/ 28 октября 2019

Я хочу иметь функцию, которая принимает все, кроме определенного типа. Грубо говоря, что-то вроде

function f(y::X) where y<:setdiff(Any,Real)
    return y
end

Есть ли оператор «не подтип», который действует как противоположность <:? Есть ли другой способ добиться этого?

Редактировать: Это неправильно и не обязательно понимать вопрос или ответы и поэтому поражено: Причина в том, что я хочу иметь конкретный метод функции fдля любого реального и общего для любого произвольного объекта. Проблема в том, что если я просто оставлю эту сигнатуру функции как where y, то она будет специализировать общую функцию как тип Float64, который более специфичен, чем функция, которую я написал для любых вещественных чисел (where y<:Real).

Ответы [ 2 ]

2 голосов
/ 28 октября 2019

Оператор «не подтип» действительно существует (это >:), но вам не нужен этот оператор для решения вашей проблемы.

Если вы просто хотите использовать универсальный метод для всех типов,и специфично для подтипов Real, тогда вы должны сделать:

f(x::Any) = 1
f(x::Real) = 2

Первый метод идентичен простому добавлению сигнатуры любого типа (например, f(x) = 1), и эта функция будет работать как запасной вариант для всехтипы аргументов. Тем не менее, поскольку Real является более точным, чем Any, второй метод будет использоваться вместо первого, если входное значение будет Real:

julia> f("Hello, world!"), f(0x01), f(1 + 2im), f(true)
(1, 2, 1, 2)

Обратите внимание, что вы получаете максимальную производительность независимо от -Независимо от того, какую сигнатуру типа вы указали в определении метода, когда метод на самом деле работает, он будет скомпилирован в конкретную версию в зависимости от конкретных типов ввода.

1 голос
/ 28 октября 2019

На самом деле вы можете самостоятельно реализовать оператор «не подтипа», используя dispatch:

notasubtype(::Type{T1}, ::Type{T2}) where {T2, T1 <: T2} = false
notasubtype(::Type, ::Type) = true

julia> notasubtype(Int, Bool)
true

julia> notasubtype(Bool, Integer)
false

julia> notasubtype(Bool, Real)
false

julia> notasubtype(Bool, Array)
true

Но это позволит вам определять отношение только во время выполнения, а не как ограничение типа. С другой стороны, поскольку мы показали, что это возможно, мы можем повторно использовать тот же принцип в конкретной функции:

f(x::T) where {T<:Real} = ... # T a subtype of Real 
f(x::T) where {T} = ...       # T not a subtype of Real

, которую вы можете написать в более простых эквивалентных терминах, как это сделал Джейкоб:

f(x::Any) = ...
f(x::Real) = ...

(Порядок не имеет значения.)

...