Open36

Swiftの勉強

oiltypebluroiltypeblur

Simple Values

変数、定数、文字列埋め込み、配列、マップ。

oiltypebluroiltypeblur

Objects and Classes

コンストラクタはinit()。
Rustでは同じスコープで同名の定数を上書きできるが、Swiftではエラーになる。
setterの定義時にnewValueを使えるのは便利。どうせ引数書いてもラベルはnewValueだし。
willSet/didSetがデフォルトであるのも良い。
メンバ変数をprivateにする方法は?→この章では解説なし。privateをつける。

oiltypebluroiltypeblur

Enumerations and Structures

enumが強力。Rust?
classは参照、structは値としてコピー。

oiltypebluroiltypeblur

Protocols and Extensions

プロトコルはclassもstructも適用可能。
組み込み型もextensionで拡張できる。

oiltypebluroiltypeblur

Generics

enumでもジェネリクスが使える。
whereで制約が書ける。C++のConcepts?

oiltypebluroiltypeblur

以上で終わり。これでSwiftを書けるようになった気は全然しない。

oiltypebluroiltypeblur

The Basics

assert()でデバッグできる。
precondition()で事前条件をチェックできる。
precondition()は-Oでも実行される。
未実装な関数をとりあえず落としたい場合はfatalError("Unimplemented")を使う。

oiltypebluroiltypeblur

Strings and Characters

Stringは値型。
文字列に対するforループは文字単位で処理される。
文字列同士の比較は正規化した上で行われる。

oiltypebluroiltypeblur

Closures

Shorthand Argument Namesはクロージャを楽に書きたいという情熱を感じる。
Trailing Closuresはちょっと見ない文法。

oiltypebluroiltypeblur

Structures and Classes

classインスタンスのidenticalは===で確認する。ポインタではない。
メモリを操作する方法は別にある。

oiltypebluroiltypeblur

Properties

lazyで初期化のタイミングを遅延できる。バグの原因になりそう。
Properties Wrappersは便利な機能だと思うが、自分が定義することはそんなになさそう。使う範囲が狭ければ単にstructでつくるだろうし。
projected valueはちょっと魔術的ではなかろうか。便利かもしれないがわかりにくい。

oiltypebluroiltypeblur

Initialization

メンバ変数の初期化をクロージャでできるのはちょっと便利。どうせどこかに書くのならこれが一番良い。

oiltypebluroiltypeblur

Error Handling

try?で例外がnilに変換されるのは面白い。いいのか?とも思うが。

oiltypebluroiltypeblur

Opaque Types

返り値に使う場合はsomeをつける。ファクトリメソッド用?
Protocols Typesとの違いはtype identityを保証するかどうか。Opaqueの場合はassosiated typeでキャプチャ(?)した型の情報を保持することができる。

oiltypebluroiltypeblur

Automatic Reference Counting

参照関係を意識しないといけないの!?

oiltypebluroiltypeblur

流し読み終わり。相変わらずデバッグとテストのやり方はわからない。

oiltypebluroiltypeblur

SwiftでLispをつくってみる。
http://www.aoky.net/articles/peter_norvig/lispy.htm

Mac OSコマンドラインプロジェクトをつくる。
https://github.com/oiltypeblur/lisw

とりあえずテストを書こうとするがエラー。

Failed to build module 'XCTest' from its module interface; the compiler that produced it, 'Apple Swift version 5.3.1 (swiftlang-1200.2.41 clang-1200.0.32.8)', may have used features that aren't supported by this compiler, 'Apple Swift version 5.3.2 (swiftlang-1200.0.45 clang-1200.0.32.28)'

単にtestフォルダをつくってSwiftファイルを置くだけではだめらしい。Test navigatorでテストターゲットとしてtestを追加する。次にテスト実行をするとschemeをconfigurationしろと言われるのでここでtestを追加すると実行可能になる。

oiltypebluroiltypeblur

srcでpublic関数を定義し、test側でimportをするが、リンク時にundefined symbolエラー。@testable importでもだめ。

一方でGUIアプリプロジェクト作成時にテストも追加しておくとエラーは発生しない。何かの呪文が抜けているようだが調べてもわからない。後からテストを追加するのは一般的ではないのか?

swift packageでつくった場合も同様のエラー。わけがわからない。

oiltypebluroiltypeblur

swift package init --type libraryでつくればswift testが成功。

ただし、swift package generate-xcodeprojでつくったプロジェクトをXcodeで開いてテストすると以下のエラー。

Compiling for macOS 10.15, but module 'Lisw' has a minimum deployment target of macOS 11.1

おそらく10.15がデフォルト値。Package.swiftに明示的にplatformを指定してプロジェクトファイルを再生成したら解消した。

platforms: [
.macOS(.v11)
],
oiltypebluroiltypeblur

とりあえず簡単なS式は処理できるようになった。グローバル環境に登録された関数が+と<しかないしエラー時は大体fatalError()で落ちるが。

Swiftの良いところ

enumが強力。再帰的に定義できる分Rustより(多分)高機能。
guardがよい。ニーズの高いところにぴったりの文法を用意している。

Swiftの良くないところ

IDEのサポートがしょぼい。未定義の関数やクラスを書いたらサジェストしてほしい。これはAppCodeでは可能らしいが有料である。組み込みのコードフォーマッタもない?Ctrl+iでインデントはできるけど。
ドキュメントが英語。つらい。MSみたいに機械翻訳のドキュメントも困るが。

作り込んでもよいのだが、年を跨いでまでやることもないか。

oiltypebluroiltypeblur

swift-format

https://github.com/apple/swift-format

git clone -b swift-5.3-branch https://github.com/apple/swift-format.git
cd swift-format
swift build
swift run swift-format format -i foo.swift
swift run swift-format lint foo.swift

lintでenumはlowerCamel使えと出てくるが無視。