書いて覚えるSwift入門

第22回 謹賀新言語

この記事を読むのに必要な時間:およそ 3 分

あらためてSwiftを始めませんか?

本稿を執筆しているのは(とくに政治的に)波乱含みどころか波乱しかなかった感のある2016年末ですが,皆さんに届くころには新年気分も過ぎ,2017年という表記に読者の皆さんも慣れているころだと思います。新言語を学びはじめるにはちょうどいいころあいかと。

本連載はこれまで連載ということもあって,すでにSwiftという言語には本連載開始時点から慣れ親しんでいる読者を対象にしてきたのですが,本誌をはじめて手にとった方,つまり本誌にはある程度の理解はあるけれどもSwiftはまだ知らないという読者に向けて,Swiftとはどんな言語なのかを紹介するころあいでしょう。

安全,高速,豊かな表現力

いったいSwiftとはどういう言語なのでしょう? 公式サイトのAbout Swiftには3つの特長が掲げられています。

  • 安全(Safe)
  • 高速(Fast)
  • 豊かな表現力(Expressive)

Swiftは静的型を採用していますが,これは安全性に寄与しています。たとえばvar i = 42Int型として初期化されたものにi = "one"とStringを代入しようとしても,コンパイル時にエラーとして弾きます。SwiftはCやC++やObjective-Cを置き換えることを標榜しているだけあって,同じことを同じように書いた場合,速度はそれらにまさるとも劣りません。それでいて,動的型を採用しているJavaScriptやPerlやPythonやRubyに匹敵する表現力を持ちます。動的言語のように速く書けて,静的言語のように速く実行できる。そのような言語はすべての言語デザイナの夢ですが,Swiftはその夢に最も近い言語だと筆者は感じています。

Getting Started

ではさっそくはじめてみましょう。え,Macなんて持ってない? ご安心を。Swift Sandboxのおかげで,今やSwiftはWebブラウザさえあればお試しできるのです図1)⁠

図1 Swiftのsandbox

図1 Swiftのsandbox

もともとはApple製品専用開発言語としてスタートしたSwiftですが,オープンソース化にともない,MacだけでなくLinuxも公式にサポートされています。Linux版はWindows 10 Anniversary Editionに搭載されたLinux on Windowsでも動きます。本稿に限らず,本連載ではなるべくプラットフォームに依存しないように当初から心がけているので,本書の連載を理解するにあたってApple製品は必須ではありません。

とはいえ,Swiftの醍醐味をもっとも堪能できるのは,MacのXcodeということになります。とくにPlaygroundは現状Mac版とiPad版しか存在しません。Swiftを100%したかったら,やはりMacが第一選択肢となります。

演習:言語処理系を実装してみる

では,さっそく言語処理系を作ってみましょう。え,いきなりハードルが高い? 心配ご無用。ここで実装するのは,その言語でプログラムするよりその言語の処理系を書くほうが簡単と定評のあるBrainfuckです図2)⁠リスト1はわずか36行ですが,それでも写経するのが面倒だというのであれば,gistにソースを用意しておきましたので利用ください。

図2 PlaygroundでBrainfuck

図2 PlaygroundでBrainfuck

リスト1 brainfuck.swift

let datasize = 65536
var framework = "Darwin"
#if os(Linux)
framework = "Glibc"
#endif
let bf2swift:[Character:String] = [
    ">": "sp += 1",
    "<": "sp -= 1",
    "+": "data[sp] += 1",
    "-": "data[sp] -= 1",
    "[": "while data[sp] != CChar(0) {",
    "]": "}",
    ".": "putchar(Int32(data[sp]))",
    ",": "data[sp] = {c in CChar(c < 0 ? 0 : c)}
(getchar())"
]
func bf2swift(src:String) -> String {
    var lines = [
        "import \(framework)",
        "var data = [CChar](repeating:CChar(0),count:ュ
¥(datasize))",
        "var (sp, pc) = (0, 0)",
    ]
    for c in src.characters {
        if let l = bf2swift[c] {
            lines.append(l)
        }
    }
    lines.append("")
    return lines.joined(separator: "¥n")
}
extension String {
    func bfCompile()->String {
        return bf2swift(src: self)
    }
}
let src = "+[,<>.]-"
print(src.bfCompile())

リスト1を実行してみると,図3のとおりに標準出力されます。図3はMacの例ですが,Linuxでは最初のDarwinGlibcになった以外同じものが出力されるはずです。

図3 brainfuck.swiftの実行時出力

