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

  • View
    1.561

  • Download
    0

  • Category

    Software

Preview:

Citation preview

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

Recommended