0

While researching XCTAssert methods by pressing command+click, it looks like they underlying method is a function that has a type (a generic type referred to as T, that conforms to the Equatable protocol). Am I saying this correctly, and if so how do functions comform to protocols? Are functions types?

public func XCTAssertEqual<T : Equatable>(_ expression1: @autoclosure () throws -> ArraySlice<T>, _ expression2: @autoclosure () throws -> ArraySlice<T>, _ message: @autoclosure () -> String = default, file: StaticString = #file, line: UInt = #line)

This line is the most confusing which I'm trying to explain above:

func XCTAssertEqual<T : Equatable>`
Laurence Wingo
  • 3,912
  • 7
  • 33
  • 61
  • 1
    that is just a "normal" function with a generic type parameter. And yes, function *have* types, for example `() -> String` or `(Int, Double) -> [UIView]`. – luk2302 Jul 09 '16 at 19:55
  • No a function cannot be a type. Types can be stored. Functions cannot. Blocks can be stored. Functions cannot. You can store pointers to functions, but not functions themselves. For example, I can store a struct. I cannot do this with a function. I can only store a pointer to it. There is no generic function pointer either (not in Swift). So you can't store a function pointer as an AnyObject or Any. You can BitCast an Objective-C function block to AnyObject and store it, but you're not storing a function. You're storing an NSMallocBlock that contains a pointer to a function. – Brandon Jul 09 '16 at 20:28
  • In swift, you can make a generic wrapper object that holds type T and store and block that calls any function. You'll of course have to cast it back to the right type. – Brandon Jul 09 '16 at 20:30
  • @Brandon please, see an appendix to my answer – user3441734 Jul 09 '16 at 20:43

1 Answers1

5

Every function has a specific function type, made up of the parameter types and the return type of the function.

typealias FooType = (Int, String)->String

func foo(i: Int, s: String)->String {
    return s + "_\(i)"
}

func bar(foo0: FooType)->String {
    return foo0(100, "alpha")
}

print(bar(foo))         // alpha_100

let f:FooType = { i, s in
    return s + "_\(i)"
}

print(f(200, "beta"))   // beta_200

an appendix, especially for Brandon :-)

let farr:[()->Int] = [{return 1}, {return 2}, {return 3}]
for f in farr {
    print(f())
/*
 1
 2
 3
*/
}

appendix 2, for Brandon

func f1()->Int {
    return 1
}
func f2()->Int {
    return 2
}

let farr2:[()->Int] = [f1, f2]
for f in farr2 {
    print(f())
/*
 1
 2
 */
}

app 3 :-)

let farr2 = [f1, f2]
for f in farr2 {
    print(f())
/*
 1
 2
 */
}

from apple docs

Every function in Swift has a type, consisting of the function’s parameter types and return type. You can use this type like any other type in Swift, which makes it easy to pass functions as parameters to other functions, and to return functions from functions. Functions can also be written within other functions to encapsulate useful functionality within a nested function scope.

user3441734
  • 16,722
  • 2
  • 40
  • 59
  • What? Those are blocks.. Each of their underlying types are NSBlock. http://pastebin.com/5Qxk3SUy http://clang.llvm.org/docs/Block-ABI-Apple.html – Brandon Jul 09 '16 at 20:46
  • @Brandon in Swift, we don't have blocks. – user3441734 Jul 09 '16 at 20:47
  • -_- are you kidding me? Pass it to Objective-C bridge function and print out its type. Then tell me swift doesn't have blocks. – Brandon Jul 09 '16 at 20:47
  • @Brandon no, i don't. please check apple docs. https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Functions.html – user3441734 Jul 09 '16 at 20:49
  • @Brandon blocks are a subset of Swift's closures, that's why you need to use `convention(block)` when you explicitly want a block (Swift can also infer this for ObjC calls). I'm not sure what's exactly the difference between the two other than the fact that closures are pure Swift and blocks come from ObjC. – Kametrixom Jul 09 '16 at 21:04
  • I don't have to use `@convention(block)` http://pastebin.com/yWqmzhg2 Also, just a second ago, you told me Swift does not have blocks. – Brandon Jul 09 '16 at 21:06
  • @Brandon take it easy ... Swift is not ObjectiveC. Yes, closures are 'similar' to blocs in C and ObjectiveC, they can be nested and passed around. In Swift functions are just a special kind of closures. – user3441734 Jul 09 '16 at 21:08
  • @Brandon please see my appendix2 with 'pure' functions – user3441734 Jul 09 '16 at 21:18
  • I don't know how else to explain this.. You are still storing only blocks. Pass that array to Objective-C and print out the element types. Here's what is capturing you. Implicit Storage. The compiler sees you trying to store a function into an array. Swift doesn't have Function Pointers. It instead will wrap the function into a block with equivalent SIGNATURE and store that into the array. Think about the signature of the array you have.. `[() -> Int]` is an array of Blocks that return Int type. – Brandon Jul 09 '16 at 21:24
  • Blocks are derived from `NSBlock` each NSBlock has a `Block_Literal_Descriptor`. Each one has a pointer to the NATIVE C function aka `invoke`: http://pastebin.com/J9078LF8 When you call a function, it just calls it natively. When you store it, one of the above is created and a pointer to the function is stored within it. When you call the above equivalent block, the compiler calls the "Invoke" function with the correct parameters, etc.. So functions aren't types and they aren't blocks. Blocks and Closures are the same. Swift just masks the pointer stuff from the developer. – Brandon Jul 09 '16 at 21:27
  • @Brendon ()->Int is a type of function with no parameters and returning Int. Once again, function in Swift is special kind of closure. – user3441734 Jul 09 '16 at 21:29
  • No it's not. Functions are not a special type of closure at all. If you do not try to store them in any way, they are just native C functions with the correct calling convention. When you store them, they are wrapped. If you still cannot understand that, I don't know how else to explain it. Print out the assembly. Put a symbolic break point, do whatever you need, to understand this because I give up. `() -> Int` is a type of Closure/Block. Not a function at all. Try making an array: `[func () -> Int]` It won't compile. – Brandon Jul 09 '16 at 21:30
  • @Brandon See [Difference between block (Objective C) and closure (Swift)](http://stackoverflow.com/questions/26374792/difference-between-block-objective-c-and-closure-swift-in-ios). Also, this compiles: `let x : @convention(swift) () -> () = {}` (uses explicitly closures). Also, this does not compile, but does when using `swift`: `let y : @convention(block) (inout Int) -> ()` – Kametrixom Jul 09 '16 at 21:43
  • @Brandon func is keyword, as let or var is. [let Int] will not compile too. Why? Because the proper syntax is [T] where T is some type. – user3441734 Jul 09 '16 at 21:52
  • @Kametrixom I already explained to the guy that a closure and a block is the same thing many times above. Copy semantics don't matter in this case. Yes Apple added a keyword to allow you to choose whether or not the block is copyable by default.. OR whether or not everything is references. That doesn't mean it not a closure. They have different copy semantics because of the way Swift works (references for Swift vs. pointers for Objective-C). Not because of the way blocks work. – Brandon Jul 09 '16 at 22:03
  • @Brandon Swift apparently works on Linux, where there isn't any Objective-C, and closures still exist, this means that they're not the same. I think *you* need to look up some stuff – Kametrixom Jul 09 '16 at 22:04
  • @Kametrixom GCC compiles Objective-C on Linux. I think you are actually the one that needs to look up stuff. Look up the implementation of Clang's Block in Objective-C and Swift's Closure. You're going to find they're exactly the same structs. That is why they are compatible. You can see my very first comment on this post. You guys are essentially saying a lambda and a function is the same thing. Go tell that to the C++11 community. Tell it to your compiler which has different assembly for both. If you think Swift is sending messages to call functions, you're dead wrong. – Brandon Jul 09 '16 at 22:05
  • @Brandon please, contact apple and ask the guys there to make corrections to their documentation, so we, the rest of the world could follow you. – user3441734 Jul 09 '16 at 22:05