'Cannot create a variadic tuple' error - swift

Here's a function from the Dollar framework for Swift:
public class func bind<T, E>(function: (T...) -> E, _ parameters: T...) -> (() -> E) {
return { () -> E in
typealias TType = (T...)
return function(unsafeBitCast(parameters, TType.self))
}
}
In the line with the typealias I get the Cannot create a variadic tuple error. When I remove the braces around T... then I receive the Consecutive statements on a line must be separated by ';' error. So, this is not a solution.
Does anyone know a workaround to get the error away?
This happens since XCode 6 Beta 6, which was (really) released today.

This is fixed in the Dollar project now. But for someone who encounters this issue in another project the way to solve it is by doing a unsafeBitCast on the function itself as such which will resolve the compile issue.
typealias Function = [T] -> E
let f = unsafeBitCast(function, Function.self)
f(params)

Related

compactMap() closure fails when adding irrelevant NOP declaration?

Playground
XCode Version 13.3 (13E113)
Swift 5.6
First print of compactMap() closure displays this:
["What\'s", "Going", "On?"]
The second print displays this:
[(), (), ()]
Seems like if I declare anything inside the closure, the output of the closure changes.
print( "What's\nGoing\nOn?".split(separator:"\n").enumerated().compactMap
{ idx, lineText in
lineText
})
print( "What's\nGoing\nOn?".split(separator:"\n").enumerated().compactMap
{ idx, lineText in
let _ : String
lineText
})
Is there a way to wrap some of it to hide the other declaration?
Is the closure confused about the type?
Is there any way to unconfuse it (or me)?
Is it a Swift bug?
Issue is root of why other things I'm trying to with this pattern aren't working.
UPDATE
As per #Shadowrun's answer below, I added a return statement in the 3rd example, but that leads to compile time errors. So is that resolvable?
print( "What's\nGoing\nOn?".split(separator:"\n").enumerated().compactMap
{ idx, lineText in
let _ : String
return lineText
})
expression failed to parse:
error: test playground.playground:38:52: error: generic parameter 'ElementOfResult' could not be inferred
print( "What's\nGoing\nOn?".split(separator:"\n").enumerated().compactMap
^
Swift.Sequence:2:28: note: in call to function 'compactMap'
#inlinable public func compactMap<ElementOfResult>(_ transform: (Self.Element) throws -> ElementOfResult?) rethrows -> [ElementOfResult]</b>
If you have a one line closure there's an implicit return, so the first one is returning lineText which is of type string. See "Functions With an Implicit Return" at https://docs.swift.org/swift-book/LanguageGuide/Functions.html
The second one doesn't actually return anything, once it is more than one line, there is no implicit return. So the return type is Void which is also spelled as the empty tuple, () and that's what you get there.
You need to say return lineText explicitly if you mean to return something.
This function:
{ idx, lineText in
let _ : String
lineText // This line evaluates the value of lineText and does nothing with the result
}
does not return a value. Any function that doesn't return a value returns a Void value. Void is a type with only one possible value, called (). Mapping to void is a pointless thing to do. Even if your function did a side effect, like printing something, it wouldn't be good style to use map just for side effects.
You can guard against this kind of mistake by being more explicit about the return type in the closure
{ idx, lineText -> String in ... }

swift 5.1 evaluate a closure in the wrong way

I'm having an issue with evaluation of one line of code
if i break it down to two lines, it's working , but in one line of code, it's just evaluate in a 'new' to a 'wrong' way.
my main reason for asking this question, is not to solve it, I know I can use parenthesis to solve it, and break it to Two line, but don't want to solve it, I just want to know why its evaluated like this , and if there's a solution for this : some setting to patch , in Order THAT it will work in ONE LINE OF CODE :
Heres the code that working in Two lines
Heres the code that trying to do the same thing, but rise an error as you can see:
full code of both working and not working :
class ClosuresStack {
var dic = Dictionary<String,(()->String)->String >()
subscript(_ str:String)-> (()->String)->String {
get {
return dic[str]!
}
set {
dic[str] = newValue
}
}
}
func createClosuresStak() -> ClosuresStack {
let cs = ClosuresStack()
func takesAClosureReturnA_string(_ closure:()->String) ->String {
return closure() + " Two"
}
cs["C"] = takesAClosureReturnA_string
return cs
}
let c = createClosuresStak()["C"]
let str = c{"One"}
print(str) // print: One Two
let c = createClosuresStak()["C"]{"One"} // error -->
now, I want to somehow understand how to change it that it will work in ONE LINE OF CODE : meaning that the evaluation of 'createClosuresStak()["C"]{"One"}' will create a closure after ["C"] , and then from that point writing the {"One"}
will make it a full evaluate of the line :
let c = createClosuresStak()["C"]{"One"}
making 'c' a String
if that's not possible, I need to know it Too , tnx :)
UPDATE
tnx for the comments , its help me understand the problem more clearly :
1) im understanding that the createClosuresStak()["C"]{"One"}
acutely trying to add the string 'One' as another parameter to the sub script , and there for the error from the compiler was that is cannot subscript (String,()->String} , 'C' as the string inside the [] , and the other parameter {"One"} -> BUT , isn't that some kind of a bug?, been that i'm using [] ,Cleary the compiler need to 'understand' that I want to subscript a String, also by power of inferring that swift has,
2) now I'm still trying to get that syntax to work as it is so I try to change some things, in order to get it to work :
so I created a function that take a string, and return a dictionary of type : Dictionary<String,()->String>, and then trying so subscript it
and the compiler don't rise an error that way :
func closuresDictionary(_ s:String) -> Dictionary<String,()->String> {
var dic = Dictionary<String,()->String>()
func foo()->String {
return s + " Two"
}
dic["C"] = foo
return dic
}
let c = closuresDictionary("One")["C"]{ "SomeString" }
c is now a closure of type ()->String which does noting with string that I put inside, so the syntax works, but the outcome is not doing anything.
when im changing the return type of the dictionary to a different closure : (String)->String instead of ()->String , im getting the same old error, that I'm trying to subscript a (String,(String)->String)
and I need a function that will take the string inside the {} , and create something from it meaning that I need to subscript to return a closure of (String)->String
its seems like there's no way to do that
im adding two more pictures of my last trying in order to get this line of code in current syntax to work
the wanted syntax working but the outcome is not an outcome not doing any thing with the string inside the {}:
same error, by changing the function to (String)->String
Your example:
let c = createClosuresStak()["C"]{"One"}
is using trailing closure syntax.
Trailing closure syntax works by including the trailing closure as an additional parameter to a function call. Subscripting an array is really a function call under the hood (to a function called subscript), and Swift is trying to pass that closure as a second parameter to the subscripting call, which is what the error is explaining:
Cannot subscript a value of type 'ClosuresStack' with an argument of type '(String, () -> String)'.
In other words, you can't pass both "C" and the closure {"One"} to the subscripting function.
There are at least 3 ways to fix this and still put it on one line:
Option 1: Use an explicit call to pass the closure instead of using trailing closure syntax
Wrap the closure in () to make the call explicit:
let c1 = createClosuresStak()["C"]({"One"})
print(c1)
Option 2: Wrap the createClosureStak()["C"] in parentheses
That lets Swift know the subscripting only gets "C" as a parameter and allows trailing closure syntax to work as expected:
let c2 = (createClosuresStak()["C"]){"One"}
print(c2)
Option 3: Add .self to the result before the trailing closure syntax:
That again finishes the subscripting call and avoids the confusion.
let c3 = createClosuresStak()["C"].self {"One"}
print(c3)
Personally, I would choose option one, because trailing closure syntax is unnecessary syntactic sugar that clearly is not working here.

