[swift-evolution] [Proposal] Automating Partial Application via Wildcards

Austin Zheng austinzheng at gmail.com
Tue Feb 2 13:12:24 CST 2016


Hmm...the rationale that Joe provided makes a lot of sense.

One question - is the explicit closure syntax amenable to multiple levels of currying? In particular, what are the scoping rules for the placeholders $n - are they limited to the immediate closure within which they appear, or can they be used within further-nested closures?

Best,
Austin

> On Feb 2, 2016, at 11:01 AM, Douglas Gregor via swift-evolution <swift-evolution at swift.org> wrote:
> 
> 
>> On Feb 2, 2016, at 9:33 AM, Erica Sadun via swift-evolution <swift-evolution at swift.org <mailto:swift-evolution at swift.org>> wrote:
>> 
>> First draft. Let's go Scala!
>> 
>> -- E
>> 
>> Automating Partial Application via Wildcards
>> 
>> Proposal: TBD
>> Author(s): Erica Sadun <http://github.com/erica>, Davide De Franceschi <http://github.com/DeFrenZ>
>> Status: TBD
>> Review manager: TBD
>>  <https://gist.github.com/erica/6327981d42eb9be6b4d2#introduction>Introduction
>> 
>> SE-0002 <https://github.com/apple/swift-evolution/blob/master/proposals/0002-remove-currying.md> has been accepted for Swift 3.0. That proposal removes currying func declaration syntax from Swift. It reasons that currying introduces unnecessary language and implementation complexity and is easily replaced with chained function return types. 
>> 
>> Because of SE-0002, this curried example:
>> 
>> public func projectFunctionToCoordinateSystem(function f: FunctionType)(p0: CGPoint, p1: CGPoint)(x: CGFloat) -> CGPoint
>> becomes
>> 
>> public func projectFunctionToCoordinateSystem(function f: FunctionType) -> (p0: CGPoint, p1: CGPoint) -> (x: CGFloat) -> CGPoint 
>> in Swift 3.
>> 
>> It's mechanically simple to re-introduce partial application but the current solution adds unnecessary nesting and complicated closure declarations, as you see in the following Swift 3 version of this projection function.
>> 
>> public func projectFunctionToCoordinateSystem(function f: FunctionType) -> (p0: CGPoint, p1: CGPoint) -> (x: CGFloat) -> CGPoint {
>>   return { p0, p1 in
>>     return { x in
>>       let (dx, dy) = (p1.x - p0.x, p1.y - p0.y)
>>       let (magnitude, theta) = (hypot(dy, dx), atan2(dy, dx)) // Thanks loooop
>>       var outPoint = CGPoint(x: x * magnitude, y: f(x) * magnitude)
>>       outPoint = CGPointApplyAffineTransform(outPoint, CGAffineTransformMakeRotation(theta))
>>       outPoint = CGPointApplyAffineTransform(outPoint, CGAffineTransformMakeTranslation(p0.x, p0.y))
>>       return CGPoint(x: outPoint.x, y: outPoint.y)
>>     }
>>   }
>> }
>> SE-0002 mentions the possibility of introducing Scala-style free-form partial implementation as a future step. This proposal requests that a Scala-style wildcard feature be adopted into Swift by introducing a form of automatic partial application.
>> 
>>  <https://gist.github.com/erica/6327981d42eb9be6b4d2#detail-design>Detail Design
>> 
>> The proposed design replaces a Swift 3 curried signature like this: 
>> 
>> public func projectFunctionToCoordinateSystem(function f: FunctionType) -> (p0: CGPoint, p1: CGPoint) -> (x: CGFloat) -> CGPoint
>> with a non-curried, fully qualified call like this:
>> 
>> public func projectFunctionToCoordinateSystem(function f: FunctionType, p0: CGPoint, p1: CGPoint, x: CGFloat) -> CGPoint
>> When called with wildcard tokens, the function is partially applied using the supplied arguments. For example:
>> 
>> let partial1 = projectFunctionToCoordinateSystem(function: mySinFunction, p0: p0, p1: p1, x: _)
>> // partial1(x: xValue)
>> 
>> let partial2 = projectFunctionToCoordinateSystem(function: mySinFunction, p0: .zero, p1: _, x: _)
>> // partial2(p1: p1Value, x: xValue) 
>> // or
>> // let partial3 = partial2(p1: p1Value, x: _); partial3(x: 0.25)
> In the SE-0021 acceptance rationale at 
> 
> 	http://article.gmane.org/gmane.comp.lang.swift.evolution/3961/match=accepted+0021 <http://article.gmane.org/gmane.comp.lang.swift.evolution/3961/match=accepted+0021>
> 
> Joe Groff sayeth:
> 
> A number of contributors proposed an alternative syntax, using a placeholder in the argument value position:
> 
> let x = Foo.bar(_, bas: _)
> 
> with the idea that this could potentially generalize to partial application syntax. We don't think this is a good direction for Swift for a couple of reasons. Swift already has fairly compact syntax for forming closures over partially applied functions, { Foo.bar($0, bas: $1) }. It may not be everyone's aesthetic cup of tea, but this notation has several important advantages. The braces unambiguously delineate the boundaries of the closure, which is a subtle problem with Scala-like approaches. The braces also provide a visual cue that capture is occurring. The $n placeholders are also more general since they allow for reordering of arguments. '_' in particular is also a poor choice of placeholder, since in other contexts where it's used, it's meant as a "black hole" for value binding in patterns rather than as a placeholder for a meaningful bound value.
> 
> 
> 	- Doug
> 
> 
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20160202/05effbab/attachment.html>


More information about the swift-evolution mailing list