有能ではあるが万能には足りない
前回の予告どおり、
公式サイトのAbout Swiftにはこうあります。
The goal of the Swift project is to create the best available language for uses ranging from systems programming, to mobile and desktop apps, scaling up to cloud services.
「Swift プロジェクトのゴールは、
RustにあってSwiftにないもの=RustになくてSwiftにあるもの
現時点において、
RustにはすでにRustで実装されたRedoxというOSがあります

それに対し、
筆者の答えは、
たとえばメモリ管理。SwiftもObjective-C同様、
しかし問題なのは参照カウンタ方式であることそのものより、
これに対しRustは、
Ownershipがいかに優れた概念であるかは、
SwiftはSwiftで書かれていない
Swift 4.
総称関数が関数(オブジェクト)でない
システムプログラミングが
本連載でも以前指摘したとおり、
たとえば、
func idInt(_ i:Int)->Int{ return i }
と、
let idInt = { (i:Int)->Int in i }
や
let idInt:(Int)->Int{ i in i }
や
let idInt:(Int)->Int{ $0 }
は等価で、
var f = idInt
f(42) // 42
と変数に代入することも可能ですが、
func id<T>(_ a:T)->T {
return a
}
に、
let id = <T>{ (i:T)->T in i }
や
let id<T>:(T)->T { i in i }
や
let id<T>:(T)->T { $0 }
という表現はありえず、
var f = id
とは書けません。Swiftが静的型言語である以上これは仕方がないことで、
それができる静的型言語はすでに存在するのです。それもSwiftの先輩言語に。
リスト1のコードにchurchNum.
と名付けて保存します。
zero = \f x -> x
one = \f x -> f x
two = \f x -> f $ f x
three = \f x -> f $ f $ f x
succ = \n f x -> f $ n f x
add = \m n f x -> m f $ n f x
mul = \m n f -> m $ n f
次にHaskellのデファクト標準実装であるghci
で実行してみます。
% ghci GHCi, version 8.4.3: http://www.haskell.org/ghc/:? for help Prelude> :l churchNum.hs [1 of 1] Compiling Main ( churchNum.hs, interpreted ) Ok, one module loaded. *Main> (add two three) (+1) 0 5 *Main> (mul two three) (+1) 0 6
これはチャーチ数n
は初期値x
に関数f
をn
回かける関数として定義するもので、0
と+1
する関数を入れると6
になっています。
*Main> (add two three) ((++) "!") "" "!!!!!" *Main> (mul two three) ((++) "!") "" "!!!!!!"
として容易に確認できますし、
*Main> :t add add :: (t1 -> t2 -> t3) -> (t1 -> t4 -> t2) -> t1 -> t4 -> t3 *Main> :t mul mul :: (t1 -> t2) -> (t3 -> t1) -> t3 -> t2
当然のことながら、
onst zero = f => x => x;
const one = f => x => f(x);
const two = f => x => f(f(x));
const three = f => x => f(f(f(x)));
const succ = n => f => x => f(n(f)(x));
const add = m => n => f => x => n(f)(m(f)(x));
const mul = m => n => f => x => n(m(f))(x);
console.log(add(two)(three)(x=>x+1)(0)); // 5
console.log(mul(two)(three)(x=>x+1)(0)); // 6
それではSwiftではどうでしょう? リスト3の結果をご覧ください。
typealias F<A,R> = (A)->R
typealias C<N> = F<N,N>
func zero<N> (_ f:@escaping C<N>)->C<N> {
return {x in x}
}
func one<N> (_ f:@escaping C<N>)->C<N> {
return {x in f(x)}
}
func two<N> (_ f:@escaping C<N>)->C<N> {
return {x in f(f(x))}
}
func three<N>(_ f:@escaping C<N>)->C<N> {
return {x in f(f(f(x)))}
}
// SUCC := λn.λf.λx.f (n f x)
func succ<S,Z,N>(
_ n: @escaping (@escaping F<S,N>)->F<Z,S>
)-> (@escaping F<S,N>)->F<Z,N>
{
return {f in {x in f(n(f)(x))}}
}
// ADD := λm.λn.λf.λx.m f (n f x)
func add<S,Z,N>(
_ m: @escaping F<Z,F<S,N>>
)-> (@escaping F<Z,F<N,S>>)->F<Z,C<N>>
{
return {n in {f in {x in m(f)(n(f)(x))}}}
}
// MUL := λm.λn.λf.m (n f)
func mul<S,Z,N>(
_ m: @escaping F<S,Z>
)-> (@escaping F<N,S>)->F<N,Z>
{
return {n in {f in m(n(f))}}
}
print( mul(two)(three)({x in x+1})(0) )
print( add(two)(three)({x in x+1})(0) )
ずいぶんとまだるっこしいものになってしまいました。実はこれ、@escaping
は不要だったのです。その一方typealias
で総称型が使えるようになったので、
Swiftの物語はこれからだ!
ひねくれた言い方をすると、
とはいえSwiftはまだ5才。ほかの主要言語は主要言語とみなされるまで10年以上かかるのが普通です。拡張の余地もまだあります。''
そもそも万能言語が必要かという疑問もあります。Cはなんでも書けますが、
それでもなお万能言語を希求してしまうのもまた、
本誌最新号をチェック!
Software Design 2022年9月号
2022年8月18日発売
B5判/
定価1,342円
- 第1特集
MySQL アプリ開発者の必修5科目
不意なトラブルに困らないためのRDB基礎知識 - 第2特集
「知りたい」 「使いたい」 「発信したい」 をかなえる
OSSソースコードリーディングのススメ - 特別企画
企業のシステムを支えるOSとエコシステムの全貌
[特別企画] Red Hat Enterprise Linux 9最新ガイド - 短期連載
今さら聞けないSSH
[前編] リモートログインとコマンドの実行 - 短期連載
MySQLで学ぶ文字コード
[最終回] 文字コードのハマりどころTips集 - 短期連載
新生「Ansible」 徹底解説
[4] Playbookの実行環境 (基礎編)