Zoeken…


Syntaxis

  • een,
  • a, b
  • a, b = xs
  • ()
  • (een,)
  • (a, b)
  • (a, b ...)
  • Tuple {T, U, V}
  • NTuple {N, T}
  • Tuple {T, U, Vararg {V}}

Opmerkingen

Tuples hebben veel betere runtime-prestaties dan arrays om twee redenen: hun typen zijn preciezer en hun onveranderlijkheid stelt hen in staat om op de stapel te worden geplaatst in plaats van op de hoop. Echter, dit nauwkeuriger typen wordt geleverd met zowel meer compile-time overhead en meer moeite met het bereiken van het type stabiliteit .

Introductie tot Tuples

Tuple zijn onveranderlijke geordende collecties van willekeurig verschillende objecten, van hetzelfde type of van verschillende types . Typisch worden tupels geconstrueerd met behulp van de (x, y) syntaxis.

julia> tup = (1, 1.0, "Hello, World!")
(1,1.0,"Hello, World!")

De individuele objecten van een tuple kunnen worden opgehaald met behulp van indexeringssyntaxis:

julia> tup[1]
1

julia> tup[2]
1.0

julia> tup[3]
"Hello, World!"

Ze implementeren de iterabele interface en kunnen daarom worden herhaald met behulp van for loops :

julia> for item in tup
           println(item)
       end
1
1.0
Hello, World!

Tuples ondersteunen ook een aantal generieke verzamelfuncties, zoals reverse of length :

julia> reverse(tup)
("Hello, World!",1.0,1)

julia> length(tup)
3

Verder tupels ondersteuning van een verscheidenheid van hogere orde collecties operaties, met inbegrip van any , all , map , of broadcast :

julia> map(typeof, tup)
(Int64,Float64,String)

julia> all(x -> x < 2, (1, 2, 3))
false

julia> all(x -> x < 4, (1, 2, 3))
true

julia> any(x -> x < 2, (1, 2, 3))
true

De lege tuple kan worden opgebouwd met () :

julia> ()
()

julia> isempty(ans)
true

Om echter een tuple van één element te construeren, is een volgkomma vereist. Dit komt omdat de haakjes ( ( en ) ) anders zouden worden behandeld als groepeerbewerkingen in plaats van een tuple te construeren.

julia> (1)
1

julia> (1,)
(1,)

Voor de consistentie is een volgkomma ook toegestaan voor tupels met meer dan één element.

julia> (1, 2, 3,)
(1,2,3)

Tuple-typen

De typeof een tupel is een subtype van Tuple :

julia> typeof((1, 2, 3))
Tuple{Int64,Int64,Int64}

julia> typeof((1.0, :x, (1, 2)))
Tuple{Float64,Symbol,Tuple{Int64,Int64}}

In tegenstelling tot andere gegevenstypen zijn Tuple typen covariant . Andere gegevenstypen in Julia zijn over het algemeen invariant. Dus,

julia> Tuple{Int, Int} <: Tuple{Number, Number}
true

julia> Vector{Int} <: Vector{Number}
false

Dit is het geval omdat overal een Tuple{Number, Number} wordt geaccepteerd, net als een Tuple{Int, Int} , omdat deze ook twee elementen heeft, die beide getallen zijn. Dat is niet het geval voor een Vector{Int} versus een Vector{Number} , omdat een functie die een Vector{Number} accepteert misschien een drijvend punt (bijvoorbeeld 1.0 ) of een complex nummer (bijvoorbeeld 1+3im ) wil 1+3im in zo'n een vector.

De covariantie van tuple-typen betekent dat Tuple{Number} (opnieuw in tegenstelling tot Vector{Number} ) eigenlijk een abstract type is:

julia> isleaftype(Tuple{Number})
false

julia> isleaftype(Vector{Number})
true

Concrete subtypen van Tuple{Number} zijn Tuple{Int} , Tuple{Float64} , Tuple{Rational{BigInt}} , enzovoort.

Tuple typen kunnen een afsluitende Vararg bevatten als hun laatste parameter om een onbeperkt aantal objecten aan te geven. Tuple{Vararg{Int}} is bijvoorbeeld het type van alle tupels die een willekeurig aantal Int s bevatten, mogelijk nul:

julia> isa((), Tuple{Vararg{Int}})
true

julia> isa((1,), Tuple{Vararg{Int}})
true

julia> isa((1,2,3,4,5), Tuple{Vararg{Int}})
true

julia> isa((1.0,), Tuple{Vararg{Int}})
false

terwijl Tuple{String, Vararg{Int}} tupels bestaande uit een string accepteert, gevolgd door een willekeurig aantal (mogelijk nul) Int s.

julia> isa(("x", 1, 2), Tuple{String, Vararg{Int}})
true

julia> isa((1, 2), Tuple{String, Vararg{Int}})
false

Gecombineerd met co-variantie betekent dit dat Tuple{Vararg{Any}} elke tuple beschrijft. Tuple{Vararg{Any}} is inderdaad gewoon een andere manier om Tuple zeggen:

julia> Tuple{Vararg{Any}} == Tuple
true

Vararg accepteert een tweede parameter van het numerieke type die aangeeft hoe vaak de parameter van het eerste type precies moet voorkomen. (Standaard is deze parameter van het tweede type, indien niet gespecificeerd, een typevar die elke waarde kan hebben, daarom wordt een willekeurig aantal Int 's geaccepteerd in de Vararg 's hierboven.) Tuple die eindigen op een opgegeven Vararg worden automatisch uitgebreid naar de gevraagde aantal elementen:

