Currying in Swift, New Declaration Syntax in Future

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



Leave a reply



Submit