プロトコル指向 - 夢と現実の狭間 #cswift
-
Upload
tomohiro-kumagai -
Category
Software
-
view
1.561 -
download
0
Transcript of プロトコル指向 - 夢と現実の狭間 #cswift
struct Variant : BooleanType { }
protocol BooleanType { var boolValue: Bool { get } }
// 適用した型は、そのまま condition として使える let value = MyValue()
if value {
}
// protocol BooleanType { // var boolValue: Bool { get } // }
// Bool 以外は condition に使えない let value = MyValue()
if value {
}
// こんな風に API を書いてましたか? func removeAll<T: BooleanType>(keepCapacity: T) { } // こう書いていませんでしたか? func removeAll(keepCapacity: Bool) { }
prefix func !<T : BooleanType>(a: T) -> Bool
func &&<T : BooleanType, U : BooleanType> (lhs: T, @autoclosure rhs: () -> U) -> Bool
func ||<T : BooleanType, U : BooleanType> (lhs: T, @autoclosure rhs: () -> U) -> Bool
// 普通は Bool 型しか受け取らない
// ObjCBool を受け取ったら boolValue で Bool 値を取得 if objcBool.boolValue { } // ちなみに CBool は Bool の型エイリアス typealias CBool = Bool
prefix func !(a: Bool) -> Bool
func &&(lhs: Bool, @autoclosure rhs: () -> Bool) -> Bool
func ||(lhs: Bool, @autoclosure rhs: () -> Bool) -> Bool
let condition: ObjCBool = true if condition.boolValue { }
struct ObjCBool {
var boolValue: Bool }
// ジェネリックで使いたいときは…また作りますか? protocol Boolean {
var boolValue: Bool }
extension ObjCBool : Boolean { }
// ともすると、真か偽を表現しそうな型 enum Result {
case success case failure
// これが boolValue だと『何が真か』考える間が発生 var isOK: Bool { … } }
// BooleanType 適用を廃止 extension JSON /* : BooleanType */ {
// boolValue プロパティは存続 var boolValue: Bool { … } }
// 判定は boolValue 必須だが、むしろ意味を汲みやすい? if json.boolValue {
}
Ծج�ࢦ
// Double は倍精度浮動小数点数 (64 bit) let value: Double = 10.5
// Float は単精度浮動小数点数 (32 bit) let value: Float = 10.5
// 0.0 で割ると、無限大 value / 0.0 // inf
// 表現しきれない値は、無限大 pow(35.0, 256.0) // inf
// 数字にならない計算は、非数値 0.0 / 0.0 // nan
// 非数値に演算しても、非数値 Double.nan + 10.0 // nan
// 非数値を無限大で割っても、非数値 Double.nan / Double.infinity // nan
// 負の非数値というのもある (-Double.nan).sign // minus
// signaling NaN を計算すると quiet NaN
Double.signalingNaN / 10.0 // quiet NaN
// ただし signaling NaN * -1 の計算なら // quiet NaN にならずに signaling NaN を維持
let value = Double.signalingNaN * -1 value.isSignalingNaN // true value.sign // minus
// 無限大から大きな値を引いても、無限大 Float.infinity - 1.0e+38 // inf
// 最大値に十分な値を足すと、無限大 maxFloat + 1.0e+38 // inf
// 最大値に小さな値を足しても、無限にはならない maxFloat + 1.0 // maxFloat
// 一旦無限になると、辻褄が合わなくなることも maxFloat + 1.0e+38 - 1.0e+38 // inf
// 正の方向から割ると、+∞ 1.0 / 0.0 // inf
// 負の方向から割ると、-∞ 1.0 / -0.0 // -inf
// 浮動小数点数でないと // 表現できない 1 / 0 // ERROR
y = 1/x
x
y
O
init(_ value: UInt8) init(_ value: Int8) init(_ value: UInt16) init(_ value: Int16) init(_ value: UInt32) init(_ value: Int32) init(_ value: UInt64) init(_ value: Int64) init(_ value: UInt) init(_ value: Int)
// Float 型の Signaling NaN を作る
var sNaNSeed = 0b1_11111111_00000000000000000000001 as UInt32
var sNaN = unsafeBitCast(sNaNSeed, to: Float.self)
// Float 型の最大値を作る
var maxSeed = 0b0_11111110_11111111111111111111111 as UInt32
var max = unsafeBitCast(maxSeed, to: Float.self)
associatedtype Exponent : SignedInteger
init(sign: FloatingPointSign, exponent: Exponent, significand: Self)
// 浮動小数点数 を作れる(Float の基数は2) Float(sign: .plus, exponent: 10, significand: 1.5)
Ծج�ࢦ
1.5 � 210
associatedtype Exponent : SignedInteger
init(signOf: Self, magnitudeOf: Self)
// value1 の符号と value2 の絶対値を合わせて、値を作る Float(signOf: value1, magnitudeOf: value2)
+, -, *, /, +=, -=, *=, /=, ==, <<, <=, >, >=
let values = [1.8, 4.6, -5.0, .nan, 3.7, -4.6]
// 以下の結果 >> [-5, 1.8, 4.6, nan, -4.6, 3.7] values.sorted()
// 以下の結果 >> [-5, -4.6, 1.8, 3.7, 4.6, nan] values.sorted {
$0.isTotallyOrdered(belowOrEqualTo: $1) }
// Float 型の Signaling NaN を作る
var sNaN = Float.signalingNaN
// Float 型の最大値を作る
var max = Float.greatestFiniteMagnitude
init(_ value: Float) init(_ value: Double) init(_ value: Float80) // Float80 は macOS のみ
associatedtype RawSignificand : UnsignedInteger associatedtype RawExponent : UnsignedInteger
// IEEE 754 の仕様に基づき、ビットを指定する init(sign: FloatingPointSign, exponentBitPattern: RawExponent, significandBitPattern: RawSignificand)
Ծج�ࢦ
0.1.
1.0 � ࢦ2
let pi80 = Float80.pi // 3.141592653589793116 let pi64 = Double.pi // 3.141592653589793 let pi32 = Float.pi // 3.141593
pi80 == Float80(pi64) // true pi80 == Float80(pi32) // false
pi80.significand // 1.570796326794896558 pi80.exponent // 1
pi64.significand // 1.570796326794897 pi64.exponent // 1
pi32.significand // 1.570796 pi32.exponent // 1
significand � 2exponent
Float80.significandBitCount // 小数部 … 63 bit Float80.exponentBitCount // 仮数部 … 15 bit
Float64.significandBitCount // 小数部 … 52 bit Float64.exponentBitCount // 仮数部 … 11 bit
Float32.significandBitCount // 小数部 … 23 bit Float32.exponentBitCount // 仮数部 … 8 bit
n.xxxx
0.xxxx
/* pi80 仮数: 100100100001111110110101010001000100001011010001100000000000000 pi64 仮数: 1001001000011111101101010100010001000010110100011000
pi80 指数: 100000000000000 pi64 指数: 10000000000 */
String(pi80.significandBitPattern, radix: 2) String(pi80.exponentBitPattern, radix: 2)
String(pi64.significandBitPattern, radix: 2) String(pi64.exponentBitPattern, radix: 2)
Float80.pi.significandBitPattern 100100100001111110110101010001000100001011010001100000000000000
Float64.pi.significandBitPattern 1001001000011111101101010100010001000010110100011000
Float32.pi.significandBitPattern 10010010000111111011010