サーチ…


構文

  • a、
  • a、b
  • a、b = xs
  • ()
  • (a、b)
  • (a、b)
  • (a、b ...)
  • タプル{T、U、V}
  • NTuple {N、T}
  • タプル{T、U、Vararg {V}}

備考

タプルは、2つの理由から、 配列よりもはるかに優れたランタイム・パフォーマンスを備えています。その型はより正確であり、その不変性により、ヒープではなくスタックに割り当てられます。しかし、このより正確な型定義には、コンパイル時のオーバーヘッドが増え、 型の安定性を達成するのが難しくなります。

タプルの紹介

Tupleは、同じ型または異なるの任意の異なるオブジェクトの不変の順序付けられたコレクションです。通常、タプルは(x, y)構文を使用して作成されます。

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

タプルの個々のオブジェクトは、インデックス構文を使用して取得できます。

julia> tup[1]
1

julia> tup[2]
1.0

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

iterableインタフェースを実装しているので、 forループを使っfor反復することができます

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

タプルは、 reverseまたはlengthなどのさまざまな汎用コレクション関数もサポートしています。

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

julia> length(tup)
3

さらに、タプルは、 anyallmap 、またはbroadcastを含むさまざまな高次コレクション操作をサポートしmap

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

空のタプルは、 ()を使って作ることができます:

julia> ()
()

julia> isempty(ans)
true

ただし、1つの要素のタプルを作成するには、末尾にカンマが必要です。これは、タプルを構築するのではなく、カッコ( (および) )をまとめてグループ化操作として扱うためです。

julia> (1)
1

julia> (1,)
(1,)

一貫性を保つために、複数の要素を持つタプルに対しても末尾のカンマを使用できます。

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

タプルタイプ

typeofタプルのサブタイプであるTuple

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

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

他のデータ型とは異なり、 Tuple型は共変です。 Juliaの他のデータ型は一般的に不変です。このように、

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

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

これは、 Tuple{Number, Number}どこでも受け入れられ、 Tuple{Int, Int}も2つの要素を持ち、両方とも数値であるためです。つまりには当てはまらないVector{Int}Vector{Number}受け付ける機能として、 Vector{Number}浮動小数点を格納することを望むかもしれない(例えば、 1.0 )または複素数(例えば1+3imように)ベクトル。

タプル型の共分散は、 Tuple{Number} (これはVector{Number}とは異なりVector{Number} )が実際に抽象型であることを意味します。

julia> isleaftype(Tuple{Number})
false

julia> isleaftype(Vector{Number})
true

Tuple{Number}具体的なサブタイプには、 Tuple{Int}Tuple{Float64}Tuple{Rational{BigInt}}などがあります。

Tuple型は、無限の数のオブジェクトを示す最後のパラメータとして終了Varargを含むことがあります。たとえば、 Tuple{Vararg{Int}}は、任意の数のIntを含むすべてのタプルの型であり、おそらくゼロです。

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

Tuple{String, Vararg{Int}}文字列とそれに続く任意の数(おそらくゼロ)のIntからなるタプルを受け入れます。

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

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

共分散と組み合わせると、 Tuple{Vararg{Any}}は任意のタプルを記述することを意味します。確かに、 Tuple{Vararg{Any}}というのがもうひとつの方法であるTuple

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

Varargは、第1の型パラメータが何回出現すべきかを示す第2の数値型パラメータを受け取ります。 (デフォルトでは、指定されていない場合、この第二のタイプのパラメータは、任意の数の理由で任意の値をとることができるtypevar、あるInt sはに受け入れられVararg sを超える。) Tuple指定で終わるタイプVararg自動的に展開されるであろうが要求された要素の数:

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

指定されたVarargNTuple{N, T}持つ均質タプルの表記法が存在する。この表記では、 Nはタプル内の要素の数を表し、 Tは受け入れられた型を表します。例えば、

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)

ことに留意されたいNTupleの特定のサイズを超えては、単にとして示されているNTuple{N, T}代わり拡大の、 Tuple形態が、それらは依然として同じタイプです。

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

タプル型のディスパッチ

Julia関数のパラメータリスト自体がタプルであるため 、さまざまな種類のタプルにディスパッチすることは、しばしばメソッドパラメータ自体を使用する方が簡単で、しばしば "splatting"演算子の自由な使用が容易... 。例えば、 Baseからのタプルのreverseの実装を考えてみましょう。

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

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

この方法でタプルにメソッドを実装すると、パフォーマンスにとって重要な型の安定性が維持されます。 @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}

読みにくいですが、ここでのコードは元のタプルの3番目、2番目、1番目の値を持つ新しいタプルを作成することです。多くのマシンでは、ロードとストアで構成される非常に効率的なLLVMコードにコンパイルされます。

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
}

複数の戻り値

タプルは、複数の戻り値に対して頻繁に使用されます。 イテラブルインタフェースの 2つの関数( nextdone )を含む標準ライブラリの多くは、2つの関連しているが異なる値を含むタプルを返します。

タプルの周りのカッコは、特定の状況では省略することができ、複数の戻り値を実装しやすくします。例えば、実数の正と負の平方根の両方を返す関数を作ることができます:

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

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

destructuring代入を使用して、複数の戻り値をアンパックすることができます。変数abに平方根を格納するには、次のように書いてください。

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

julia> a
3.0

julia> b
-3.0

これの別の例は、 divremfldmod行う機能、 (それぞれ切り捨て又は床の)整数除算同時に及び剰余演算を:

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
ライセンスを受けた CC BY-SA 3.0
所属していない Stack Overflow