From AP to Z
本題に入る前に臨時ニュースを。本連載第18回でも紹介したAPFSですが,
それよりずっと地味ながらも見落とせないのは,
すでにインストーラまでZFSに対応しているFreeBSD以外のOSのZFSブート環境構築はまだまだ面倒なのですが,
オープンソースといえば,
型の集まりもまた型
ニュースはこれくらいにして本題に入りましょう。前回に引き続き今回も型の話です。今回は配列
Swiftの型は静的。当然配列や辞書も静的な型を持つのですが,
まずは,
Rubyの例
% irb irb(main):001:0> [nil,false,0,"",[],{}].each{¦e¦ p e.class} NilClass FalseClass Fixnum String Array Hash => [nil, false, 0, "", [], {}]
JavaScriptの例
% node > [null,false,0,"",[],{}].forEach(function(e){console.log(typeof e)}) object boolean number string object object undefined >
見てのとおり,
Swiftはどうでしょう?
図3のように文句を言われてしまいました。もう少し見ていきましょう。
図3 Swiftでの配列実験の結果
% swift Welcome to Apple Swift version 3.0.2 (swiftlang-800.0.63 clang-800.0.42.1). Type :help for assistance. 1> [nil,false,0,"",[],[:]] error: repl.swift:1:1: error: type of expression is ambiguous without more context [nil,false,0,"",[],[:]]
1> [false,true] $R0: [Bool] = 2 values { [0] = false [1] = true } 2> [0,1] $R1: [Int] = 2 values { [0] = 0 [1] = 1 } 3> ["","one"] $R2: [String] = 2 values { [0] = "" [1] = "one" }
そう。Swiftでは配列の要素の型はすべて同じで,[Element]
という型になるのです。
なんて型苦しい? ところでこのRubyコードを見てくれ。図4をどう思う?
図4 Rubyの実行結果
% irb irb(main):001:0> ["answer",42,42.195,[true],false].each{¦e¦ p e + e} "answeranswer" 84 84.39 [true, true] NoMethodError: undefined method `+' for false:FalseClass from (irb):2:in `block in irb_binding' from (irb):2:in `each' from (irb):2 from /usr/bin/irb:12:in `<main>'
すごく……大きなバグを誘発しそうな気がしませんか?
こういう場合,
% irb irb(main):001:0> ["answer",42,42.195,[true],false].each do ¦e¦ irb(main):002:1* p e + e if e.respond_to?(:+) irb(main):003:1> end "answeranswer" 84 84.39 [true, true] => ["answer", 42, 42.195, [true], false]
しかしそれはその分コードの量が増えるということでもあり,
1> [41,42].map{$0+$0} $R0: [Int] = 2 values { [0] = 82 [1] = 84 } 2> [41.0,42.195].map{$0+$0} $R1: [Double] = 2 values { [0] = 82 [1] = 84.39 } 3> ["answer","universe"].map{$0+$0} $R2: [String] = 2 values { [0] = "answeranswer" [1] = "universeuniverse" } 4> [false,true].map{$0+$0} error: repl.swift:4:20: error: binary operator'+' cannot be applied to two 'Bool' operands [false,true].map {$0+$0}