The book says that "functions and closures are reference types". So, how do you find out if the references are equal? == and === don't work.
func a() { }
let å = a
let b = å === å // Could not find an overload for === that accepts the supplied arguments
Chris Lattner wrote on the developer forums:
This is a feature we intentionally do not want to support. There are
a variety of things that will cause pointer equality of functions (in
the swift type system sense, which includes several kinds of closures)
to fail or change depending on optimization. If "===" were defined on
functions, the compiler would not be allowed to merge identical method
bodies, share thunks, and perform certain capture optimizations in
closures. Further, equality of this sort would be extremely
surprising in some generics contexts, where you can get reabstraction
thunks that adjust the actual signature of a function to the one the
function type expects.
https://devforums.apple.com/message/1035180#1035180
This means that you should not even try to compare closures for equality because optimizations may affect the outcome.
I searched a lot. There seems to be no way of function pointer comparison. The best solution I got is to encapsulate the function or closure in an hashable object. Like:
var handler:Handler = Handler(callback: { (message:String) in
//handler body
}))
Simplest way is designate the block type as #objc_block, and now you can cast it to an AnyObject which is comparable with ===. Example:
typealias Ftype = #convention(block) (s:String) -> ()
let f : Ftype = {
ss in
println(ss)
}
let ff : Ftype = {
sss in
println(sss)
}
let obj1 = unsafeBitCast(f, AnyObject.self)
let obj2 = unsafeBitCast(ff, AnyObject.self)
let obj3 = unsafeBitCast(f, AnyObject.self)
println(obj1 === obj2) // false
println(obj1 === obj3) // true
Update 2021; changed #objc_block to #convention(block) to support Swift 2.x and later (which don't recognize #objc_block).
I've been looking for the answer, too. And I've found it at last.
https://gist.github.com/dankogai/b03319ce427544beb5a4
What you need is the actual function pointer and its context hidden in the function object.
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)
return (ptr.memory, ptr.successor().memory)
}
#infix 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
}
And here is the demo:
// 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 the URLs below to find why and how it works:
https://github.com/rodionovd/SWRoute/wiki/Function-hooking-in-Swift
https://github.com/rodionovd/SWRoute/blob/master/SWRoute/rd_get_func_impl.c
As you see it is capable of checking identity only (the 2nd test yields false). But that should be good enough.
Here is one possible solution (conceptually the same as 'tuncay' answer). The point is to define a class that wraps some functionality (e.g. Command):
Swift:
typealias Callback = (Any...)->Void
class Command {
init(_ fn: #escaping Callback) {
self.fn_ = fn
}
var exec : (_ args: Any...)->Void {
get {
return fn_
}
}
var fn_ :Callback
}
let cmd1 = Command { _ in print("hello")}
let cmd2 = cmd1
let cmd3 = Command { (_ args: Any...) in
print(args.count)
}
cmd1.exec()
cmd2.exec()
cmd3.exec(1, 2, "str")
cmd1 === cmd2 // true
cmd1 === cmd3 // false
Java:
interface Command {
void exec(Object... args);
}
Command cmd1 = new Command() {
public void exec(Object... args) [
// do something
}
}
Command cmd2 = cmd1;
Command cmd3 = new Command() {
public void exec(Object... args) {
// do something else
}
}
cmd1 == cmd2 // true
cmd1 == cmd3 // false
Not a general solution, but if one is trying to implement a listener pattern, I've ended up returning an "id" of the function during the registration so I can use it to unregister later (which is kind of workaround to the original question for "listeners" case as usually unregistering comes down to checking the functions for equality, which is at least not "trivial" as per other answers).
So something like this:
class OfflineManager {
var networkChangedListeners = [String:((Bool) -> Void)]()
func registerOnNetworkAvailabilityChangedListener(_ listener: #escaping ((Bool) -> Void)) -> String{
let listenerId = UUID().uuidString;
networkChangedListeners[listenerId] = listener;
return listenerId;
}
func unregisterOnNetworkAvailabilityChangedListener(_ listenerId: String){
networkChangedListeners.removeValue(forKey: listenerId);
}
}
Now you just need to store the key returned by the "register" function and pass it when unregistering.
This is a great question and while Chris Lattner intentionally doesn't want to support this feature I, like many developers, also can't let go of my feelings coming from other languages where this is a trivial task. There are plenty of unsafeBitCast examples, most of them don't show the full picture, here's a more detailed one:
typealias SwfBlock = () -> ()
typealias ObjBlock = #convention(block) () -> ()
func testSwfBlock(a: SwfBlock, _ b: SwfBlock) -> String {
let objA = unsafeBitCast(a as ObjBlock, AnyObject.self)
let objB = unsafeBitCast(b as ObjBlock, AnyObject.self)
return "a is ObjBlock: \(a is ObjBlock), b is ObjBlock: \(b is ObjBlock), objA === objB: \(objA === objB)"
}
func testObjBlock(a: ObjBlock, _ b: ObjBlock) -> String {
let objA = unsafeBitCast(a, AnyObject.self)
let objB = unsafeBitCast(b, AnyObject.self)
return "a is ObjBlock: \(a is ObjBlock), b is ObjBlock: \(b is ObjBlock), objA === objB: \(objA === objB)"
}
func testAnyBlock(a: Any?, _ b: Any?) -> String {
if !(a is ObjBlock) || !(b is ObjBlock) {
return "a nor b are ObjBlock, they are not equal"
}
let objA = unsafeBitCast(a as! ObjBlock, AnyObject.self)
let objB = unsafeBitCast(b as! ObjBlock, AnyObject.self)
return "a is ObjBlock: \(a is ObjBlock), b is ObjBlock: \(b is ObjBlock), objA === objB: \(objA === objB)"
}
class Foo
{
lazy var swfBlock: ObjBlock = self.swf
func swf() { print("swf") }
#objc func obj() { print("obj") }
}
let swfBlock: SwfBlock = { print("swf") }
let objBlock: ObjBlock = { print("obj") }
let foo: Foo = Foo()
print(testSwfBlock(swfBlock, swfBlock)) // a is ObjBlock: false, b is ObjBlock: false, objA === objB: false
print(testSwfBlock(objBlock, objBlock)) // a is ObjBlock: false, b is ObjBlock: false, objA === objB: false
print(testObjBlock(swfBlock, swfBlock)) // a is ObjBlock: true, b is ObjBlock: true, objA === objB: false
print(testObjBlock(objBlock, objBlock)) // a is ObjBlock: true, b is ObjBlock: true, objA === objB: true
print(testAnyBlock(swfBlock, swfBlock)) // a nor b are ObjBlock, they are not equal
print(testAnyBlock(objBlock, objBlock)) // a is ObjBlock: true, b is ObjBlock: true, objA === objB: true
print(testObjBlock(foo.swf, foo.swf)) // a is ObjBlock: true, b is ObjBlock: true, objA === objB: false
print(testSwfBlock(foo.obj, foo.obj)) // a is ObjBlock: false, b is ObjBlock: false, objA === objB: false
print(testAnyBlock(foo.swf, foo.swf)) // a nor b are ObjBlock, they are not equal
print(testAnyBlock(foo.swfBlock, foo.swfBlock)) // a is ObjBlock: true, b is ObjBlock: true, objA === objB: true
The interesting part is how swift freely casts SwfBlock to ObjBlock, yet in reality two casted SwfBlock blocks will always be different values, while ObjBlocks won't. When we cast ObjBlock to SwfBlock, the same thing happens to them, they become two different values. So, in order to preserve the reference, this sort of casting should be avoided.
I'm still comprehending this whole subject, but one thing I left wishing for is ability to use #convention(block) on class / struct methods, so I filed a feature request that needs up-voting or explaining why it's a bad idea. I also get a sense this approach might be bad all together, if so, can anyone explain why?
Well it's been 2 days and nobody has chimed in with a solution, so I'll change my comment to an answer:
As far as I can tell, you can't check equality or identity of functions (like your example) and metaclasses (e.g., MyClass.self):
But – and this is just an idea – I can't help but notice that the where clause in generics appears to be able to check equality of types. So maybe you can leverage that, at least for checking identity?
My solution was to wrap functions to class that extends NSObject
class Function<Type>: NSObject {
let value: (Type) -> Void
init(_ function: #escaping (Type) -> Void) {
value = function
}
}
I know I'm answering this question six years late, but I think it's worth looking at the motivation behind the question. The questioner commented:
Without being able to remove closures from an invocation list by reference, however, we need to create our own wrapper class. That is a drag, and shouldn't be necessary.
So I guess the questioner wants to maintain a callback list, like this:
class CallbackList {
private var callbacks: [() -> ()] = []
func call() {
callbacks.forEach { $0() }
}
func addCallback(_ callback: #escaping () -> ()) {
callbacks.append(callback)
}
func removeCallback(_ callback: #escaping () -> ()) {
callbacks.removeAll(where: { $0 == callback })
}
}
But we can't write removeCallback that way, because == doesn't work for functions. (Neither does ===.)
Here's a different way to manage your callback list. Return a registration object from addCallback, and use the registration object to remove the callback. Here in 2020, we can use the Combine's AnyCancellable as the registration.
The revised API looks like this:
class CallbackList {
private var callbacks: [NSObject: () -> ()] = [:]
func call() {
callbacks.values.forEach { $0() }
}
func addCallback(_ callback: #escaping () -> ()) -> AnyCancellable {
let key = NSObject()
callbacks[key] = callback
return .init { self.callbacks.removeValue(forKey: key) }
}
}
Now, when you add a callback, you don't need to keep it around to pass to removeCallback later. There is no removeCallback method. Instead, you save the AnyCancellable, and call its cancel method to remove the callback. Even better, if you store the AnyCancellable in an instance property, then it will cancel itself automatically when the instance is destroyed.
You can use a callAsFunction method so for example
struct MyType: Equatable {
func callAsFunction() {
print("Image a function")
}
static func == (lhs: MyType, rhs: MyType) -> Bool { true }
}
let a = MyType()
let b = MyType()
a()
b()
let e = a == b
In this case they are always going to be true, you can have initialiser t give them different internal states, or other methods to change there states, and the callAsFunction can be changed to take arguments
Not sure why === would not work on real functions because you are just testing address, but == invokes the == method of the Equatable protocol, and function don't implement this protocol
Related
i want to sort some array whit a specific condition, where if after you compare 3 other condition and they are the same it will check wether the boolean is true or false. if it's true i want it to be sorted first but idk how to do it since boolean is not comparable
here's my array i want to sort
public struct Beef
{
let country:Country
var grade:Character
let condition:Condition
let marbling:Bool
}
public var beefs:[Beef]
{
[
Beef(country: .id, grade: "C", condition: .fresh, marbling: false),
Beef(country: .us, grade: "B", condition: .frozen, marbling: true),
Beef(country: .au, grade: "A", condition: .fresh, marbling: true),
Beef(country: .id, grade: "A", condition: .frozen, marbling: false),
Beef(country: .us, grade: "A", condition: .fresh, marbling: true),
Beef(country: .au, grade: "A", condition: .fresh,marbling: false),
Beef(country: .au, grade: "A", condition: .fresh,marbling: true)
]
}
and this is my sort code
func sortBythree()
{
let sortedBeef = beef.sorted { left, right in
if left.country == right.country
{
if left.grade == right.grade
{
if left.condition == right.condition
{
//what to write? for bool comparison
}
return left.condition > right.condition
}
return left.grade < right.grade
}
return left.country < right.country
}
for beef in sortedBeef
{
print(beef.country,beef.grade,beef.condition,beef.marbling)
}
}
and this is the result
'''
id A frozen false
id C fresh false
us A fresh true
us B frozen true
au A fresh true
au A fresh false
au A fresh true
'''
i want true to be sorted before false but idon't know how
You can do really easily sorting using tuples. It takes much less code and it's harder to make a mistake. And as to Bool, you can convert it to Int, like this:
.sorted { left, right in
return (left.country, left.grade, left.condition, left.marbling.toInt())
< (right.country, right.grade, right.condition, right.marbling.toInt())
}
extension Bool {
func toInt() -> Int {
if self {
return 1
} else {
return 0
}
}
}
Check out more about sorting with tuples here
This is one of two different answers I'm submitting. This one covers how to do this with the the built-in tuple comparison operators, which are probably the preferable approach for most cases.
I would define some helpers that make comparable types from your booleans, like so:
enum OrderedBool { // Empty enum that I'm just using as a namespace
struct TrueIsLess: Comparable {
var value: Bool
init(_ value: Bool) { self.value = value }
static func < (lhs: Self, rhs: Self) -> Bool {
lhs.value && !rhs.value
}
}
struct TrueIsLess: Comparable {
var value: Bool
init(_ value: Bool) { self.value = value }
static func < (lhs: Self, rhs: Self) -> Bool {
!lhs.value && rhs.value
}
}
}
The call site would look like this:
func sortBythree() {
let sortedBeef = beef.sorted { a, b in
return (a.country, a.grade, OrderedBool.TrueIsLess(a.condition))
< (b.country, b.grade, OrderedBool.TrueIsLess(b.condition))
}
for beef in sortedBeef {
print(beef.country, beef.grade, beef.condition, beef.marbling)
}
}
This is one of two different answers I'm submitting. This one covers how to do this with the the a more imperative style, which is more similar to what you have already. This might be necessary if you have a lot of properties you want to compare, or if you have more complicated comparison logic. For most cases though, I'd probably recommend the tuple-based approach.
You have a bit of a pyramid of doom going on. Not only does it add a lot of indentation, and makes it harder to read, but it also separates the equality comparison of a property from the check of its ordering. So I'd fix that first:
func sortBythree() {
let sortedBeef = beef.sorted { left, right in
guard left.country == right.country else { return left.country < right.country }
guard left.grade == right.grade { return left.grade < right.grade }
guard left.condition == right.condition {
//what to write? for bool comparison
}
}
for beef in sortedBeef {
print(beef.country, beef.grade, beef.condition, beef.marbling)
}
}
As you noticed, Bool doesn't conform to Comparable. We could add our own conformance, but I don't think it would be proper. The Swift standard library intentionally omits such a conformance, because there isn't a universally correct understanding of whether true should be "less" or false should be "less". This is similar to how Optional doesn't conform to comparable, even if its Wrapped typed does.
It's possible to sketch out some truth tables and figure out the correct Boolean expression. The correct expression is return left.condition && !right.condition. You might also express it in terms of a bunch of if/else statements instead, but I wouldn't recommend either of those approaches.
The issue is that you have to be really careful to ensure your predicate is correctly implementing the semantics of implementing <, and not <= by accident. It also needs to be clear to readers of your code that this is what you're doing.
Similar to me nilComparator in the question linked above, I would recommend you write yourself something a helper function for comparing bools. This has two main benefits:
It's more readable at the call-site.
It's reusable, so you don't have to reinvent this logic every time you need to compare some bools.
It's testable, so you can be sure you didn't mess it up.
Here's my take on it:
enum BoolComparisonOrdering { case trueIsLess, falseIsLess }
/// Implements `lhs < rhs` for two booleans, with ordering determined by the provided `BoolComparisonOrdering`
func compare(_ lhs: Bool, _ rhs: Bool, _ ordering: BoolComparisonOrdering) -> Bool {
switch ordering {
case .trueIsLess: return lhs && !rhs
case .falseIsLess: return !lhs && rhs
}
}
Here's what the tests for it might look like:
final class BoolComparatorTests: XCTestCase {
let bools = [true, true, false, false]
func testTrueIsFirst() throws {
for _ in 1...1000 {
let input = bools.shuffled()
let result = input.sorted{ a, b in compare(a, b, .trueIsLess)}
XCTAssertEqual(result, [true, true, false, false])
}
}
func testFalseIsFirst() throws {
let bools = [true, true, false, false]
for _ in 1...1000 {
let input = bools.shuffled()
let result = input.sorted { a, b in compare(a, b, .falseIsLess)}
XCTAssertEqual(result, [false, false, true, true])
}
}
}
And here's the usage:
func sortBythree() {
let sortedBeef = beef.sorted { left, right in
guard left.country == right.country else { return left.country < right.country }
guard left.grade == right.grade { return left.grade < right.grade }
guard left.condition == right.condition {
return compare(left.condition, right.condition, .trueIsLess)
}
}
for beef in sortedBeef {
print(beef.country, beef.grade, beef.condition, beef.marbling)
}
}
I recently downloaded the Advanced NSOperations sample app from Apple and found this code...
// Operators to use in the switch statement.
private func ~=(lhs: (String, Int, String?), rhs: (String, Int, String?)) -> Bool {
return lhs.0 ~= rhs.0 && lhs.1 ~= rhs.1 && lhs.2 == rhs.2
}
private func ~=(lhs: (String, OperationErrorCode, String), rhs: (String, Int, String?)) -> Bool {
return lhs.0 ~= rhs.0 && lhs.1.rawValue ~= rhs.1 && lhs.2 == rhs.2
}
It seems to use the ~= operator against Strings and Ints but I've never seen it before.
What is it?
Simply use as a shortcut to "range": you can construct a range and "~=" means "contains".
(other can add more theoretical details, but the sense is this). Read it as "contains"
let n: Int = 100
// verify if n is in a range, say: 10 to 100 (included)
if n>=10 && n<=100 {
print("inside!")
}
// using "patterns"
if 10...100 ~= n {
print("inside! (using patterns)")
}
try with some values of n.
Is used widely for example in HTTP response:
if let response = response as? HTTPURLResponse , 200...299 ~= response.statusCode {
let contentLength : Int64 = response.expectedContentLength
completionHandler(contentLength)
} else {
completionHandler(nil)
It is an operator used for pattern matching in a case statement.
You can take a look here to know how you can use and leverage it providing your own implementation:
http://oleb.net/blog/2015/09/swift-pattern-matching/
http://austinzheng.com/2014/12/17/custom-pattern-matching/
Here is a simple example of defining a custom one and using it:
struct Person {
let name : String
}
// Function that should return true if value matches against pattern
func ~=(pattern: String, value: Person) -> Bool {
return value.name == pattern
}
let p = Person(name: "Alessandro")
switch p {
// This will call our custom ~= implementation, all done through type inference
case "Alessandro":
print("Hey it's me!")
default:
print("Not me")
}
// Output: "Hey it's me!"
if case "Alessandro" = p {
print("It's still me!")
}
// Output: "It's still me!"
You can look into Define Swift
func ~=<I : IntervalType>(pattern: I, value: I.Bound) -> Bool
func ~=<T>(lhs: _OptionalNilComparisonType, rhs: T?) -> Bool
func ~=<T : Equatable>(a: T, b: T) -> Bool
func ~=<I : ForwardIndexType where I : Comparable>(pattern: Range<I>, value: I) -> Bool
I want to compare two objects(of the same Class) and return what is NOT nil.
How do you write something like this in swift? :
func returnWhatIsNotNil(objA: SomeClass, objB: SomeClass) -> SomeClass {
if objA != nil && objB != nil { //error
//both are not nil
return nil
}
if objA == nil && objB != nil { // error
// objA is nil
return objB
}
if objA != nil && objB == nil { // error
// objB is nil
return objA
}
}
with one object,
if let x = objA {
//objA is not nil
}
would do the job, but I quiet don't know how I would do this with TWO objects.
class SomeObject {
}
func returnWhatIsNotNil(objA: SomeObject?, objB: SomeObject?) -> SomeObject? {
if let objA = objA where objB == nil {
return objA
}
if let objB = objB where objA == nil {
return objB
}
return nil
}
edit: sorry, misread your original question. if you want nil when both are non-nil, then here is a one-liner that does it: return objA.map { objB == nil ? $0 : nil } ?? objB. However, #LeoDabus’s version using if…let…where looks more readable to me.
pre-edit assuming you want the first when neither are nil:
You want to use the nil-coalescing operator, ??. So to return an optional from your function, you just need return objA ?? objB. Note, all your input and output types also have to be optional.
Ordinarily you use it to give a default value in case of nil, i.e. "foo".toInt() ?? 0 which unwraps the value if non-nil, or replaces it with the default if its nil.
But if the right-hand side is also an optional, it will return an optional, with the left one if it’s non-nil, else the right one, even if that one is nil.
let i: Int? = nil
let j: Int? = nil
let k: Int? = 42
if let num = i ?? j {
fatalError("won't execute")
}
if let num = j ?? k {
assert(num == 42, "k will be chosen")
}
else {
fatalError("this would run if all 3 were nil")
}
Also bear in mind you can chain ?? too:
let x = i ?? j ?? k ?? 0 // will result in an unwrapped 42
As a follow up to #LeoDabus' accepted answer, you can use a switch statement also:
class SomeObject {
}
func returnWhatIsNotNil(objA: SomeObject?, objB: SomeObject?) -> SomeObject? {
switch (objA, objB) {
case (let a, nil): return a
case (nil, let b): return b
default: return nil
}
}
As mentioned the nil coalescing operator ?? can be used.
Here is an implementation of your function, note you didn't define what would happen when both objA and objB were non-nil
func returnWhatIsNotNil(objA: SomeClass?, objB: SomeClass?) -> SomeClass? {
return objA ?? objB
}
Although, a literal translation of your code in Swift is possible, which is
func returnNotNil(num1: Int?, num2: Int?) -> Int?
{
if let x = num1 {
return x
}
else if let y = num2
{
return y
}
else
{
return nil
}
}
The problem here is, in Swift, we will have to keep the return type as optional - so once returned from the function, you will again have to check for returned value being not nil, and unwrap.
IMHO, a logical translation would be, (assuming that you don't mind returning either, when none of them are nil)
func returnNotNilOrAssert(num1: Int?, num2: Int?) -> Int
{
if let x = num1 {
return x
}
else if let y = num2
{
return y
}
else
{
assert(false, "Both nil")
}
}
Whether or not to assert, is probably an implementation choice that you would have to make. Another way would be, if you're absolutely sure, that one of them would be not nil, that you make the return type of the function "implicitly unwrapped". I know you wanna return nil when both are nil, but then having to check the returned value of this function which is supposed to check two values and return the one which is not nil, IMHO wasn't making much sense, thus I tried it this way.
Lets say I have an Array of String and I want to map it to an Array of Int
I can use the map function:
var arrayOfStrings: Array = ["0", "a"]
let numbersOptional = arrayOfStrings.map { $0.toInt() }
// numbersOptional = "[Optional(0), nil]"
Numbers is now an Array of Int?, but I want an Array of Int.
I know I can do this:
let numbers = arrayOfStrings.map { $0.toInt() }.filter { $0 != nil }.map { $0! }
// numbers = [0]
But that doesn't seem very swift. Converting from the Array of Int? to Array of Int requires calling both filter and map with pretty much boilerplate stuff. Is there a more swift way to do this?
Update: As of Swift 1.2, there's a built-in flatMap method for arrays, but it doesn't accept Optionals, so the helper below is still useful.
I like using a helper flatMap function for that sort of things, just like Scala's flatMap method on collections (which can consider an Scala Option as a collection of either 0 or 1 element, roughly spoken):
func flatMap<C : CollectionType, T>(source: C, transform: (C.Generator.Element) -> T?) -> [T] {
var buffer = [T]()
for elem in source {
if let mappedElem = transform(elem) {
buffer.append(mappedElem)
}
}
return buffer
}
let a = ["0", "a", "42"]
let b0 = map(a, { $0.toInt() }) // [Int?] - [{Some 0}, nil, {Some 42}]
let b1 = flatMap(a, { $0.toInt() }) // [Int] - [0, 42]
This definition of flatMap is rather a special case for Optional of what a more general flatMap should do:
func flatMap<C : CollectionType, T : CollectionType>(source: C, transform: (C.Generator.Element) -> T) -> [T.Generator.Element] {
var buffer = [T.Generator.Element]()
for elem in source {
buffer.extend(transform(elem))
}
return buffer
}
where we'd get
let b2 = flatMap(a, { [$0, $0, $0] }) // [String] - ["0", "0", "0", "a", "a", "a", "42", "42", "42"]
Using reduce to build the new array might be more idiomatic
func filterInt(a: Array<String>) -> Array<Int> {
return a.reduce(Array<Int>()) {
var a = $0
if let x = $1.toInt() {
a.append(x)
}
return a
}
}
Example
filterInt(["0", "a", "42"]) // [0, 42]
What you would really want is a collect (map + filter) method. Given the specific filter you need to apply, in this case even a flatMap would work (see Jean-Philippe's answer). Too bad both methods are not provided by the swift standard library.
update: Xcode 7.2 • Swift 2.1.1
let arrayOfStrings = ["0", "a", "1"]
let numbersOnly = arrayOfStrings.flatMap { Int($0) }
print(numbersOnly) // [0,1]
There’s no good builtin Swift standard library way to do this. However, Haskell has a function, mapMaybe, that does what you’re looking for (assuming you just want to ditch nil values). Here’s an equivalent in Swift:
func mapSome<S: SequenceType, D: ExtensibleCollectionType>
(source: S, transform: (S.Generator.Element)->D.Generator.Element?)
-> D {
var result = D()
for x in source {
if let y = transform(x) {
result.append(y)
}
}
return result
}
// version that defaults to returning an array if unspecified
func mapSome<S: SequenceType, T>
(source: S, transform: (S.Generator.Element)->T?) -> [T] {
return mapSome(source, transform)
}
let s = ["1","2","elephant"]
mapSome(s) { $0.toInt() } // [1,2]
You can consider using reduce, it's more flexible:
var arrayOfStrings: Array = ["0", "a"]
let numbersOptional = arrayOfStrings.reduce([Int]()) { acc, str in
if let i = str.toInt() {
return acc + [i]
}
return acc
}
The book says that "functions and closures are reference types". So, how do you find out if the references are equal? == and === don't work.
func a() { }
let å = a
let b = å === å // Could not find an overload for === that accepts the supplied arguments
Chris Lattner wrote on the developer forums:
This is a feature we intentionally do not want to support. There are
a variety of things that will cause pointer equality of functions (in
the swift type system sense, which includes several kinds of closures)
to fail or change depending on optimization. If "===" were defined on
functions, the compiler would not be allowed to merge identical method
bodies, share thunks, and perform certain capture optimizations in
closures. Further, equality of this sort would be extremely
surprising in some generics contexts, where you can get reabstraction
thunks that adjust the actual signature of a function to the one the
function type expects.
https://devforums.apple.com/message/1035180#1035180
This means that you should not even try to compare closures for equality because optimizations may affect the outcome.
I searched a lot. There seems to be no way of function pointer comparison. The best solution I got is to encapsulate the function or closure in an hashable object. Like:
var handler:Handler = Handler(callback: { (message:String) in
//handler body
}))
Simplest way is designate the block type as #objc_block, and now you can cast it to an AnyObject which is comparable with ===. Example:
typealias Ftype = #convention(block) (s:String) -> ()
let f : Ftype = {
ss in
println(ss)
}
let ff : Ftype = {
sss in
println(sss)
}
let obj1 = unsafeBitCast(f, AnyObject.self)
let obj2 = unsafeBitCast(ff, AnyObject.self)
let obj3 = unsafeBitCast(f, AnyObject.self)
println(obj1 === obj2) // false
println(obj1 === obj3) // true
Update 2021; changed #objc_block to #convention(block) to support Swift 2.x and later (which don't recognize #objc_block).
I've been looking for the answer, too. And I've found it at last.
https://gist.github.com/dankogai/b03319ce427544beb5a4
What you need is the actual function pointer and its context hidden in the function object.
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)
return (ptr.memory, ptr.successor().memory)
}
#infix 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
}
And here is the demo:
// 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 the URLs below to find why and how it works:
https://github.com/rodionovd/SWRoute/wiki/Function-hooking-in-Swift
https://github.com/rodionovd/SWRoute/blob/master/SWRoute/rd_get_func_impl.c
As you see it is capable of checking identity only (the 2nd test yields false). But that should be good enough.
Here is one possible solution (conceptually the same as 'tuncay' answer). The point is to define a class that wraps some functionality (e.g. Command):
Swift:
typealias Callback = (Any...)->Void
class Command {
init(_ fn: #escaping Callback) {
self.fn_ = fn
}
var exec : (_ args: Any...)->Void {
get {
return fn_
}
}
var fn_ :Callback
}
let cmd1 = Command { _ in print("hello")}
let cmd2 = cmd1
let cmd3 = Command { (_ args: Any...) in
print(args.count)
}
cmd1.exec()
cmd2.exec()
cmd3.exec(1, 2, "str")
cmd1 === cmd2 // true
cmd1 === cmd3 // false
Java:
interface Command {
void exec(Object... args);
}
Command cmd1 = new Command() {
public void exec(Object... args) [
// do something
}
}
Command cmd2 = cmd1;
Command cmd3 = new Command() {
public void exec(Object... args) {
// do something else
}
}
cmd1 == cmd2 // true
cmd1 == cmd3 // false
Not a general solution, but if one is trying to implement a listener pattern, I've ended up returning an "id" of the function during the registration so I can use it to unregister later (which is kind of workaround to the original question for "listeners" case as usually unregistering comes down to checking the functions for equality, which is at least not "trivial" as per other answers).
So something like this:
class OfflineManager {
var networkChangedListeners = [String:((Bool) -> Void)]()
func registerOnNetworkAvailabilityChangedListener(_ listener: #escaping ((Bool) -> Void)) -> String{
let listenerId = UUID().uuidString;
networkChangedListeners[listenerId] = listener;
return listenerId;
}
func unregisterOnNetworkAvailabilityChangedListener(_ listenerId: String){
networkChangedListeners.removeValue(forKey: listenerId);
}
}
Now you just need to store the key returned by the "register" function and pass it when unregistering.
This is a great question and while Chris Lattner intentionally doesn't want to support this feature I, like many developers, also can't let go of my feelings coming from other languages where this is a trivial task. There are plenty of unsafeBitCast examples, most of them don't show the full picture, here's a more detailed one:
typealias SwfBlock = () -> ()
typealias ObjBlock = #convention(block) () -> ()
func testSwfBlock(a: SwfBlock, _ b: SwfBlock) -> String {
let objA = unsafeBitCast(a as ObjBlock, AnyObject.self)
let objB = unsafeBitCast(b as ObjBlock, AnyObject.self)
return "a is ObjBlock: \(a is ObjBlock), b is ObjBlock: \(b is ObjBlock), objA === objB: \(objA === objB)"
}
func testObjBlock(a: ObjBlock, _ b: ObjBlock) -> String {
let objA = unsafeBitCast(a, AnyObject.self)
let objB = unsafeBitCast(b, AnyObject.self)
return "a is ObjBlock: \(a is ObjBlock), b is ObjBlock: \(b is ObjBlock), objA === objB: \(objA === objB)"
}
func testAnyBlock(a: Any?, _ b: Any?) -> String {
if !(a is ObjBlock) || !(b is ObjBlock) {
return "a nor b are ObjBlock, they are not equal"
}
let objA = unsafeBitCast(a as! ObjBlock, AnyObject.self)
let objB = unsafeBitCast(b as! ObjBlock, AnyObject.self)
return "a is ObjBlock: \(a is ObjBlock), b is ObjBlock: \(b is ObjBlock), objA === objB: \(objA === objB)"
}
class Foo
{
lazy var swfBlock: ObjBlock = self.swf
func swf() { print("swf") }
#objc func obj() { print("obj") }
}
let swfBlock: SwfBlock = { print("swf") }
let objBlock: ObjBlock = { print("obj") }
let foo: Foo = Foo()
print(testSwfBlock(swfBlock, swfBlock)) // a is ObjBlock: false, b is ObjBlock: false, objA === objB: false
print(testSwfBlock(objBlock, objBlock)) // a is ObjBlock: false, b is ObjBlock: false, objA === objB: false
print(testObjBlock(swfBlock, swfBlock)) // a is ObjBlock: true, b is ObjBlock: true, objA === objB: false
print(testObjBlock(objBlock, objBlock)) // a is ObjBlock: true, b is ObjBlock: true, objA === objB: true
print(testAnyBlock(swfBlock, swfBlock)) // a nor b are ObjBlock, they are not equal
print(testAnyBlock(objBlock, objBlock)) // a is ObjBlock: true, b is ObjBlock: true, objA === objB: true
print(testObjBlock(foo.swf, foo.swf)) // a is ObjBlock: true, b is ObjBlock: true, objA === objB: false
print(testSwfBlock(foo.obj, foo.obj)) // a is ObjBlock: false, b is ObjBlock: false, objA === objB: false
print(testAnyBlock(foo.swf, foo.swf)) // a nor b are ObjBlock, they are not equal
print(testAnyBlock(foo.swfBlock, foo.swfBlock)) // a is ObjBlock: true, b is ObjBlock: true, objA === objB: true
The interesting part is how swift freely casts SwfBlock to ObjBlock, yet in reality two casted SwfBlock blocks will always be different values, while ObjBlocks won't. When we cast ObjBlock to SwfBlock, the same thing happens to them, they become two different values. So, in order to preserve the reference, this sort of casting should be avoided.
I'm still comprehending this whole subject, but one thing I left wishing for is ability to use #convention(block) on class / struct methods, so I filed a feature request that needs up-voting or explaining why it's a bad idea. I also get a sense this approach might be bad all together, if so, can anyone explain why?
Well it's been 2 days and nobody has chimed in with a solution, so I'll change my comment to an answer:
As far as I can tell, you can't check equality or identity of functions (like your example) and metaclasses (e.g., MyClass.self):
But – and this is just an idea – I can't help but notice that the where clause in generics appears to be able to check equality of types. So maybe you can leverage that, at least for checking identity?
My solution was to wrap functions to class that extends NSObject
class Function<Type>: NSObject {
let value: (Type) -> Void
init(_ function: #escaping (Type) -> Void) {
value = function
}
}
I know I'm answering this question six years late, but I think it's worth looking at the motivation behind the question. The questioner commented:
Without being able to remove closures from an invocation list by reference, however, we need to create our own wrapper class. That is a drag, and shouldn't be necessary.
So I guess the questioner wants to maintain a callback list, like this:
class CallbackList {
private var callbacks: [() -> ()] = []
func call() {
callbacks.forEach { $0() }
}
func addCallback(_ callback: #escaping () -> ()) {
callbacks.append(callback)
}
func removeCallback(_ callback: #escaping () -> ()) {
callbacks.removeAll(where: { $0 == callback })
}
}
But we can't write removeCallback that way, because == doesn't work for functions. (Neither does ===.)
Here's a different way to manage your callback list. Return a registration object from addCallback, and use the registration object to remove the callback. Here in 2020, we can use the Combine's AnyCancellable as the registration.
The revised API looks like this:
class CallbackList {
private var callbacks: [NSObject: () -> ()] = [:]
func call() {
callbacks.values.forEach { $0() }
}
func addCallback(_ callback: #escaping () -> ()) -> AnyCancellable {
let key = NSObject()
callbacks[key] = callback
return .init { self.callbacks.removeValue(forKey: key) }
}
}
Now, when you add a callback, you don't need to keep it around to pass to removeCallback later. There is no removeCallback method. Instead, you save the AnyCancellable, and call its cancel method to remove the callback. Even better, if you store the AnyCancellable in an instance property, then it will cancel itself automatically when the instance is destroyed.
You can use a callAsFunction method so for example
struct MyType: Equatable {
func callAsFunction() {
print("Image a function")
}
static func == (lhs: MyType, rhs: MyType) -> Bool { true }
}
let a = MyType()
let b = MyType()
a()
b()
let e = a == b
In this case they are always going to be true, you can have initialiser t give them different internal states, or other methods to change there states, and the callAsFunction can be changed to take arguments
Not sure why === would not work on real functions because you are just testing address, but == invokes the == method of the Equatable protocol, and function don't implement this protocol