Skip to content
dankogai edited this page Oct 24, 2014 · 12 revisions

Built-in overloads

(A->R) === (A->R)

Checks if the function object lhs is identical to rhs.

Identical means that the internal function pointer points to the same address.

func peekFunc<A,R>(f:A->R)->(fp:Int, ctx:Int) {
    typealias IntInt = (Int, Int)
    let (hi, lo) = unsafeBitCast(f, IntInt.self)
    let offset = sizeof(Int) == 8 ? 16 : 12
    // let ptr  = UnsafePointer<Int>(lo+offset)
    let ptr  = UnsafePointer<Int>(bitPattern: lo+offset)
    return (ptr.memory, ptr.successor().memory)
}
func === <A,R>(lhs:A->R,rhs:A->R)->Bool {
    let (tl, tr) = (peekFunc(lhs), peekFunc(rhs))
    return tl.0 == tr.0 && tl.1 == tr.1
}

Usage:

// simple functions
func genericId<T>(t:T)->T { return t }
func incr(i:Int)->Int { return i + 1 }
var f:Int->Int = genericId
var g = f;      println("(f === g) == \(f === g)")
f = genericId;  println("(f === g) == \(f === g)")
f = g;          println("(f === g) == \(f === g)")
// closures
func mkcounter()->()->Int {
    var count = 0;
    return { count++ }
}
var c0 = mkcounter()
var c1 = mkcounter()
var c2 = c0
println("peekFunc(c0) == \(peekFunc(c0))")
println("peekFunc(c1) == \(peekFunc(c1))")
println("peekFunc(c2) == \(peekFunc(c2))")
println("(c0() == c1()) == \(c0() == c1())") // true : both are called once
println("(c0() == c2()) == \(c0() == c2())") // false: because c0() means c2()
println("(c0 === c1) == \(c0 === c1)")
println("(c0 === c2) == \(c0 === c2)")

See URLs below to find how it works:

(A->R) !== (A->R)

func !== <A,R>(lhs:A->R,rhs:A->R)->Bool {
    let (tl, tr) = (peekFunc(lhs), peekFunc(rhs))
    return tl.0 != tr.0 || tl.1 != tr.1
}

Custom Operators

A => (A->R)

arg => fun does what fun(arg) does.

infix operator => { associativity left precedence 95 }
func => <A,R> (lhs:A, rhs:A->R)->R {
    return rhs(lhs)
}

Example:

2.0 => { Array(count:Int($0), repeatedValue:$0) }
    => { $0.map{$0 * $0} }
    => println  // [4.0, 4.0]

(A->R) =< A

=> in reverse order

infix operator =< { associativity right precedence 95 }
func =< <A,R> (lhs:A->R, rhs:A)->R {
    return lhs(rhs)
}

Example:

println // [4.0, 4.0]
    =< { $0.map{$0 * $0} }
    =< { Array(count:Int($0), repeatedValue:$0) }
    =< 2.0

(A->I) *> (I->R)

Compose funcitons.

infix operator *> { associativity left precedence 160 }
func *> <A,I,R> (lhs:A->I, rhs:I->R)->A->R {
    return { rhs(lhs($0)) }
}

(I->R) <* (A->I)

*> in reverse order.

infix operator <* { associativity right precedence 160 }
func <* <A,I,R> (lhs:I->R, rhs:A->I)->A->R {
    return { lhs(rhs($0)) }
}