julia> Tuple{String,Vararg{Int, 3}}
Tuple{String,Int64,Int64,Int64}

Er bestaat notatie voor homogene tupels met een opgegeven Vararg : NTuple{N, T} . In deze notatie geeft N het aantal elementen in de tuple aan en geeft T het geaccepteerde type aan. Bijvoorbeeld,

julia> NTuple{3, Int}
Tuple{Int64,Int64,Int64}

julia> NTuple{10, Int}
NTuple{10,Int64}

julia> ans.types
svec(Int64,Int64,Int64,Int64,Int64,Int64,Int64,Int64,Int64,Int64)

Merk op dat NTuple 's boven een bepaalde grootte eenvoudig worden weergegeven als NTuple{N, T} , in plaats van de uitgebreide Tuple vorm, maar ze zijn nog steeds van hetzelfde type:

julia> Tuple{Int,Int,Int,Int,Int,Int,Int,Int,Int,Int}
NTuple{10,Int64}

Verzending op tuple types

Omdat de functieparameterlijsten van Julia zelf tuples zijn, is het verzenden van verschillende soorten tuples vaak eenvoudiger via de methodeparameters zelf, vaak met liberaal gebruik voor de "splatting" ... -operator. Overweeg bijvoorbeeld de implementatie van reverse voor tupels, van Base :

revargs() = ()
revargs(x, r...) = (revargs(r...)..., x)

reverse(t::Tuple) = revargs(t...)

Implementatie van methoden op tupels op deze manier behoudt de stabiliteit van het type , wat cruciaal is voor de prestaties. We kunnen zien dat er geen overhead is aan deze benadering met behulp van de macro @code_warntype :

julia> @code_warntype reverse((1, 2, 3))
Variables:
  #self#::Base.#reverse
  t::Tuple{Int64,Int64,Int64}

Body:
  begin 
      SSAValue(1) = (Core.getfield)(t::Tuple{Int64,Int64,Int64},2)::Int64
      SSAValue(2) = (Core.getfield)(t::Tuple{Int64,Int64,Int64},3)::Int64
      return (Core.tuple)(SSAValue(2),SSAValue(1),(Core.getfield)(t::Tuple{Int64,Int64,Int64},1)::Int64)::Tuple{Int64,Int64,Int64}
  end::Tuple{Int64,Int64,Int64}

Hoewel enigszins moeilijk te lezen, wordt de code hier eenvoudigweg een nieuwe tuple gemaakt met respectievelijk de waarden 3e, 2e en 1e elementen van de oorspronkelijke tuple. Op veel machines komt dit neer op een uiterst efficiënte LLVM-code, die bestaat uit ladingen en opslag.

julia> @code_llvm reverse((1, 2, 3))

define void @julia_reverse_71456([3 x i64]* noalias sret, [3 x i64]*) #0 {
top:
  %2 = getelementptr inbounds [3 x i64], [3 x i64]* %1, i64 0, i64 1
  %3 = getelementptr inbounds [3 x i64], [3 x i64]* %1, i64 0, i64 2
  %4 = load i64, i64* %3, align 1
  %5 = load i64, i64* %2, align 1
  %6 = getelementptr inbounds [3 x i64], [3 x i64]* %1, i64 0, i64 0
  %7 = load i64, i64* %6, align 1
  %.sroa.0.0..sroa_idx = getelementptr inbounds [3 x i64], [3 x i64]* %0, i64 0, i64 0
  store i64 %4, i64* %.sroa.0.0..sroa_idx, align 8
  %.sroa.2.0..sroa_idx1 = getelementptr inbounds [3 x i64], [3 x i64]* %0, i64 0, i64 1
  store i64 %5, i64* %.sroa.2.0..sroa_idx1, align 8
  %.sroa.3.0..sroa_idx2 = getelementptr inbounds [3 x i64], [3 x i64]* %0, i64 0, i64 2
  store i64 %7, i64* %.sroa.3.0..sroa_idx2, align 8
  ret void
}

Meerdere retourwaarden

Tuples worden vaak gebruikt voor meerdere retourwaarden. Veel van de standaard bibliotheek, inclusief twee van de functies van de iterable-interface ( next en done ) terug tupels met twee verwante, maar verschillende waarden.

De haakjes rond tupels kunnen in bepaalde situaties worden weggelaten, waardoor meerdere retourwaarden gemakkelijker kunnen worden geïmplementeerd. We kunnen bijvoorbeeld een functie maken om zowel positieve als negatieve vierkantswortels van een reëel getal terug te geven:

julia> pmsqrt(x::Real) = sqrt(x), -sqrt(x)
pmsqrt (generic function with 1 method)

julia> pmsqrt(4)
(2.0,-2.0)

Destructureringstoewijzing kan worden gebruikt om de meerdere retourwaarden uit te pakken. Om de vierkantswortels op te slaan in variabelen a en b , volstaat het om te schrijven:

julia> a, b = pmsqrt(9.0)
(3.0,-3.0)

julia> a
3.0

julia> b
-3.0

Een ander voorbeeld hiervan zijn de divrem en fldmod functies, die tegelijkertijd een integer (afkappend of gevloerd) deling en fldmod uitvoeren:

julia> q, r = divrem(10, 3)
(3,1)

julia> q
3

julia> r
1


Modified text is an extract of the original Stack Overflow Documentation
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow