0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Control Flow

Last updated at Posted at 2024-10-27

制御フロー文(Control flow statement)は、関数内の実行の流れを制御します。

Conditional branching: if-statement

if文は、特定の条件が満たされた場合にのみ、コードの一部を実行することを可能にします。
if文は、ifキーワードで始まり、条件、そして条件が満たされた場合に実行されるコードが、開始波括弧と終了波括弧内に続きます。条件式はブール値(Boolean)でなければなりません。波括弧は必須であり、省略はできません。条件を囲む括弧は省略可能です。

let a = 0
var b = 0

if a == 0 {
   b = 1
}

// Parentheses can be used around the condition, but are not required.
if (a != 0) {
   b = 2
}

// `b` is `1`

条件が偽の場合に別のコードを実行するには、追加のオプショナル else 節を追加することができます。 else 節は、else キーワードで導入され、その後に実行すべきコードを含む中括弧が続きます。

let a = 0
var b = 0

if a == 1 {
   b = 1
} else {
   b = 2
}

// `b` is `2`

else節には別のif文を含めることができ、つまり、if文を連結することができます。この場合、波括弧は省略できます。

let a = 0
var b = 0

if a == 1 {
   b = 1
} else if a == 2 {
   b = 2
} else {
   b = 3
}

// `b` is `3`

if a == 1 {
   b = 1
} else {
    if a == 0 {
        b = 2
    }
}

// `b` is `2`

Optional Binding

オプショナルバインディングは、オプショナル内の値を取得することを可能にします。これは、if文の変形です。

オプショナルに値が含まれている場合は、最初の分岐が実行され、一時的な定数または変数が宣言され、オプショナルに含まれる値に設定されます。そうでない場合は、else分岐(がある場合)が実行されます。

オプショナルバインディングは、ifキーワードを使用してif文と同様に宣言しますが、ブーリアン値のテストの代わりに、letまたはvarキーワードを続けて、定数または変数を導入し、その後に名前、等号(=)、オプショナル値を続けます。

let maybeNumber: Int? = 1

if let number = maybeNumber {
    // This branch is executed as `maybeNumber` is not `nil`.
    // The constant `number` is `1` and has type `Int`.
} else {
    // This branch is *not* executed as `maybeNumber` is not `nil`
}
let noNumber: Int? = nil

if let number = noNumber {
    // This branch is *not* executed as `noNumber` is `nil`.
} else {
    // This branch is executed as `noNumber` is `nil`.
    // The constant `number` is *not* available.
}

Switch

switch文は、同じ型の複数の値を順番に比較します。等しい値が見つかると、関連するコードブロックが実行されます。

switchステートメントはswitchキーワードで始まり、テストする値が続き、開始波括弧と終了波括弧内のケースが続きます。テスト式は等価でなければなりません。波括弧は必須であり、省略できません。

各ケースはコード実行の別々の分岐であり、caseキーワードで始まり、値、コロン(:)、ケースの値がテスト値と等しい場合に実行されるコードブロックが続きます。

switch caseに関連するコードブロックは暗黙的にフォールスルーせず、少なくとも1つのステートメントを含める必要があります。空のブロックは無効です。

オプションのデフォルトケースは、defaultキーワードを使用して指定できます。デフォルトケースのコードブロックは、それ以前のケースのテストがすべて失敗した場合に実行されます。これは常に最後に配置する必要があります。

fun word(_ n: Int): String {
    // Test the value of the parameter `n`
    switch n {
    case 1:
        // If the value of variable `n` is equal to `1`,
        // then return the string "one"
        return "one"
    case 2:
        // If the value of variable `n` is equal to `2`,
        // then return the string "two"
        return "two"
    default:
        // If the value of variable `n` is neither equal to `1` nor to `2`,
        // then return the string "other"
        return "other"
    }
}

word(1)  // returns "one"
word(2)  // returns "two"
word(3)  // returns "other"
word(4)  // returns "other"

Duplicate cases

caseは順番にテストされるため、ケースが重複した場合は、成功した最初のケースに関連するコードブロックが実行されます。

fun test(_ n: Int): String {
    // Test the value of the parameter `n`
    switch n {
    case 1:
        // If the value of variable `n` is equal to `1`,
        // then return the string "one"
        return "one"
    case 1:
        // If the value of variable `n` is equal to `1`,
        // then return the string "also one".
        // This is a duplicate case for the one above.
        return "also one"
    default:
        // If the value of variable `n` is neither equal to `1` nor to `2`,
        // then return the string "other"
        return "other"
    }
}

word(1) // returns "one", not "also one"

break

switch caseに関連するコードブロックには、breakステートメントが含まれている場合があります。これは、switchステートメントの実行を即座に終了し、switchステートメントの後のコードに制御を移します。

No Implicit Fallthrough

Cadenceのswitch文は、他の言語のswitch文とは異なり、「フォールスルー(fall through)」しません。最初の一致するケースに関連するコードブロックが完了すると、switch文の実行が終了します。明示的なbreak文は必要ありません。

これにより、switch文はより安全で使いやすくなり、複数のswitch caseの誤った実行を回避できます。

他の言語では、次のcaseに関連するコードブロックに暗黙的にフォールスルー(fall through)するため、複数の値を同じ方法で処理するためにブロックが空のcaseを記述することが一般的です。

開発者がこのような動作を想定したswitch文を記述しないように、ブロックには少なくとも1つのステートメントが必要です。空のブロックにすることはできません。

