プロトコル指向 - 夢と現実の狭間 #cswift

1,744 views

Published on

Swift 3.0 で、廃止される BooleanType と、強化される FloatingPoint と。それらを見たときに感じた衝撃。その事実を観察しながら、実際の様子、感じたこと、これからのこと。そんなことを綴った発表資料です。

Published in: Software
0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
1,744
On SlideShare
0
From Embeds
0
Number of Embeds
1,291
Actions
Shares
0
Downloads
6
Comments
0
Likes
1
Embeds 0
No embeds

No notes for slide

プロトコル指向 - 夢と現実の狭間 #cswift

  1. 1. struct Variant : BooleanType { }
  2. 2. 
 

  3. 3. #cswift
  4. 4. protocol BooleanType { var boolValue: Bool { get } } // 適用した型は、そのまま condition として使える let value = MyValue() if value { }
  5. 5. // protocol BooleanType { // var boolValue: Bool { get } // } // Bool 以外は condition に使えない let value = MyValue() if value { }
  6. 6. // こんな風に API を書いてましたか? func removeAll<T: BooleanType>(keepCapacity: T) { } // こう書いていませんでしたか? func removeAll(keepCapacity: Bool) { }
  7. 7. 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
  8. 8. // 普通は Bool 型しか受け取らない // ObjCBool を受け取ったら boolValue で Bool 値を取得 if objcBool.boolValue { } // ちなみに CBool は Bool の型エイリアス typealias CBool = Bool
  9. 9. prefix func !(a: Bool) -> Bool func &&(lhs: Bool, @autoclosure rhs: () -> Bool) -> Bool func ||(lhs: Bool, @autoclosure rhs: () -> Bool) -> Bool
  10. 10. let condition: ObjCBool = true if condition.boolValue { }
  11. 11. struct ObjCBool { var boolValue: Bool } // ジェネリックで使いたいときは…また作りますか? protocol Boolean { var boolValue: Bool } extension ObjCBool : Boolean { }
  12. 12. // ともすると、真か偽を表現しそうな型 enum Result { case success case failure // これが boolValue だと『何が真か』考える間が発生 var isOK: Bool { … } }
  13. 13. // BooleanType 適用を廃止 extension JSON /* : BooleanType */ { // boolValue プロパティは存続 var boolValue: Bool { … } } // 判定は boolValue 必須だが、むしろ意味を汲みやすい? if json.boolValue { }
  14. 14. // 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
  15. 15. // 数字にならない計算は、非数値 0.0 / 0.0 // nan // 非数値に演算しても、非数値 Double.nan + 10.0 // nan // 非数値を無限大で割っても、非数値 Double.nan / Double.infinity // nan // 負の非数値というのもある (-Double.nan).sign // minus
  16. 16. // 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
  17. 17. // 無限大から大きな値を引いても、無限大 Float.infinity - 1.0e+38 // inf // 最大値に十分な値を足すと、無限大 maxFloat + 1.0e+38 // inf // 最大値に小さな値を足しても、無限にはならない maxFloat + 1.0 // maxFloat // 一旦無限になると、辻褄が合わなくなることも maxFloat + 1.0e+38 - 1.0e+38 // inf
  18. 18. // 正の方向から割ると、+∞ 1.0 / 0.0 // inf // 負の方向から割ると、-∞ 1.0 / -0.0 // -inf // 浮動小数点数でないと // 表現できない 1 / 0 // ERROR y = 1/x x y O
  19. 19. 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)
  20. 20.
  21. 21. // Float 型の Signaling NaN を作る var sNaNSeed = 0b1_11111111_00000000000000000000001 as UInt32 var sNaN = unsafeBitCast(sNaNSeed, to: Float.self)
  22. 22. // Float 型の最大値を作る var maxSeed = 0b0_11111110_11111111111111111111111 as UInt32 var max = unsafeBitCast(maxSeed, to: Float.self)
  23. 23. associatedtype Exponent : SignedInteger init(sign: FloatingPointSign, exponent: Exponent, significand: Self) // 浮動小数点数 を作れる(Float の基数は 2 ) Float(sign: .plus, exponent: 10, significand: 1.5) 1.5 210
  24. 24. associatedtype Exponent : SignedInteger init(signOf: Self, magnitudeOf: Self) // value1 の符号と value2 の絶対値を合わせて、値を作る Float(signOf: value1, magnitudeOf: value2)
  25. 25.
  26. 26. +, -, *, /, +=, -=, *=, /=, ==, <<, <=, >, >=
  27. 27. 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) }
  28. 28. // Float 型の Signaling NaN を作る var sNaN = Float.signalingNaN
  29. 29. // Float 型の最大値を作る var max = Float.greatestFiniteMagnitude
  30. 30. init(_ value: Float) init(_ value: Double) init(_ value: Float80) // Float80 は macOS のみ
  31. 31. associatedtype RawSignificand : UnsignedInteger associatedtype RawExponent : UnsignedInteger // IEEE 754 の仕様に基づき、ビットを指定する init(sign: FloatingPointSign, exponentBitPattern: RawExponent, significandBitPattern: RawSignificand)
  32. 32. 0. 1.
  33. 33. 1.0 2
  34. 34. 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
  35. 35. pi80.significand // 1.570796326794896558 pi80.exponent // 1 pi64.significand // 1.570796326794897 pi64.exponent // 1 pi32.significand // 1.570796 pi32.exponent // 1 significand 2exponent
  36. 36. Float80.significandBitCount // 小数部 … 63 bit Float80.exponentBitCount // 仮数部 … 15 bit Float64.significandBitCount // 小数部 … 52 bit Float64.exponentBitCount // 仮数部 … 11 bit Float32.significandBitCount // 小数部 … 23 bit Float32.exponentBitCount // 仮数部 … 8 bit
  37. 37. n.xxxx 0.xxxx
  38. 38. /* 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)
  39. 39. Float80.pi.significandBitPattern 100100100001111110110101010001000100001011010001100000000000000 Float64.pi.significandBitPattern 1001001000011111101101010100010001000010110100011000 Float32.pi.significandBitPattern 10010010000111111011010
  40. 40.

×