Swift - Ambiguous reference to member '==' error

I've done some searching and can't seem to find a solution for my below issue. I'm fairly new to swift so working through some issues. I have the below function which is just a stub containing the signature of the function and a return value just to get it to compile.
The test code is what I've been given, I did not write this and unfortunately cannot alter it.
My issues is that when I run it, it says that the test that calls this function has an "Ambiguous call to member '=='". I cannot alter the test code. Whatever the issue is must be in my function signature i'm assuming but could use some help.
Function That I am writing (That I assume contains the issue):
func contains(target: StringOrInt, compare: Character ) -> Bool {
return false
} // contains
Test that calls the function (I'm not allowed to edit this and did not write it):
func test_contains_cons_2_strings_3() {
let list1 = MyList.cons("foo", MyList.cons("bar", MyList.empty))
assertEquals(testName: "test_contains_cons_2_strings_3",
expected: true,
received: list1.contains(target: "bar", compare: ==))//Error is on this line '=='
} // test_contains_cons_2_strings_3
Error:
main.swift:807:67: error: ambiguous reference to member '=='
received: list1.contains(target: "foo", compare: ==))
Also note that "StringOrInt" is a protocol that I've defined that acts as an extension on both Int and String. This is done because the test code (Which i did not write and cannot edit) passes both strings and ints to this same variable and function.
Thanks advance for any help, I really appreciate it!
I think you want to compare two strings by passing "==" operator and return a Boolean value.If so you can use the below method,
func myList(_ compare:((String, String) -> Bool)) -> Bool {
return compare("foo","bar")
}
myList(==)
I was able to figure this out using the below. I implemented an enum of generic type and the nan extension on that enum. I then used this generic type within the contains function to represent multiple types instead of StringOrInt. Thanks everyone for the comments and the help.
enum implemented:
indirect enum my_list<A> {
case cons(A, my_list<A>)
case empty
}
I then implemented in extension for this enum "extension my_list" and placed the contains function within the extension.
contains function signature/stub:
func contains(target: A, compare:((A, A) -> Bool))
-> Bool {
return true
}// contains