import Darwin
var data = [CChar](repeating:CChar(0), count:65536)
var (sp, pc) = (0, 0)
data[sp] += 1
while data[sp] != CChar(0) {
data[sp] = {c in CChar(c < 0 ? 0 : c)}(getchar())
sp -= 1
sp += 1
putchar(Int32(data[sp]))
}
data[sp] -= 1

これをたとえばecho.swiftというテキストファイルにセーブしたうえで,次のようにシェルからコンパイルして実行してみます。

$ swiftc echo.swift
$ ./echo < echo.swift

echo.swiftの中身がそのまま出力されれば成功です。

では処理系中の最後から2番目のsrc+++++++++[>++++++++>+++++++++++>+++++<<<-]>.>++.+++++++..+++.>-.------------.<++++++++.--------.+++.------.--------.>+.にしたうえで,もう一度同じようにしてみてください。Hello, world!と表示されましたか?

それではあらためて処理系のソースコードを見てみましょう。こんな小さなコードからでも,次のことが読み解けるはずです表1)⁠

  • 変数varや定数letを定義するにはどうすればよいか
  • 文字列中に変数を展開(interpolate)するにはどうすればよいか
  • 型を指定すればどうなるか
    • →指定しない場合はどうなるか?
    • bf2swift:[Character:String]:[Character:String]を消したらどんなエラーが出るか
  • 辞書(Dictionary)をどう初期化してどう使うか
  • 配列(Array)をどう初期化してどう使うか
  • 文字列を1文字ごとに処理するにはどうすればよいか
  • 既存のデータ型(String)にメソッドを追加するにはどうすればよいか(extension)⁠
  • アーキテクチャごとに処理を変えたい場合はどうすればよいか(#if)

表1 CとSwift実装比較

BFCSwift
>sp++;sp += 1
<sp--;sp -= 1
+data[sp]++;data[sp] += 1
-data[sp]--data[sp] -= 1
[while(data[sp]){while data[sp] != CChar(0) {
]}}
.putchar(data[sp])putchar(Int32(data[sp]))
,data[sp] = getchar()data[sp] = {c in CChar(c < 0 ? 0 : c)}(getchar())

BF:Brainfuck

余裕があったら,次の課題にも挑戦してみてください。

  • BrainfuckにはBrainfuck自身で書かれた処理系が存在するが,その処理系を本処理系で生成してみる
  • 現状ソースコード中のsrcにハードコードされたBrainfuckコードではなく,任意のソースファイルをコンパイルできるようにしてみる
  • Swift処理系をBrainfuckで実装してみる

最後はさすがに冗談ですが,ある言語で簡素な言語の処理系を実装するというのは,その言語を覚える一番の近道の1つ。さすがにBrain fuckほど簡単ではありませんが,Lispの実装などはなかなか楽しそうです。

では,今月はこのへんで。

Software Design

本誌最新号をチェック!
Software Design 2017年5月号

2017年4月18日発売
B5判/192ページ
定価(本体1,220円+税)

  • 第1特集
    先輩が教えるマル得ノウハウ
    Linux入門(UNIXネットワーク編)
  • 第2特集
    サイボウズ流
    サービス改善につなげるドッグフーディング環境の作り方
  • 第3特集
    いまから学ぶブロックチェーンのしくみ
    ブロックチェーンの構造と機能,次なる展開
  • 一般記事
    DDoS攻撃! そのときクラウド事業者は!?
    クラウド事業者が考えるDDoS攻撃への対策と対処法
  • 一般記事
    [ニフティクラウド mobile backend]mBaaSのしくみ紹介【2】
    クラウドサービスで運用不要! すべておまかせシステムの舞台裏
  • 一般記事
    [短期集中連載]人工知能時代のLispのススメ
    【1】なぜ今Lispなのか? Lispはここがすごい!

著者プロフィール

小飼弾(こがいだん)

1969年生まれ,東京都出身。元ライブドア取締役の肩書きよりも,最近はPokemon GOのガチトレーナーのほうが有名になりつつある……かもしれない永遠のエンジニアオヤジ。

活躍の場はIT業界だけでなく,サブカルからアカデミックまで多方面にわたり,ネットからの情報発信は気の向くまま毎日毎秒! https://twitter.com/dankogai,ニコニコチャンネルは,http://ch.nicovideo.jp/dankogai,blogはhttp://blog.livedoor.jp/dankogai/

当社刊行書籍は『小飼弾のアルファギークに逢ってきた』『小飼弾のコードなエッセイ』など。他にも著書多数。

コメント

コメントの記入