2015-11-25 7 views
9

TL; DR

なぜこれは機能しませんか?私はスウィフトに好きmap()内のinit()の使用

"abcdefg".characters.map(String.init) // error: type of expression is ambiguous without more context 

詳細

一つは本当にクールなことは、(存在するそのタイプのinit()を想定)initメソッドに渡すことにより、別のもののコレクションを変換する機能です。

ここでは、タプルのリストをClosedIntervalのインスタンスに変換する例を示します。例はまた、我々は限りタプルは関数の引数リストと一致するように、単一の引数として、引数のタプルを渡すことができるという事実を利用すること

[(1,3), (3,4), (4,5)].map(ClosedInterval.init) 

この例では、数値のリストを文字列インスタンスに変換する別の例を示します。

(1...100).map(String.init) 

残念ながら、次の例は機能しません。ここでは、文字列を1文字の文字列のリストに分割しようとしています。

"abcdefg".characters.map(String.init) // error: type of expression is ambiguous without more context 

map()Characterのリスト上で動作すべきである(実際に私はスイフトはここmapに渡される[文字]の正しいタイプを推論遊び場に確認することができました)。

Stringは、Characterから明確にインスタンス化できます。

let a: Character = "a" 
String(a) // this works 

興味深いことに、これは文字がそれぞれ独自の配列にある場合に有効です。

"abcdefg".characters.map { [$0] }.map(String.init) 

または同等:

let cx2: [[Character]] = [["a"], ["b"], ["c"], ["d"]] 
cx2.map(String.init) 

私はこれを行うことができることを知っている:

"abcdefg".characters.map { String($0) } 

しかし、私は特にIMOこの構文は次のとおりです("abcdefg".characters.map(String.init)が動作しない理由を理解しようとしていますまた、読みやすくエレガント)

答えて

13

簡体字版:

String.init as Character -> String 
// error: type of expression is ambiguous without more context 

Stringは1 Characterを受け入れる2つの初期化子があるので、これはされています。私の知る限りでは

init(_ c: Character) 
init(stringInterpolationSegment expr: Character) 

を、値として初期化子を使用したときにそれらを明確にする方法はありません。

(1...100).map(String.init)については、String.initは、Int -> Stringと呼ばれます。1 Intを受け入れる2つの初期化子がありますが:

init(stringInterpolationSegment expr: Int) 
init<T : _SignedIntegerType>(_ v: T) 

一般的なタイプは、明示的な型より弱いです。したがって、この場合コンパイラはstringInterpolationSegment:を選択します。 コマンド + .initをクリックして確認できます。

+1

これは優れた答えです。このように '.init'を使用することを記述しているリファレンスドキュメント(または記事など)はありますか(たとえば、map/flatMapなど)? –

+1

2つの初期設定を明確にすることができます。 'String.init(_ :)'を使って最初のものを参照してください。 – Sweeper

関連する問題