fun words(_ n: Int): [String] {
    // Declare a variable named `result`, an array of strings,
    // which stores the result
    let result: [String] = []

    // Test the value of the parameter `n`
    switch n {
    case 1:
        // If the value of variable `n` is equal to `1`,
        // then append the string "one" to the result array
        result.append("one")
    case 2:
        // If the value of variable `n` is equal to `2`,
        // then append the string "two" to the result array
        result.append("two")
    default:
        // If the value of variable `n` is neither equal to `1` nor to `2`,
        // then append the string "other" to the result array
        result.append("other")
    }
    return result
}

words(1)  // returns `["one"]`
words(2)  // returns `["two"]`
words(3)  // returns `["other"]`
words(4)  // returns `["other"]`

Looping

while-statement

While文は、条件が真である限り、特定のコードを繰り返し実行することを可能にします。

While文は、whileキーワードで始まり、条件、そして開始波括弧と終了波括弧の内側で条件が真である場合に繰り返し実行されるコードが続きます。条件はブール値でなければならず、波括弧は必須です。

while文はまず条件を評価します。条件が真であれば、コードの一部が実行され、条件の評価が繰り返されます。条件が偽であれば、while文全体の実行が終了します。したがって、コードは0回以上実行されます。

var a = 0
while a < 5 {
    a = a + 1
}

// `a` is `5`

For-in statement

for-inステートメントは、配列の各要素に対して特定のコードを繰り返し実行することを可能にします。

for-inステートメントは、forキーワードで始まり、ループの各反復で使用される要素の名前が続き、inキーワードが続き、ループで反復処理される配列が続きます。

そして、ループの各反復で繰り返し実行されるコードが波括弧で囲まれます。

データ構造に要素が含まれていない場合、ループ内のコードはまったく実行されません。そうでない場合、コードは配列内の要素の数と同じ回数だけ実行されます。

let array = ["Hello", "World", "Foo", "Bar"]

for element in array {
    log(element)
}

// The loop would log:
// "Hello"
// "World"
// "Foo"
// "Bar"

オプションとして、開発者は要素名の前にカンマで区切った追加の変数を挿入することができます。この変数が存在する場合、その変数には、繰り返し実行の際に順次処理される配列の現在のインデックス(0から始まる)が格納されます。

let array = ["Hello", "World", "Foo", "Bar"]

for index, element in array {
    log(index)
}

// The loop would log:
// 0
// 1
// 2
// 3

ディクショナリのエントリ(キーと値)を繰り返し処理するには、ディクショナリのキーに対して for-in ループを使用し、各キーの値を取得します。

let dictionary = {"one": 1, "two": 2}
for key in dictionary.keys {
    let value = dictionary[key]!
    log(key)
    log(value)
}

// The loop would log:
// "one"
// 1
// "two"
// 2

その代わり、ディクショナリには、forEachKeyメソッドが用意されており、キー用の中間配列を割り当てる必要がありません。

let dictionary = {"one": 1, "two": 2, "three": 3}
dictionary.forEachKey(fun (key: String): Bool {
    let value = dictionary[key]
    log(key)
    log(value)

    return key != "two" // stop iteration if this returns false
})

Ranges in Loops

InclusiveRangeの値は、配列やディクショナリの代わりにfor-in文で使用することができます。この場合、ループはrange.startから始まり、range.endで終了する範囲に含まれるすべての値を繰り返し処理します。例:

let range: InclusiveRange<UInt> = InclusiveRange(1, 100, step: 2)
var elements : [UInt] = []
for element in range {
    elements.append(element)
}
// after this loop, `elements` contains all the odd integers from 1 to 99

この例では、100 がrangeの終わりであっても、start値とstep値では到達できないため、ループには含まれません。

上記のループは、以下と同等です。

let range: InclusiveRange<UInt> = InclusiveRange(1, 100, step: 2)
var elements : [UInt] = []
var index = range.start
while index <= range.end {
    elements.append(element)
    index = index + range.step
}
// after this loop, `elements` contains all the odd integers from 1 to 99

一般的に、正のstepのfor-inループは、以下と同等です。

var index = range.start
while index <= range.end {
    // loop body
    index = index + range.step
}

負のstepのfor-inループは、以下と同等です。

var index = range.start
while index >= range.end {
    // loop body
    index = index + range.step // `range.step` here is negative, so this decreases `index`
}

どちらも次のように書き換えることができます。

var index = range.start
while range.contains(index) {
    // loop body
    index = index + range.step
}

continue and break

for-loopおよびwhile-loopでは、continueステートメントを使用して、ループの現在の繰り返しを中止し、次の繰り返しを開始することができます。

var i = 0
var x = 0
while i < 10 {
    i = i + 1
    if i < 3 {
        continue
    }
    x = x + 1
}
// `x` is `8`


let array = [2, 2, 3]
var sum = 0
for element in array {
    if element == 2 {
        continue
    }
    sum = sum + element
}

// `sum` is `3`

break ステートメントは、forループまたはwhileループの実行を停止するために使用できます。

var x = 0
while x < 10 {
    x = x + 1
    if x == 5 {
        break
    }
}
// `x` is `5`


let array = [1, 2, 3]
var sum = 0
for element in array {
    if element == 2 {
        break
    }
    sum = sum + element
}

// `sum` is `1`

Immediate function return: return-statement

returnステートメントは、関数を即座に終了させます。つまり、returnステートメント以降のコードは実行されません。returnステートメントはreturnキーワードで始まり、関数呼び出しの戻り値となるオプショナルの式が続きます。

翻訳元->https://cadence-lang.org/docs/language/control-flow

Flow BlockchainのCadence version1.0ドキュメント (Control Flow)

Previous << Functions

Next >> Scope

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?