Swiftはメソッドパラメータを変更可能にしますか?


123

追加の変数を作成せずにこのエラーに対処するにはどうすればよいですか?

func reduceToZero(x:Int) -> Int {
    while (x != 0) {
        x = x-1            // ERROR: cannot assign to 'let' value 'x'
    }
    return x
}

xの値を格納するためだけに追加の変数を作成したくありません。私がやりたいことをすることさえ可能ですか?


3
下記の更新された回答を参照してください。Swift3はあなたの承認された回答を非推奨にしました。
achi 2016年

回答:


191

他の回答で述べたように、Swift 3以降、変数が廃止される前にvarが配置されます。他の回答では述べられていませんが、inoutパラメーターを宣言する機能があります。考えてみてください:ポインターを渡す。

func reduceToZero(_ x: inout Int) {
    while (x != 0) {
        x = x-1     
    }
}

var a = 3
reduceToZero(&a)
print(a) // will print '0'

これは、再帰で特に役立ちます。

Appleのinout宣言ガイドラインはここにあります


2
どうもありがとうございました!!!!再帰の質問でここで行き詰まっています。あなたは私の命を救いました。
JW.ZG 2016

2
これは関数のスコープ外の変数を変更するため、注意して使用する必要があります。関数内で変更した値を明示的に返すのが理想的です。
Chris Gunawardena

2
inoutキーワードは、パラメーター名とパラメータータイプの間に次のように配置する必要があります:func reduceToZero(x: inout Int) 現在のSwift 3バージョン。
アグスティ・サンチェス

ただし、クロージャは明らかに値によって入出力パラメータのみをキャプチャするため(これはXcodeから表示されるエラーメッセージです)、クロージャでは機能しないようです。この場合、@ GeRyChソリューションを使用します。
wcochran 2017

ありがとうございました。これは今のところ機能しましたが、Cでポインタを使用するようなものです。これは別のSwiftバージョンでも存続しますか?
クリシュナヴェドゥラ2017

45

'var'パラメータは廃止予定であり、Swift 3で削除される予定です。そのため、新しいパラメータへの割り当ては今のところ最良の方法のようです:

func reduceToZero(x:Int) -> Int {
    var x = x
    while (x != 0) {
        x = x-1            
    }
    return x
}

ここで述べたように:'var'パラメータは非推奨であり、Swift 3で削除されます


1
この場合、x新しいに実際にコピーされvar xますか?それともSwiftはそれよりも効率的なことをしていますか?
元気

3
これは機能し、私がやっていることですが、非常に扱いにくいようです。
wcochran

1
@Gomfucius Swift 3.1ガイドでは、これについては一言もありません。この場合(xレジスターに収まる)、実質的に費用はかかりません。場合x、配列、構造体、または変異されたオブジェクトであり、その後、ほぼ確実にコピー(オプティマイザはそれをインラインでそれを分析し、エイリアスができない場合)に実行される必要があります。
wcochran 2017

1
@wcochranこれは巧妙なトリックですが、実際には特別なことは何もありません。入力パラメーターをローカルのvarコピーで単純に覆い隠しています。OPの状況では、意図しない副作用が発生する可能性のあるvaresを使用inoutするよりも、argsを置き換える方が適切です。varがポインタの場合。
エシェロン2017年

45

Swift 1と2の場合(Swift 3の場合は、inoutパラメーターを使用したachiの回答を参照):Swiftの関数の引数はletデフォルトであるのでvar、値を変更する必要がある場合はに変更します。

func reduceToZero(var x:Int) -> Int {
    while (x != 0) {
        x = x-1     
    }
    return x
}

2
なぜこの答えは地獄のように投票されるのですか?もう1つの回答はこの回答の前にあり、これよりも多くの情報が含まれています。
Cristik

16
/!\ varを使用すると、パラメーターで渡された変数のコピーが作成されます。したがって、変更しても元の値は変更されません。またvargithub.com
Matthieu

17
メソッドparemeterでvarキーワードはスウィフト3に廃止される予定
ブーン

4
Swift 3では、これを実行できなくなると思います。配列の可変コピーを作成し、その変更された配列を返す必要があります。
C0D3 2016年

この答えは正解です。stackoverflow.com
questions / 24077880

14

可変配列ポインターを渡すためのSwift3回答。

関数:

func foo(array: inout Array<Int>) {
    array.append(1)
}

関数の呼び出し:

var a = Array<Int>()
foo(array:&a)

正直なところ、Swiftのグラウンドは常に変化しているため、これが正しいかどうかはわかりません。これはコピーを作成するため(そして実際には元の配列構造に影響を与えないため)、関数内でvar array = arrayを実行するよりも良いと思いましたか?前述のvarアプローチに対するより優れた設計アプローチであり、その後、新しい変異配列を返しますか?
joshd

7

Swift varでは、関数宣言の変数名の前にキーワードを追加するだけです。

func reduceToZero(var x:Int) -> Int { // notice the "var" keyword
    while (x != 0) {
        x = x-1            
    }
    return x
}

Swiftブック(現在のiBookの210ページ)の「関数」の章にある「定数と変数のパラメーター」のサブセクションを参照してください。


7
'var'パラメータは廃止され、Swift 3で削除されます
Regis St-Gelais '19年

1
Swift 4以降では無効です。
ilkayaktas

0

使用する必要がない場合があります inout

変更/スコープを関数内のみにしたい場合は、次のようなものを使用できます。

func manipulateData(a: Int) -> Int {
    var a = a
    // ...
}

0

関数型プログラミングでSwift5を使用するソリューション...

func reduceToZeroFP(x:Int) -> Int {
    x == 0 ? x : reduceToZeroFP(x: x - 1)
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.