⭐
1 / 7
// 定義は、外部引数名、内部変数名、型名を活用して紡ぐ
func insert(_ newItem: Item, into position: Int)
// 使用時は、変数名も活用して紡ぐ
bookshelf.insert(newBook, into: freeSpace)
// item が冗長だったり、freeSpace が説明不足だったり
bookshelf.insert(item: newBook, position: freeSpace)
// 定義を見れば、意図を汲めるけれど…
func add(handler: () -> Void, for eventName: String)
// 使用時に、説明不足で主体から用途が想像しにくい
document.add(handler: () -> Void, for: String)
// 定義時に名前で補足すると…
func addEventHandler(_ handler: () -> Void,
forEventName name: String)
// 使用時に用途を汲みやすくなる
document.addEventHandler(handler: () -> Void,
forEventName: String)
// 動詞系で、自身を書き換えないなら、末尾に“ed”とか
nonmutating func advanced(by n: Int) -> Int
// 動詞系で、自身を書き換えないなら、末尾に“ing”とか
nonmutating func adding(_ other: Int) -> Int
// 動詞系で、自身を書き換えるなら、動詞そのもの
mutating func add(_ other: Int)
// 名詞系で、自身を書き換えないなら、名詞そのもの
nonmutating func squareRoot() -> Double
// 名詞系で、自身を書き換えるなら、先頭に“form”付与
mutating func formSquareRoot()
// 引数を書き換える場合も Mutating と同じく“form”付与
nonmutating func formIndex(after i: inout Int)
// 素直に命名するとラベルがアンバランスになる
func cell(atColumn: Int, row: Int) -> Cell
// at をメソッド名に含めることでラベルが整う
func cellAt(column: Int, row: Int) -> Cell
// タプルで表現することでもバランスが取れる
func cell(at location: (column:Int, row:Int)) -> Cell
⭐
2 / 7
// bytes と count をとって初期化する
init(bytes: UnsafeRawPointer, count: Int)
// value と radix と uppercase をとって初期化する
init(_ value: Int, radix: Int, uppercase: Bool)
// lower と upper をとって初期化する
init(lower: Bound, upper: Bound)
// Int 型の値を String 型で忠実に再現(全幅変換)
struct String {
init(_ value: Int, radix: Int = 10)
}
// UInt32 型の値をビットパターンとして Int32 型に再解釈
struct Int32 {
init(truncatingBitPattern pattern: UInt64)
}
// Int 型の値を String 型にキャスト(全幅変換)
let string = String(number, radix: 16)
// ビットパターンを指定して Int32 型を生成(Narrow 変換)
let value = Int32(truncatingBitPattern: number)
// 範囲を生成
let range = MyRange(lower: start, upper: last)
⭐
3 / 7
// 自作の型なら、直接でも拡張でも自由に備えられる
struct Bookshelf : Collection {
mutating func arrange() { … }
}
// 他者が作ったものにも、拡張で備えられる
extension Collection where Iterator.Element == Book {
func sortedByTitle() -> [Book] { … }
}
// 全ての値が対等で、主体が定まらない
func average(of values: Double...) -> Double
// 具体的な主体が定義に現れないため、所属できない
func convert<T: Any, U: Compatible>(from: T) -> U
// プログラミングの分野では、絶対値は関数 abs で取得する
func abs(_ x: Double) -> Double
⭐
4 / 7
struct Int128 {
fileprivate var low: UInt64
fileprivate var high: UInt64
// Int 型の値を Int128 型に全幅変換
init(_ value: Int) {
low = UInt64(value)
high = 0
}
}
extension Int {
// Int128 型の値を Int 型に全幅変換
init(_ value: Int128) {
guard value.high == 0 else {
fatalError("Overflow")
}
self = Int(value.low)
}
}


