currying in Swift, new declaration syntax in future?
only the declaration syntax will be removed e.g. func(a: Int)(b:Int) -> Int
func curry(a: Int)(b: Int) -> Int {
return a + b
}
is equivalent to:
func newCurry(a: Int) -> (b: Int) -> Int {
return { b in
return a + b
}
}
Cannot translate Swift 2.2 currying to future Swift format
The inner curly braces are wrong, it should be:
func handleDownload2(iCount:Int) -> (NSData?, NSError?) -> Void {
return { (data: NSData?, error: NSError?) -> Void in
// received image
print(iCount)
print(data!.length)
}
}
How to fix this curried function in Swift?
Ignore the Xcode 7.3 warning about the second version. If you clean out the build folder, the warning will probably go away. More important, the second version does work — it compiles in Swift 3, which is all that matters.
Pass additional parameters to completion handler without curried function?
Currying isn't being removed – it's just the convenience syntax for defining a curried function that's being removed. Now you have to define a curried function as explicitly returning another function (a single parameter list).
For example in your case, you'll want something like this:
func parseSessionCompletion(profileName: String, pageNumber: Int) -> (data: NSData?, response: NSURLResponse?, error: NSError?) -> () {
// do something
return {data, response, error in
// do something else
}
}
Take a look at the proposal for the removal of the currying syntax for more info about the change.
What is this syntax: func funcName(stuff1)(stuff2)-returnType {}
That's a curried function -- it decomposes a function of several parameters into a chain of several functions of one parameter each. You can read about them in the Language Reference portion of the book: go to Function declaration and scroll down a bit.
It's equivalent to:
func funcName(a: TypeOfA) -> (b: TypeOfB -> returnType) {
func curryFunc(b: TypeOfB) -> returnType {
return somethingOfreturnType
}
return curryFunc
}
It's also good with sausages.
Why is this showing 'Expected 'func' keyword in instance method declaration'
In an normal project, this is not valid:
class NormalSpace {
var name = ""
var value = 0
var rent = 0
var owned = false
}
var newRoad = NormalSpace()
newRoad.name = "New Road"
newRoad.value = 600
newRoad.rent = 25
newRoad.owned = false
You can do that in a playground (where it just runs this code directly), but in an app, code (such as the setting of the properties) belongs in a function or initializer.
That initialization code needs to be placed within some context. Let us imagine that it is inside a struct
. But this still is not valid:
class NormalSpace {
var name = ""
var value = 0
var rent = 0
var owned = false
}
struct Foo {
var newRoad = NormalSpace()
newRoad.name = "New Road"
newRoad.value = 600
newRoad.rent = 25
newRoad.owned = false
}
The property, newRoad
is fine, but the values are not. You need to wrap it inside a func
(hence the error) or an init
. E.g., this initializes newRoad
during the init
of the struct
:
struct Foo {
let newRoad: NormalSpace
init() {
newRoad = NormalSpace()
newRoad.name = "New Road"
newRoad.value = 600
newRoad.rent = 25
newRoad.owned = false
}
}
Or you might initialize it in a func
:
struct Foo {
var newRoad: NormalSpace?
mutating func bar() {
let road = NormalSpace()
road.name = "New Road"
road.value = 600
road.rent = 25
road.owned = false
newRoad = road
}
}
Or, alternatively, you can initialize this property with a closure (note the extra ()
at the end):
struct Foo {
let newRoad: NormalSpace = {
let road = NormalSpace()
road.name = "New Road"
road.value = 600
road.rent = 25
road.owned = false
return road
}()
}
But the code where you initialize the properties must be placed within some context, so that the compiler knows when those lines of code should be run.
Note, we would generally give NormalSpace
a “memberwise initializer”, e.g.:
class NormalSpace {
let name: String
let value: Int
let rent: Int
let owned: Bool
init(name: String, value: Int, rent: Int, owned: Bool) {
self.name = name
self.value = value
self.rent = rent
self.owned = owned
}
}
Or, if a struct
(and we would generally prefer to make our model objects struct
value-types rather than class
reference-types), this memberwise initializer would be created for you:
struct NormalSpace {
let name: String
let value: Int
let rent: Int
let owned: Bool
}
Either way, you can then provide all the desired values during initialization, e.g.:
struct Foo {
let newRoad = NormalSpace(name: "New Road", value: 600, rent: 25, owned: false)
}
Note, that I've removed the “default” values because those really are not appropriate. If you wanted to say that they do not need to be provided, then you would make them “optionals”. But there is generally a big difference between, say, a rent of zero (i.e. it is my grandmother’s house and she's not charging me) and that no rent has been specified. In Swift, we generally avoid using “sentinel” values like ""
or 0
for “no value provided”.
Also, now that we have a memberwise initializer, I have also made the properties immutable (let
rather than var
). If you need to make them mutable (e.g. to let someone change the rent later), fine, revert back to var
. But only make properties mutable if you really need to change them later on.
Is there a way to reference instance function when calling SequenceType.forEach?
There are two different problems here. The trailing closure syntax
can be used when calling a function and the last parameter is a closure,
so
let b1 = someFoos.contains({ $0.isBaz })
let b2 = someFoos.contains { $0.isBaz }
are fully equivalent. However, the trailing closure syntax can be problematic in the condition of an if-statement:
if someFoos.contains({ $0.isBaz }) { } // OK
if someFoos.contains { $0.isBaz } { } // Compiler error
if (someFoos.contains { $0.isBaz }) { } // OK, as noted by R Menke
We can only speculate why the second one does not work. It could be that the compiler
takes the first {
as the start of the if-body. Perhaps this will
change in a future version of Swift but probably it is not worth
the effort.
The other problem is about curried functions.
someFoos.forEach(bar2)
compiles because bar2
has the type Foo -> Void
, and that is exactly
what the forEach()
method expects. Foo.bar
, on the other hand,
is a curried function (see http://oleb.net/blog/2014/07/swift-instance-methods-curried-functions/) which takes the instance as the first
argument. It has the type Foo -> () -> ()
. So
Foo.bar(someFoo)
is a closure with type () -> ()
, and
Foo.bar(someFoo)()
calls the bar
method on the someFoo
instance.
(Note: The following is not meant as an actual recommendation,
but only as a demonstration about curried functions and fun
with closures!)
To pass Foo.bar
directly as an argument to forEach()
we need to
"swap" the order of the parameters. Haskell has a "flip" function for that purpose,
and it is also possible in Swift (see e.g. How to write a flip method in Swift?):
func flip<A, B, C>(f: A -> B ->C) -> B -> A ->C {
return { b in { a in f(a)(b) } }
}
Then flip(Foo.bar)
has the type () -> Foo -> ()
, so
the void argument of the bar
method can be applied
flip(Foo.bar)()
to get a Foo -> ()
closure, and
flip(Foo.bar)()(someFoo)
calls the bar
method on the someFoo
instance.
And now we can call
someFoos.forEach (flip(Foo.bar)())
without using a closure expression { .. }
!!
If isBaz
were a method instead of a property
func isBaz() -> Bool { return false }
then you
could do the same in the if-expression:
if someFoos.contains(flip(Foo.isBaz)()) {
// ...
}
Again, this is only meant as a demonstration. Also properties
are not curried functions, so this cannot be done with
your isBaz
property.
Expected declaration on switch declaration
You can't write switch rank {
inside the struct directly , it should be inside a function init
or any other custom one
public struct beltRank {
var rank = 0
var belt = ""
init(rank:Int) {
// write switch here
}
}
Related Topics
Saving a Codable Struct to Userdefaults with Swift
Why Are Uiscreen.Bounds Incorrect in iOS11
Dyld: Library Not Loaded: @Rpath/Libswiftdispatch.Dylib
How to Change Its Own Button Image on Tap in Swift
Swift: Specialize Method of Generic Class for Function Types
Menu Items Disabled in MACos Menubar App
Avaudiosinknode with Non-Default, But Still Device-Native Sample Rates
How to Create Apple Watchos5 Complication
Check If a Func Exists in Swift
Corebluetooth on MAC Command Line Application
Reading Data from Excel Document in a Swift App
Swift Cannot Assign to Self in a Class Init Method
How to Edit Swift Error Breakpoint
Swift Tdd & Async Urlsession - How to Test
How to Make a Segue to Second Item of Tab Bar
Adding Index List and Section Headers to Translated Tableview
Iwatch: Wkinterfacelabel How to Stop Text from Being Cut Off with "..." at The End of a Label