Error testing a method that throws an Error in Quick with Nimble

I'm having a problem getting a Nimble matcher correct in testing a method that throws an exception. According to the docs it should be simple. I just need an expectation like this
expect( try somethingThatThrows() ).toNot( throwError() )
However with Swift 3 and Xcode 8.2 I'm getting a compiler editor. Here's the context.
describe("Using RealmDatasource") {
let datastore = RealmDatasource() as Datasource
it("can retrieve an object") {
expect( try datastore.getCurrentObject() ).to( throwError() )
}
}
I get the following error on the 'it' declaration line
Invalid conversion from throwing function of type '() -> () throws to non-throwing function of type '() -> ()'
try using expect with curly brackets { }
expect { try datastore.getCurrentObject() }.to( throwError() )
should be working

readWithCallback function not working in swift 3

Before the swift update(in swift 2) my code was like the following and it worked successfully with no errors.
client.me.events.readWithCallback({
(list: Array<AnyObject>!, error: MSOrcError!) -> Void in
}
But after the swift update (in Swift 3) I get errors in the previous code, so I changed it to the below code. It has no errors but when I run the app it gets crashes and terminates. When I remove the last line I get an error saying:
Cannot convert value of type 'Any?' to expected argument type
'(([Any]?, MSOrcError?) -> Void)!'
client.me.events.read(callback: Any?{
(list: Array<AnyObject>!, error: MSOrcError!) -> Void in
} as! (([Any]?, MSOrcError?) -> Void)! )
How do I solve this error?
The error message says that the expected argument type is (([Any]?, MSOrcError?) -> Void)!. Why don't you follow it?
client.me.events.read(callback: {(list: [Any]?, error: MSOrcError?) in
//...
})
Or simply:
client.me.events.read {list, error in
//...
}