2014-10-30 1 views
0

Установка: Рассмотрим параметрического типа в ДжулииВзаимодействия параметрических типов и множественной диспетчеризации в Джулии

type MyType1{T1} 
    x::T1 
end 

Я определяю два метода для одной функции над этим типом использованием несколько диспетчерских и типа параметров:

f1(m::MyType1, i::Int64) = m.x + i #Method 1 
f1{T1}(m::MyType1, i::T1) = m.x + i + 1 #Method 2 

Способ 1 соответствует случаю, когда второй вход Int64. Метод 2 соответствует случаю, когда второй вход является параметрическим. Я создаю экземпляр MyType1 с использованием m=MyType1{Int64}(1) и обратите внимание, что m.x теперь возвращает 1.

Вопрос 1: Я свидетельствую следующее поведение:

In : f1(m, 1.0) 

Out : 3.0 

Хорошо, так что я не представила никакой информации о T1 в вызове функции. Кажется, Джулия предположила, что она должна выполнить метод 2 на том основании, что второй вход не был a Int64. Это то, как вещи действительно работают под капотом?

Вопрос 2: Предположим, что я хочу назвать второй метод, но со вторым вводом как Int64. Очевидно, что f1(m, 1) не будет работать, так как это вызовет первый метод. Я попытался это:

In : f1{Int64}(m, 1) 

Но Джулия бросает эту ошибку:

ERROR: type: instantiate_type: expected TypeConstructor, got Function 

Можно ли получить второй метод для запуска со вторым входом указанного в Int64, или я глупо?

ответ

3

Прежде всего, мне интересно, должен ли вы иметь первый аргумент во втором методе, введенном как m::MyType1{T1}, например.

f1{T1}(m::MyType1{T1}, i::T1) = m.x + i + 1 #Method 2b 

Это означает, что второй метод будет применим только, если i имеет тот же тип, что и параметр типа из T1 от типа m. С вашим исходным определением T1 будет просто соответствовать любому типу фактического аргумента i, поэтому вы могли бы написать его f1(m::MyType1, i::Any) = ....

1) Использование метода 2b вместо метода 2, я получаю

julia> f1(m, 1.0) 
ERROR: no method f1(MyType1{Int64}, Float64) 

, так как нет никакого метода, который применяется. В вашем оригинальном случае метод 1 не применяется, но метод 2 делает это. Джулия выбирает наиболее специфический метод, который применяется, например. Метод 2. Итак, да, вы можете сказать, что метод 2 выбран потому, что второй вход не был Int64.

2) Явные параметры типа (по крайней мере до сих пор) поддерживаются только типами, а не функциями.Функция invoke позволяет вызывать определенную функцию и выбирать метод на основе заданного (более общего) списка типов аргументов, но я не уверен, что здесь применяется, поскольку для MyType{Int64} эти два метода применяются к точно таким же типам для второй аргумент. В любом случае, не рекомендуется использовать invoke вообще, и я думаю, что это может дать довольно большой штраф.

Если вы действительно хотите, чтобы в этом случае вы могли вызвать метод 2, вы должны найти другой способ, по которому вам не придется бороться с несколькими отправками. Один из вариантов заключается в том, чтобы вытащить реализацию метода 2 в его собственную функцию, например.

f1(m::MyType1, i::Int64)  = m.x + i #Method 1 
f1{T1}(m::MyType1{T1}, i::T1) = g1(m, i) #Method 2b 
g1{T1}(m::MyType1{T1}, i::T1) = m.x + i + 1 

вы можете позвонить g1 напрямую, если вы хотите использовать второй метод.

Btw, любая конкретная причина, по которой вы используете Int64? Если вам явно не нужны 64 бита, используя Int (который является typealiased либо Int32, либо Int64 в зависимости от вашей системы) более Julian и имеет тенденцию взаимодействовать немного лучше с другим кодом.

+1

Вы правы, я пытался реализовать свой метод 2b. Я преобразовываю Matlab, так что все еще изучаю, насколько это касается типов. Нет особых причин для 'Int64'. Я с радостью переключусь на 'Int', если нет удара производительности. Используется ли такое же правило для 'Float' (т. Е. Использовать' Float' вместо 'Float64')? ps Спасибо за ответ + 1 + Tick. Очень ясно, и это именно то, чем я был. –

+2

Нет, для поплавков вам нужно указать 'Float64' или' Float32'. Причина в том, что решение, тип которого используется редко, зависит от типа машины, но требует точности. –