2016-07-03 18 views
1

In Julia kann ich eine Funktion definieren, die alle Subtypen von Type nimmt vonJulia Funktion mit verschiedenen Parametern Subtypen

tun
function foo{T<:Type}(bar::T, arg::T) end 

Aber dies erlegt dass bar und arg die gleichen Subtyp von Type sein. Gibt es eine Abkürzung, um eine Funktion zu definieren, die verschiedene Subtypen von Type für bar und akzeptiert? Ich weiß, ich kann

function foo{T<:Type, S<:Type}(bar::T, arg::S) end 

Aber für eine Funktion mit mehreren Parametern wird es ziemlich umständlich.

+0

nur zu erwähnen, wenn der Typ von 'bar' oder' arg' nicht parametrisch ist, müssen keine parametrischen Methoden verwendet werden. z.B. 'Funktion foo {T <: Ganzzahl} (Balken :: Vektor {T}, arg :: Nummer)' – Gnimuc

+0

@GnimucK. Ich weiß, aber sie sind alle Arrays. – Mauricio

Antwort

3

Wenn der auf der linken Seite von T<:Type verwendete Typ ein abstrakter Typ ist, dann werden die Funktionsargumente, die als Typ T deklariert sind, alle Objekte akzeptieren, die zu dieser Abstraktion gehören, einschließlich zugehöriger Dinge eine untergeordnete (erbende) Abstraktion.

Für die meisten Zwecke sind diese Dinge Realisierungen eines konkreten Typs, Instanziierungen des Typs. Ein konkreter Typ kann einen abstrakten Typ als Obertyp haben, und dieser abstrakte Typ kann einen anderen, abstrakteren Typ als Obertyp haben und so weiter. Any ist der super Supertyp, Wurzel des abstrakten Baumtyps.

Im Beispiel

function foo{T<:Type}(bar::T, arg::T) ... end 

Bei jedem Aufruf von foo nimmt T auf genau einen der Subtypen von Type oder bleibt Type selbst. Deshalb müssen bar und arg den gleichen spezifischen Typ für diese Version von foo teilen, der abgeglichen und aufgerufen werden soll. Und es erklärt, warum das nächste Beispiel Spiele und

function foo{T<:Type, U<:Type}(bar::T, arg::U) ... end 

aufgerufen wird, wenn foo und bar jeweils Subtypen von Type sind aber sind Realisierungen von zwei verschiedenen Betonarten (z Int32 und Int64 Aktien die abstrakte Supertyp Integer).

Es gibt keine allgemeine Kurzschreibweise für die Verwendung von Parametern, mit denen Sie verschiedene Arten von Dingen akzeptieren möchten. dass die verschiedenen Sortierungen einen gemeinsamen abstrakten Typ gemeinsam haben, ist nützliche Information und erlaubt es Ihnen, sowohl die erste als auch die zweite Möglichkeit zu definieren, foo aufzurufen. Diese flexible Art der Verwaltung von algorithmischen Spezifikationen vereinfacht oft die Implementierung. Das ist eine der Stärken, die Julias Multidispatch bietet.

Es gibt Situationen, in denen die Verwendung von typealias das Schreiben einer Funktionssignatur vereinfachen kann. typealias funktioniert gut, um selektiv zu versenden, indem Sie nicht überlappende Sammlungen von Subtypen verwenden, die sich einen Supertyp teilen.

typealias FastInt Union{ Int32, Int64 } # division is fast 
typealias SlowInt Union{ Int8, Int128 } # slightly slower 

foo{T<:Integer}(a::T, b::T) ... end; # default/fallback 
foo{T<:FastInt}(a::T, b::T) ... end; # specialized for fast types 
foo{T<:SlowInt}(a::T, b::T) ... end; # specialized for slow types 

`` `

+0

Also gibt es keine Kurzschrift. Traurig. Ich schreibe wirklich 'Funktion foo {T <: Typ} (bar :: AbstraktArray {T}, arg :: AbstraktArray {T}) end'. Sollte angegeben haben. Trotzdem danke! – Mauricio

2

Ich würde dies einfach schreiben als

function foo(bar::MyType, arg::MyType) 
    ... 
end 

Innerhalb der Funktion, wenn Sie die konkreten Typen benötigen, verwenden typeof(bar) und typeof(arg). Dies sind Konstanten und beeinträchtigen die Leistung nicht.

Natürlich nehme ich an, Sie meinen Type als einen benutzerdefinierten Typ, und nicht den eingebauten Type Typ.

Auch wenn die Argumente Arrays sind, muss die Funktion nicht parametrisch geschrieben werden. Es ist vollkommen in Ordnung

function foo(bar::AbstractArray, arg::AbstractArray) 
    ... 
end 

und innerhalb der Funktion Gebrauch eltype(bar) und eltype(arg) bei Bedarf zu tun. Allerdings würde ich persönlich das parametrische Formular verwenden, wenn die eltype s erforderlich sind.

+0

Ich hätte genauer sein sollen, aber ich schreibe wirklich 'Funktion foo {T <: Typ} (bar :: AbstraktArray {T}, arg :: AbstraktArray {T}) Ende' – Mauricio

+0

@Mauricio: Ja, dann Ich bevorzuge den parametrischen Ansatz. –

+0

Nun, ich dachte, es ging darum, in-function-checks zu vermeiden. Außerdem bin ich mir nicht sicher, wie ich die Dimension angeben soll, ohne den Typ anzugeben, oder fehlt mir da etwas Offensichtliches? – Mauricio

Verwandte Themen