いものやま。

雑多な知識の寄せ集め

Swiftをコマンドラインから使ってみた。

現在、Swiftについて勉強中・・・

とりあえず、Swiftコマンドラインから使ってみた。

なお、Xcodeのバージョンは、6.3.2。

swiftコマンド

まず、swiftコマンド。

このコマンドを使うと、Swiftを対話的に使ったり、スクリプトを実行させたりすることが出来る。

対話的な利用

swiftコマンドを引数なしで実行すると、Rubyirbのように、対話的に使うことが出来る。

例えば、以下のような感じ。

$ swift
Welcome to Swift version 1.2. Type :help for assistance.
  1> 1 + 2
$R0: Int = 3
  2> println("Hello")
Hello
  3> class Fibonacci {
  4.     private var first: Int
  5.     private var second: Int
  6.     init(first: Int = 1, second: Int = 1) {
  7.         self.first = first
  8.         self.second = second
  9.     }
 10.     func get() -> Int {
 11.         let old_first = self.first
 12.         self.first = self.second
 13.         self.second += old_first
 14.         return old_first
 15.     }
 16.     func get(count: Int) -> [Int] {
 17.         var ret = [Int]()
 18.         for _ in 1...count {
 19.             ret.append(self.get())
 20.         }
 21.         return ret
 22.     }
 23. }
 24> let fibo = Fibonacci()
fibo: Fibonacci = {
  first = 1
  second = 1
}
 25> fibo.get()
$R1: Int = 1
 26> fibo.get()
$R2: Int = 1
 27> fibo.get(5)
$R3: [Int] = 5 values {
  [0] = 2
  [1] = 3
  [2] = 5
  [3] = 8
  [4] = 13
}
 28> :quit

swiftコマンドを実行すると、まず簡単なメッセージが表示され、その次に行番号とプロンプト(>)が表示されるので、ここにSwiftのコードを書いていくことになる。

書いたコードは、1文ごとに解釈、実行される。
なお、クラスの定義や、if文、while文などのように、複数行に渡るような文の場合、プロンプトがドット(.)になり、文が終わるまではカーソルを移動して修正することも出来る。

対話的な利用を終了したい場合、:quitというコマンドを打つと、終了できる。
(あるいは、Ctrl+DでもOK)

なお、一応:helpでヘルプを見ることも出来るけど、正直、あまり有益な情報は出てこない感じ・・・
LLVMのデバッガであるLLDBを起動してhelpを実行すると、ほぼ同じヘルプメッセージが出るので、おそらく内部的にデバッガの式評価の機能を使っていて、ヘルプメッセージもこれをほぼそのまま流用しているのだと思う)

スクリプトの実行

swiftコマンドに引数としてSwiftのファイルを指定すると、そのファイルをスクリプトとして実行してくれる。

例えば、次のようなファイルを用意してみる。

/* Fibonacci.swift */

class Fibonacci {
    private var first: Int
    private var second: Int
    init(first: Int = 1, second: Int = 1) {
        self.first = first
        self.second = second
    }
    func get() -> Int {
        let old_first = self.first
        self.first = self.second
        self.second += old_first
        return old_first
    }
    func get(count: Int) -> [Int] {
        var ret = [Int]()
        for _ in 1...count {
            ret.append(self.get())
        }
        return ret
    }
}

let fibo = Fibonacci()
println(fibo.get())
println(fibo.get())
println(fibo.get(5))

内容的には先程の対話的な利用のコードとほぼ同じだけど、対話的な利用のときと違って、実行結果はそのままでは表示されないので、println()を使って表示させるようにしている。

このファイルをswiftコマンドで実行させると、次のような感じ。

$ swift Fibonacci.swift
1
1
[2, 3, 5, 8, 13]

なお、シバンをつけて実行権限をつけると、コマンドのように実行することも出来る。

例えば、以下のような感じ。

$ cat > fibonacci
#!/usr/bin/swift
^D
$ cat Fibonacci.swift >> fibonacci
$ chmod 755 fibonacci
$ ./fibonacci
1
1
[2, 3, 5, 8, 13]

swiftcコマンド

swiftcコマンドを使うと、Swiftで書かれたファイルをコンパイルし、実行ファイルを作ることが出来る。

なお、自分の環境の場合、swiftcをそのまま使おうとするとエラーになるので、次のように実行する必要があった。

$ xcrun -sdk macosx swiftc (swiftcのオプションやコマンドライン引数)

単一ファイル

単一ファイルをコンパイルするには、単にそのファイル名を指定すればいい。
そうすると、そのファイルと同名の実行ファイルが作成される。

例えば、先程のFibonacci.swiftコンパイルすると、次のような感じ。

$ ls -F
Fibonacci.swift
$ xcrun -sdk macosx swiftc Fibonacci.swift
$ ls -F
Fibonacci*  Fibonacci.swift
$ ./Fibonacci
1
1
[2, 3, 5, 8, 13]

複数ファイル

小さいプログラムならファイル1枚でもいいけど、もうちょい大きなプログラムを書こうとしたら、やはりファイルを分割したいところ。

ファイルを分割する場合、次のような制約がある。

  • C言語のmain関数に相当するコードは、main.swiftというファイルのトップレベルに書く。
  • main.swift以外のファイルには、トップレベルにコードを書いてはいけない。

そして、コンパイルは次のように行う。

$ xcrun -sdk macosx swiftc -o (実行ファイル名) main.swift (その他のソースファイル)

例えば、先程のファイルの場合、次のような感じに分割し、そしてコンパイルすることになる。

/* Fibonacci.swift */

class Fibonacci {
    private var first: Int
    private var second: Int
    init(first: Int = 1, second: Int = 1) {
        self.first = first
        self.second = second
    }
    func get() -> Int {
        let old_first = self.first
        self.first = self.second
        self.second += old_first
        return old_first
    }
    func get(count: Int) -> [Int] {
        var ret = [Int]()
        for _ in 1...count {
            ret.append(self.get())
        }
        return ret
    }
}
/* main.swift */

let fibo = Fibonacci()
println(fibo.get())
println(fibo.get())
println(fibo.get(5))
$ xcrun -sdk macosx swiftc -o Fibonacci main.swift Fibonacci

Makefile

コードを複数ファイルに分割した場合、各ファイルの動作確認として、簡単なコードを書いて実行してみたいことがけっこうある。
こういったとき、Pythonif __name__ == "__main__"Rubyif __FILE__ == $PROGRAM_NAMEは便利なんだけど、Swiftの場合、そういったことは出来ない。

そこで、一つの方法として、Makefileを使うことが考えられる。

例えば、先程のmain.swiftは、Fibonacciというクラスの動作確認なので、FibonacciTest.swiftというファイル名に変えて、次のようなMakefileを用意してみる。

# source files of module
SOURCE = Fibonacci.swift

# source files for test
TEST_SOURCE = FibonacciTest.swift

# test application name (DON'T EDIT)
TEST_APP = $(TEST_SOURCE:%.swift=%)

# make rules (DON'T EDIT)

testbuild: $(TEST_APP)

$(TEST_APP): $(SOURCE)

$(TEST_APP):%:%.swift
  cp $< main.swift
  xcrun -sdk macosx swiftc -o $@ main.swift $(SOURCE)
  rm main.swift

こうすると、make testbuildとすることで、動作確認のコードを簡単にコンパイルすることが出来る。

ファイルや動作確認のコードを追加した場合は、SOURCEやTEST_SOURCEにファイルを追加すればいい。

(なお、ちゃんと使うには、もうちょい手を加える必要がある。
cleanの定義とか、main.swiftを書き潰さないようにするとか)

今日はここまで!