// お馴染みの Double から Int へのキャスト例
let taxIncluded = Int(Double(price) * (1 + tax))
// お馴染みのキャストと同じ書き方になる
let endOfInteger = Int128(Int64.max) + 1
// 自作の Int128 から Int への変換もいつも通り
let stride = Int(Int128.max / samples)
⭐
5 / 7
// 標準ライブラリーに規定されている性質
/// A type that can be compared for value equality.
protocol Equatable {
/// Returns a Boolean value indicating
/// whether two values are equal.
static func ==(lhs: Self, rhs: Self) -> Bool
}
// プロトコルで比較可能性を説明すると…
extension Int128 : Equatable {
static func == (lhs: Int128, rhs: Int128) -> Bool {
return (lhs.low, lhs.high) == (rhs.low, rhs.high)
}
}
// 比較演算を使って比較可能になる
Int128(1000) == Int128(1000)
Int128(1000) != Int128(1000)
// 比較可能な要素を扱う場合だけ使えるようになっている
extension Array where Element : Equatable {
func index(of element: Element) -> Int?
}
// 配列で、要素からインデックスを特定できるようになる
let values = [Int128(1), Int128(5), Int128(10)]
let index = values.index(of: Int128(5))
⭐
6 / 7
// 標準ライブラリーに規定されている性質
/// A type with a customized textual representation.
protocol CustomStringConvertible {
/// A textual representation of this instance.
var description: String { get }
}
enum Device : CustomStringConvertible {
case iPhone, iPad, appleWatch
var description: String {
switch self {
case .iPhone: return "iPhone"
case .iPad: return "iPad"
case .appleWatch: return " Watch"
}
}
let device = Device.appleWatch
// テキスト表現への Narrow 変換
let displayText = String(describing: device)
// テキスト表現に変換して、テキストコンソールに出力
print(device)
// String 型の文字列補完構文は、テキスト表現を使用
let message = "I love (device)"
⭐
7 / 7
// 変数 floatValues が Array<Float> で定義されている
let floatValues: [Float]
// サブスクリプトに範囲を渡すと、部分配列が取れる
let slice = floatValues[2 ..< 6]
// 部分配列の型は ArraySlice<Float> になる
type(of: slice) == ArraySlice<Float>.self
// 一般的な定義の仕方
func sum(of values: [Double]) -> Double {
return values.reduce(0, +)
}
// Float 型の配列の部分配列の合計を計算
sum(of: floatValues[2 ..< 6].map(Double.init))
// 任意の浮動小数点数を対象にする
func sum<T: FloatingPoint>(of values: [T]) -> T {
return values.reduce(0, +)
}
// Float 型の配列の部分配列の合計を計算
sum(of: Array(floatValues[2 ..< 6]))
// 標準ライブラリーに規定されている性質
/// A type that provides sequential,
/// iterated access to its elements.
public protocol Sequence {
/// A type that provides the sequence's iteration
/// interface and encapsulates its iteration state.
associatedtype Iterator : IteratorProtocol
// 連続する任意の浮動小数点数を対象にする
func sum<S: Sequence, T: FloatingPoint>
(of values: S) -> T where S.Iterator.Element == T {
return values.reduce(0, +)
}
// 連続する浮動小数点数の部分配列の合計を計算
sum(of: floatValues[2 ..< 6])
// 自身の値でストライドできる値を対象にする
func sum<S: Sequence, T:Strideable>(of values: S) -> T
where S.Iterator.Element == T, T.Stride == T {
return values.reduce(0) { $0.advanced(by: $1) }
}
// 連続する値の部分配列の合計を計算
sum(of: floatValues[2 ..< 6])
sum(of: integerValues[2 ..< 6])
// 整数を対象とした合計関数
func sum<S:Sequence, T:Integer>(of values:S) -> T
where S.Iterator.Element == T {
return values.reduce(0, +)
}
// 浮動小数点数を対象とした合計関数
func sum<S:Sequence, T:FloatingPoint>(of values:S) -> T
where S.Iterator.Element == T {
return values.reduce(0, +)
}















Swift らしい表現を目指そう #eventdots