列挙
下記URLから引用し、日本語訳をつけてみました。
https://docs.swift.org/swift-book/documentation/the-swift-programming-language/enumerations
Model custom types that define a list of possible values.
可能な値のリストを定義するカスタム タイプをモデル化します。
An enumeration defines a common type for a group of related values and enables you to work with those values in a type-safe way within your code.
列挙は、関連する値のグループに共通の型を定義し、コード内でタイプセーフな方法でそれらの値を操作できるようにします。
If you are familiar with C, you will know that C enumerations assign related names to a set of integer values. Enumerations in Swift are much more flexible, and don’t have to provide a value for each case of the enumeration. If a value (known as a raw value) is provided for each enumeration case, the value can be a string, a character, or a value of any integer or floating-point type.
C に精通している場合は、C の列挙型が一連の整数値に関連する名前を割り当てることがわかるでしょう。 Swift の列挙ははるかに柔軟であり、列挙の各ケースに値を指定する必要はありません。 各列挙のケースに値(生の値と呼ばれる)が指定されている場合、その値は文字列、文字、または任意の整数または浮動小数点型の値にすることができます。
Alternatively, enumeration cases can specify associated values of any type to be stored along with each different case value, much as unions or variants do in other languages. You can define a common set of related cases as part of one enumeration, each of which has a different set of values of appropriate types associated with it.
あるいは、他の言語の共用体やバリアントと同様に、列挙型ケースでは、さまざまなケース値ごとに保存される任意の型の関連値を指定できます。 関連するケースの共通セットを 1 つの列挙の一部として定義できます。各ケースには、適切なタイプの異なる値のセットが関連付けられています。
Enumerations in Swift are first-class types in their own right. They adopt many features traditionally supported only by classes, such as computed properties to provide additional information about the enumeration’s current value, and instance methods to provide functionality related to the values the enumeration represents. Enumerations can also define initializers to provide an initial case value; can be extended to expand their functionality beyond their original implementation; and can conform to protocols to provide standard functionality.
Swift の列挙型は、それ自体が最初のクラスの型です。 これらは、列挙型の現在の値に関する追加情報を提供する計算プロパティや、列挙型が表す値に関連する機能を提供するインスタンス メソッドなど、従来クラスによってのみサポートされていた多くの機能を採用しています。 列挙型では、初期ケース値を提供するイニシャライザを定義することもできます。 元の実装を超えて機能を拡張するために拡張できます。 プロトコルに準拠して標準機能を提供できます。
For more about these capabilities, see Properties, Methods, Initialization, Extensions, and Protocols.
これらの機能の詳細については、「プロパティ」、「メソッド」、「初期化」、「拡張機能」、「プロトコル」をご覧ください。
Enumeration Syntax
列挙構文
You introduce enumerations with the enum
keyword and place their entire definition within a pair of braces:
enum
キーワードを使用して列挙を導入し、定義全体を中括弧の中に置きます。
enum SomeEnumeration {
// enumeration definition goes here
}
Here’s an example for the four main points of a compass:
羅針盤の 4 つの主要な方位の例を次に示します。
enum CompassPoint {
case north
case south
case east
case west
}
The values defined in an enumeration (such as north
, south
, east
, and west
) are its enumeration cases. You use the case
keyword to introduce new enumeration cases.
列挙で定義された値(north
、south
、east
、west
など)がその列挙ケースです。 新しい列挙ケースを導入するには、case
キーワードを使用します。
Note
注釈
Swift enumeration cases don’t have an integer value set by default, unlike languages like C and Objective-C. In the CompassPoint
example above, north
, south
, east
and west
don’t implicitly equal 0
, 1
, 2
and 3
. Instead, the different enumeration cases are values in their own right, with an explicitly defined type of CompassPoint
.
Swift の列挙ケースには、C や Objective-C などの言語とは異なり、デフォルトでは整数値が設定されていません。 上記の CompassPoint
の例では、north
、south
、east
、west
が暗黙的に 0
、1
、2
、3
に等しいわけではありません。代わりに、明示的に定義されたタイプの CompassPoint
を使用して、さまざまな列挙ケースがそれ自体の値になります。
Multiple cases can appear on a single line, separated by commas:
複数のケースをカンマで区切って 1 行に記述することができます。
enum Planet {
case mercury, venus, earth, mars, jupiter, saturn, uranus, neptune
}
Each enumeration definition defines a new type. Like other types in Swift, their names (such as CompassPoint
and Planet
) start with a capital letter. Give enumeration types singular rather than plural names, so that they read as self-evident:
各列挙定義は新しい型を定義します。 Swift の他のタイプと同様に、それらの名前 (CompassPoint
や Planet
など) は大文字で始まります。 列挙型に複数名ではなく単数名を付けて、それが自明であるようにします。
var directionToHead = CompassPoint.west
The type of directionToHead
is inferred when it’s initialized with one of the possible values of CompassPoint
. Once directionToHead
is declared as a CompassPoint
, you can set it to a different CompassPoint
value using a shorter dot syntax:
directionToHead
のタイプは、CompassPoint
の可能な値の 1 つで初期化されるときに推測されます。 directionToHead
を CompassPoint
として宣言したら、より短いドット構文を使用して別の CompassPoint
値に設定できます。
directionToHead = .east
The type of directionToHead
is already known, and so you can drop the type when setting its value. This makes for highly readable code when working with explicitly typed enumeration values.
directionToHead
のタイプはすでにわかっているため、値を設定するときにタイプを削除できます。 これにより、明示的に型指定された列挙値を操作する場合にコードが非常に読みやすくなります。
Matching Enumeration Values with a Switch Statement
Switch ステートメントを使用した列挙値の照合
You can match individual enumeration values with a switch
statement:
個々の列挙値を switch ステートメントと照合できます。
directionToHead = .south
switch directionToHead {
case .north:
print("Lots of planets have a north")
case .south:
print("Watch out for penguins")
case .east:
print("Where the sun rises")
case .west:
print("Where the skies are blue")
}
// Prints "Watch out for penguins"
You can read this code as:
このコードは次のように読み取ることができます。
“Consider the value of directionToHead
. In the case where it equals .north
, print "Lots of planets have a north"
. In the case where it equals .south
, print "Watch out for penguins"
.”
「directionToHead
の値を考えてみましょう。 .north
に等しい場合は、「Lots of planets have a north」と出力します。 .south
に等しい場合は、「Watch out for penguins」と出力します。」
…and so on.
…等々。
As described in Control Flow, a switch
statement must be exhaustive when considering an enumeration’s cases. If the case
for .west
is omitted, this code doesn’t compile, because it doesn’t consider the complete list of CompassPoint
cases. Requiring exhaustiveness ensures that enumeration cases aren’t accidentally omitted.
制御フローで説明されているように、列挙のケースを考慮する場合、switch
ステートメントは網羅的である必要があります。 .west
のケースが省略された場合、CompassPointcase
の完全なリストが考慮されないため、このコードはコンパイルされません。 網羅性を要求することで、列挙ケースが誤って省略されることがなくなります。
When it isn’t appropriate to provide a case
for every enumeration case, you can provide a default
case to cover any cases that aren’t addressed explicitly:
すべての列挙ケースにcase
を提供することが適切でない場合は、明示的に対処されていないケースをカバーするdefault
のケースを提供できます。
let somePlanet = Planet.earth
switch somePlanet {
case .earth:
print("Mostly harmless")
default:
print("Not a safe place for humans")
}
// Prints "Mostly harmless"
Iterating over Enumeration Cases
列挙ケースの反復処理
For some enumerations, it’s useful to have a collection of all of that enumeration’s cases. You enable this by writing : CaseIterable
after the enumeration’s name. Swift exposes a collection of all the cases as an allCases
property of the enumeration type. Here’s an example:
一部の列挙では、その列挙のすべてのケースのコレクションがあると便利です。 これを有効にするには、列挙名の後に CaseIterable
を記述します。 Swift は、すべてのケースのコレクションを列挙型の allCases
プロパティとして公開します。 以下に例を示します。
enum Beverage: CaseIterable {
case coffee, tea, juice
}
let numberOfChoices = Beverage.allCases.count
print("\(numberOfChoices) beverages available")
// Prints "3 beverages available"
In the example above, you write Beverage.allCases
to access a collection that contains all of the cases of the Beverage
enumeration. You can use allCases
like any other collection — the collection’s elements are instances of the enumeration type, so in this case they’re Beverage
values. The example above counts how many cases there are, and the example below uses a for
–in
loop to iterate over all the cases.
上の例では、Beverage.allCases
を記述して、Beverage
列挙のすべてのケースを含むコレクションにアクセスします。 allCases
は他のコレクションと同様に使用できます。コレクションの要素は列挙型のインスタンスであるため、この場合は飲料の値になります。 上の例ではケースの数をカウントし、以下の例では for-in
ループを使用してすべてのケースを反復処理しています。
for beverage in Beverage.allCases {
print(beverage)
}
// coffee
// tea
// juice
The syntax used in the examples above marks the enumeration as conforming to the CaseIterable
(Link:developer.apple.com) protocol. For information about protocols, see Protocols.
上記の例で使用されている構文は、列挙型を CaseIterable
(Link:developer.apple.com)(英語)プロトコルに準拠していると見当します。 プロトコルの詳細については、「プロトコル」を参照してください。
Associated Values
関連する値
The examples in the previous section show how the cases of an enumeration are a defined (and typed) value in their own right. You can set a constant or variable to Planet.earth
, and check for this value later. However, it’s sometimes useful to be able to store values of other types alongside these case values. This additional information is called an associated value, and it varies each time you use that case as a value in your code.
前のセクションの例は、列挙型のケースがそれ自体でどのように定義された (および型付けされた) 値であるかを示しています。 Planet.earth に定数または変数を設定し、後でこの値を確認できます。 ただし、これらのケースの値と一緒に他の型の値も保存できると便利な場合があります。 この追加情報は関連値と呼ばれ、コード内の値としてそのケースを使用するたびに変化します。
You can define Swift enumerations to store associated values of any given type, and the value types can be different for each case of the enumeration if needed. Enumerations similar to these are known as discriminated unions, tagged unions, or variants in other programming languages.
Swift 列挙を定義して、任意の型に関連付けられた値を格納できます。また、必要に応じて、値の型を列挙のケースごとに変えることもできます。 これらに似た列挙は、他のプログラミング言語では識別共用体、タグ付き共用体、またはバリアントとして知られています。
For example, suppose an inventory tracking system needs to track products by two different types of barcode. Some products are labeled with 1D barcodes in UPC format, which uses the numbers 0
to 9
. Each barcode has a number system digit, followed by five manufacturer code digits and five product code digits. These are followed by a check digit to verify that the code has been scanned correctly:
たとえば、在庫追跡システムが 2 つの異なるタイプのバーコードで製品を追跡する必要があるとします。 一部の製品には、0 ~ 9 の数字を使用する UPC 形式の 1D バーコードがラベルに付けられています。各バーコードには番号体系の数字があり、その後にメーカー コードの 5 桁と製品コードの 5 桁が続きます。 これらの後には、コードが正しくスキャンされたことを確認するためのチェック ディジットが続きます。
Other products are labeled with 2D barcodes in QR code format, which can use any ISO 8859-1 character and can encode a string up to 2,953 characters long:
他の製品には QR コード形式の 2D バーコードがラベル付けされており、任意の ISO 8859-1 文字を使用でき、最大 2,953 文字の長さの文字列をエンコードできます。
It’s convenient for an inventory tracking system to store UPC barcodes as a tuple of four integers, and QR code barcodes as a string of any length.
在庫追跡システムでは、UPC バーコードを 4 つの整数のタプルとして保存し、QR コード バーコードを任意の長さの文字列として保存すると便利です。
In Swift, an enumeration to define product barcodes of either type might look like this:
Swift では、いずれかのタイプの製品バーコードを定義する列挙は次のようになります。
enum Barcode {
case upc(Int, Int, Int, Int)
case qrCode(String)
}
This can be read as:
これは次のように解釈できます。
“Define an enumeration type called Barcode
, which can take either a value of upc
with an associated value of type (Int
, Int
, Int
, Int
), or a value of qrCode
with an associated value of type String
.”
「Barcode
という列挙型を定義します。これは、タイプ (Int、Int、Int、Int)
の値が関連付けられた upc
の値、または String
型の値が関連付けられた qrCode
の値のいずれかを受け取ります。」
This definition doesn’t provide any actual Int
or String
values — it just defines the type of associated values that Barcode
constants and variables can store when they’re equal to Barcode.upc
or Barcode.qrCode
.
この定義は、実際の Int
値や String
値を提供するものではありません。Barcode.upc
または Barcode.qrCode
と等しい場合に、バーコード定数と変数が保存できる関連する値のタイプを定義するだけです。
You can then create new barcodes using either type:
その後、次のいずれかのタイプを使用して新しいバーコードを作成できます。
var productBarcode = Barcode.upc(8, 85909, 51226, 3)
This example creates a new variable called productBarcode
and assigns it a value of Barcode.upc
with an associated tuple value of (8, 85909, 51226, 3)
.
この例では、productBarcode
という新しい変数を作成し、それに関連するタプル値 (8, 85909, 51226, 3)
を持つ Barcode.upc
の値を割り当てます。
You can assign the same product a different type of barcode:
同じ商品に異なるタイプのバーコードを割り当てることができます。
productBarcode = .qrCode("ABCDEFGHIJKLMNOP")
At this point, the original Barcode.upc
and its integer values are replaced by the new Barcode.qrCode
and its string value. Constants and variables of type Barcode
can store either a .upc
or a .qrCode
(together with their associated values), but they can store only one of them at any given time.
この時点で、元の Barcode.upc
とその整数値は、新しい Barcode.qrCode
とその文字列値に置き換えられます。 Barcode
タイプの定数と変数は、.upc
または .qrCode
(関連する値とともに) を保存できますが、一度に保存できるのはどちらか 1 つだけです。
You can check the different barcode types using a switch statement, similar to the example in Matching Enumeration Values with a Switch Statement. This time, however, the associated values are extracted as part of the switch statement. You extract each associated value as a constant (with the let
prefix) or a variable (with the var
prefix) for use within the switch
case’s body:
「Switch ステートメントによる列挙値の照合」の例と同様に、switch
ステートメントを使用してさまざまなバーコード タイプを確認できます。 ただし、今回は、関連する値が switch
ステートメントの一部として抽出されます。 スイッチケースの本体内で使用するために、関連付けられた各値を定数(let
プレフィックス付き)または変数(var
プレフィックス付き)として抽出します。
switch productBarcode {
case .upc(let numberSystem, let manufacturer, let product, let check):
print("UPC: \(numberSystem), \(manufacturer), \(product), \(check).")
case .qrCode(let productCode):
print("QR code: \(productCode).")
}
// Prints "QR code: ABCDEFGHIJKLMNOP."
If all of the associated values for an enumeration case are extracted as constants, or if all are extracted as variables, you can place a single let
or var
annotation before the case name, for brevity:
列挙型ケースに関連付けられたすべての値が定数として抽出される場合、またはすべてが変数として抽出される場合、簡潔にするために、ケース名の前に 1 つの let
または var
アノテーションを配置できます。
switch productBarcode {
case let .upc(numberSystem, manufacturer, product, check):
print("UPC : \(numberSystem), \(manufacturer), \(product), \(check).")
case let .qrCode(productCode):
print("QR code: \(productCode).")
}
// Prints "QR code: ABCDEFGHIJKLMNOP."
Raw Values
生の値
The barcode example in Associated Values shows how cases of an enumeration can declare that they store associated values of different types. As an alternative to associated values, enumeration cases can come prepopulated with default values (called raw values), which are all of the same type.
関連する値のバーコードの例は、列挙型のケースがさまざまなタイプの関連する値を格納することを宣言する方法を示しています。 関連する値の代わりに、列挙ケースには、すべて同じタイプのデフォルト値(生の値と呼ばれます)が事前に設定されている場合があります。
Here’s an example that stores raw ASCII values alongside named enumeration cases:
以下は、生の ASCII 値を名前付き列挙ケースと一緒に保存する例です。
enum ASCIIControlCharacter: Character {
case tab = "\t"
case lineFeed = "\n"
case carriageReturn = "\r"
}
Here, the raw values for an enumeration called ASCIIControlCharacter
are defined to be of type Character
, and are set to some of the more common ASCII control characters. Character
values are described in Strings and Characters.
ここでは、ASCIIControlCharacter
という列挙の生の値が Character
タイプになるように定義されており、より一般的な ASCII 制御文字のいくつかに設定されています。 Character
の値については、「文字列と文字」で説明されています。
Raw values can be strings, characters, or any of the integer or floating-point number types. Each raw value must be unique within its enumeration declaration.
生の値は、文字列、文字、または任意の整数型または浮動小数点数型にすることができます。 各生の値は、その列挙宣言内で一意である必要があります。
Note
注釈
Raw values are not the same as associated values. Raw values are set to prepopulated values when you first define the enumeration in your code, like the three ASCII codes above. The raw value for a particular enumeration case is always the same. Associated values are set when you create a new constant or variable based on one of the enumeration’s cases, and can be different each time you do so.
生の値は、関連する値と同じではありません。 生の値は、上記の 3 つの ASCII コードのように、コード内で列挙を最初に定義するときに、事前に設定された値に設定されます。 特定の列挙型ケースの生の値は常に同じです。 関連付けられた値は、列挙型のケースの 1 つに基づいて新しい定数または変数を作成するときに設定され、作成するたびに異なる値になる可能性があります。
Implicitly Assigned Raw Values
暗黙的に割り当てられた生の値
When you’re working with enumerations that store integer or string raw values, you don’t have to explicitly assign a raw value for each case. When you don’t, Swift automatically assigns the values for you.
整数または文字列の生の値を格納する列挙型を操作する場合、それぞれの場合に生の値を明示的に割り当てる必要はありません。 そうしないときは、Swift が自動的に値を割り当てます。
For example, when integers are used for raw values, the implicit value for each case is one more than the previous case. If the first case doesn’t have a value set, its value is 0
.
たとえば、生の値に整数が使用される場合、各ケースの暗黙的な値は前のケースよりも 1 大きくなります。 最初のケースに値が設定されていない場合、その値は 0
になります。
The enumeration below is a refinement of the earlier Planet
enumeration, with integer raw values to represent each planet’s order from the sun:
以下の列挙は、以前のPlanet
の列挙を改良したもので、太陽からの各惑星の順序を表す生の整数値が含まれています。
enum Planet: Int {
case mercury = 1, venus, earth, mars, jupiter, saturn, uranus, neptune
}
In the example above, Planet.mercury
has an explicit raw value of 1
, Planet.venus
has an implicit raw value of 2
, and so on.
上の例では、Planet.mercury
の明示的な生の値は 1
、Planet.venus
の暗黙的な生の値は 2
などとなります。
When strings are used for raw values, the implicit value for each case is the text of that case’s name.
文字列が生の値に使用される場合、各ケースの暗黙の値はそのケースの名前のテキストになります。
The enumeration below is a refinement of the earlier CompassPoint
enumeration, with string raw values to represent each direction’s name:
以下の列挙は、各方向の名前を表す文字列の生の値を使用して、以前の CompassPoint
列挙を改良したものです。
enum CompassPoint: String {
case north, south, east, west
}
In the example above, CompassPoint.south
has an implicit raw value of "south"
, and so on.
上の例では、CompassPoint.south
には暗黙的な生の値「south
」などが含まれています。
You access the raw value of an enumeration case with its rawValue
property:
列挙型ケースの生の値には、rawValue
プロパティを使用してアクセスします。
let earthsOrder = Planet.earth.rawValue
// earthsOrder is 3
let sunsetDirection = CompassPoint.west.rawValue
// sunsetDirection is "west"
Initializing from a Raw Value
生の値からの初期化
If you define an enumeration with a raw-value type, the enumeration automatically receives an initializer that takes a value of the raw value’s type (as a parameter called rawValue
) and returns either an enumeration case or nil
. You can use this initializer to try to create a new instance of the enumeration.
raw 値型を使用して列挙型を定義すると、列挙型は、生の値の型の値を(rawValue
というパラメータとして)受け取るイニシャライザを自動的に受け取り、列挙型の値または nil
を返します。 このイニシャライザを使用して、列挙型の新しいインスタンスの作成を試みることができます。
This example identifies Uranus from its raw value of 7
:
この例では、生の値 7 から天王星を特定します。
let possiblePlanet = Planet(rawValue: 7)
// possiblePlanet is of type Planet? and equals Planet.uranus
Not all possible Int
values will find a matching planet, however. Because of this, the raw value initializer always returns an optional enumeration case. In the example above, possiblePlanet
is of type Planet?
, or “optional Planet
.”
ただし、考えられるすべての Int
値で一致する惑星が見つかるわけではありません。 このため、生の値の初期化子は常にオプションの列挙ケースを返します。 上の例では、possiblePlanet
のタイプは Planet?
、つまり「optional Planet
」です。
Note
注釈
The raw value initializer is a failable initializer, because not every raw value will return an enumeration case. For more information, see Failable Initializers(Link:developer.apple.com).
すべての生の値が列挙型ケースを返すわけではないため、生の値の初期化子は失敗可能な初期化子です。 詳細については、「失敗可能なイニシャライザ(Link:developer.apple.com)(英語)」を参照してください。
If you try to find a planet with a position of 11
, the optional Planet
value returned by the raw value initializer will be nil
:
位置 11 の惑星を見つけようとすると、生の値初期化子によって返されるオプションのPlanet
値は nil
になります。
let positionToFind = 11
if let somePlanet = Planet(rawValue: positionToFind) {
switch somePlanet {
case .earth:
print("Mostly harmless")
default:
print("Not a safe place for humans")
}
} else {
print("There isn't a planet at position \(positionToFind)")
}
// Prints "There isn't a planet at position 11"
This example uses optional binding to try to access a planet with a raw value of 11
. The statement if let somePlanet = Planet(rawValue: 11)
creates an optional Planet
, and sets somePlanet
to the value of that optional Planet
if it can be retrieved. In this case, it isn’t possible to retrieve a planet with a position of 11
, and so the else
branch is executed instead.
この例では、オプションのバインディングを使用して、生の値が 11
の惑星にアクセスしようとします。ステートメント if let somePlanet = Planet(rawValue:
11) はオプショナルPlanet
を作成し、取得できる場合はそのオプションのプラネットの値を somePlanet
に設定します。 。 この場合、位置 11
の惑星を取得することはできないため、代わりに else
節 が実行されます。
Recursive Enumerations
再帰的な列挙
A recursive enumeration is an enumeration that has another instance of the enumeration as the associated value for one or more of the enumeration cases. You indicate that an enumeration case is recursive by writing indirect
before it, which tells the compiler to insert the necessary layer of indirection.
再帰的列挙とは、1 つ以上の列挙ケースに関連付けられた値として列挙の別のインスタンスを持つ列挙です。 列挙型のケースの前に indirect
を記述することで、列挙型のケースが再帰的であることを示します。これにより、必要な間接層を挿入するようにコンパイラーに指示されます。
For example, here is an enumeration that stores simple arithmetic expressions:
たとえば、次は単純な算術式を格納する列挙です。
enum ArithmeticExpression {
case number(Int)
indirect case addition(ArithmeticExpression, ArithmeticExpression)
indirect case multiplication(ArithmeticExpression, ArithmeticExpression)
}
You can also write indirect
before the beginning of the enumeration to enable indirection for all of the enumeration’s cases that have an associated value:
列挙の先頭の前に indirect
を記述して、値が関連付けられているすべての列挙のケースに対して間接化を有効にすることもできます。
indirect enum ArithmeticExpression {
case number(Int)
case addition(ArithmeticExpression, ArithmeticExpression)
case multiplication(ArithmeticExpression, ArithmeticExpression)
}
This enumeration can store three kinds of arithmetic expressions: a plain number, the addition of two expressions, and the multiplication of two expressions. The addition
and multiplication
cases have associated values that are also arithmetic expressions — these associated values make it possible to nest expressions. For example, the expression (5 + 4) * 2
has a number on the right-hand side of the multiplication and another expression on the left-hand side of the multiplication. Because the data is nested, the enumeration used to store the data also needs to support nesting — this means the enumeration needs to be recursive. The code below shows the ArithmeticExpression
recursive enumeration being created for (5 + 4) * 2
:
この列挙には、単純な数値、2 つの式の加算、および 2 つの式の乗算の 3 種類の算術式を格納できます。 addition
とmultiplication
のケースには、算術式でもある関連付けられた値があります。これらの関連付けられた値により、式をネストすることが可能になります。 たとえば、式 (5 + 4) * 2
には、乗算の右側に数値があり、乗算の左側に別の式があります。 データはネストされているため、データの保存に使用される列挙もネストをサポートする必要があります。これは、列挙が再帰的である必要があることを意味します。 以下のコードは、(5 + 4) * 2
に対して作成される ArithmeticExpression
再帰列挙を示しています。
let five = ArithmeticExpression.number(5)
let four = ArithmeticExpression.number(4)
let sum = ArithmeticExpression.addition(five, four)
let product = ArithmeticExpression.multiplication(sum, ArithmeticExpression.number(2))
A recursive function is a straightforward way to work with data that has a recursive structure. For example, here’s a function that evaluates an arithmetic expression:
再帰関数は、再帰構造を持つデータを操作する簡単な方法です。 たとえば、算術式を評価する関数は次のとおりです。
func evaluate(_ expression: ArithmeticExpression) -> Int {
switch expression {
case let .number(value):
return value
case let .addition(left, right):
return evaluate(left) + evaluate(right)
case let .multiplication(left, right):
return evaluate(left) * evaluate(right)
}
}
print(evaluate(product))
// Prints "18"
This function evaluates a plain number by simply returning the associated value. It evaluates an addition or multiplication by evaluating the expression on the left-hand side, evaluating the expression on the right-hand side, and then adding them or multiplying them.
この関数は、関連する値を返すだけで単純な数値を評価します。 左側の式を評価し、右側の式を評価してから、それらを加算または乗算することによって、加算または乗算を評価します。