Swift 2.0b4: Curried initializer syntax

Originator:rix.rob
Number:rdar://22108354 Date Originated:02-Aug-2015 04:07 PM
Status:Open Resolved:
Product:Developer Tools Product Version:Xcode-beta (7A165t)
Classification:Enhancement Reproducible:Always
 
Summary:
Functions have a curried syntax allowing convenient definition of functions returning functions:

func add(x: Int)(_ y: Int) -> Int {
	return x + y
}

The same syntax would be useful for defining initializers:

struct Add {
	init(_ x: Int)(_ y: Int) {
		self.x = x
		self.y = y
	}
	let x: Int
	let y: Int
}

The above initializer would be equivalent to a static function:

struct Add {
	static func init_(x: Int)(_ y: Int) -> Add {
		return Add(x: x, y: y)
	}
	let x: Int
	let y: Int
}

For example it can be partially applied, returning a function which initializes new instances of the type:

let incremented = [0, 1, 2, 3, 4].map(Add(1)) // equivalently: .map(Add.init(1))

This would also allow failable initialization in the usual way:

struct Pair<A, B> {
	init?(x: A?)(y: B?) {
		guard let x = x else { return nil }
		guard let y = y else { return nil }
		left = x
		right = y
	}
	let left: A
	let right: B
}

This would yield an initializer of type A? -> B? -> Pair<A, B>?, i.e. the semantics are again identical to a curried static function defined over an uncurried (failable) initializer:

struct Pair<A, B> {
	static func init_(x: A?)(y: B?) -> Pair {
		return Pair(x: x, y: y)
	}

	init?(x: A?, y: B?) {
		guard let x = x else { return nil }
		guard let y = y else { return nil }
		left = x
		right = y
	}
	let left: A
	let right: B
}

This syntax would enable more idiomatic curried construction of Swift types than is currently possible. For example, my motivating case is the family of `loc` functions defined here:

https://github.com/antitypical/Manifold/blob/289e8444349c9d3bf7d02cefde7db08966134f69/Manifold/Location.swift#L46-L79

Taking the first function as an example, we could define it in extant Swift 2 syntax as a failable initializer, something like so (🚨 untested 🚨):

init?(_ weave: (A -> Location?) -> A -> Location?, _ up: A -> Location?, _ a: A) {
	func into(t1: A) -> Location? {
		return Location(it: t1, down: weave(into), up: up, left: const(nil), right: const(nil))
	}
	self = into(a)
}

However, in doing so we would lose the ability to partially apply it, which is depended upon elsewhere in the codebase.


Steps to Reproduce:
N/A

Expected Results:
N/A

Actual Results:
N/A

Regression:
N/A

Notes:
N/A

Comments


Please note: Reports posted here will not necessarily be seen by Apple. All problems should be submitted at bugreport.apple.com before they are posted here. Please only post information for Radars that you have filed yourself, and please do not include Apple confidential information in your posts. Thank you!