<div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote">On Wed, Feb 10, 2016 at 1:21 PM, Brent Royal-Gordon via swift-evolution <span dir="ltr"><<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">So, since SE-0029 has been accepted, let's think about explicit replacements. So far, I've been able to think of three general approaches. For the examples below, I'll assume there's a `func concatenate(number: Int, to string: String) -> String`, which does the obvious thing. Where supported, I will fully qualify names with SE-0021 syntax, but in some cases this might not be necessary.<br>
<br>
1. Special parameter label.<br>
<br>
`concatenate` is implicitly overloaded with a `func concatenate(parameters: (Int, String)) -> String`.<br>
<br>
concatenate(parameters: tuple)<br>
tuples.map(concatenate(parameters:))<br>
<br>
Advantages:<br>
- Does not require any new call-side syntax.<br>
- Googleable thanks to use of identifiers.<br>
<br>
Disadvantages:<br>
- Could conflict with functions that use `parameters` as an argument label.<br>
- Not clear how it would distinguish between `concatenate(_:to:)` and e.g. `concatenate(_:with:)`.<br>
- Might reintroduce type checking complexity, since it's adding overloads.<br>
- A bit wordy.<br>
- As far as I know, not precedented in other languages.<br>
<br>
2. Method on functions.<br>
<br>
`concatenate` has a method on it called, say, `apply(to:)` which takes a tuple of parameters.<br>
<br>
concatenate(_:to:).apply(to: tuple)<br>
tuples.map(concatenate(_:to:).apply(to:))<br>
<br>
Advantages:<br>
- You can be sure of the variant you're selecting.<br>
- Googleable thanks to use of identifiers.<br>
- Similar to usage in Javascript.<br>
<br>
Disadvantages:<br>
- Rather wordy, with lots of chaining and extra parentheses.<br>
- Methods on unapplied functions might be a little confusing.<br>
<br>
3. Splat operator.<br>
<br>
An operator like `*` is used to indicate splatting. A tuple can be put to the right of the operator to splat it in immediately, or it can be omitted to select a splattable version of the function.<br>
<br>
concatenate(_:to: *tuple)<br>
tuples.map(concatenate(_:to: *))<br>
<br>
Advantages:<br>
- You can be sure of the variant you're selecting.<br>
- Similar to usage in Ruby and Perl 6.<br>
- Fairly short in all forms.<br>
<br>
Disadvantages:<br>
- Not Googleable.<br>
- New magic syntax.<br>
- Two slightly different forms depending on whether you're calling or not.<br>
<br>
Any thoughts on these, or alternative approaches (as opposed to small syntax tweaks)?<br>
<br>
<br>
<br>
P.S. As for pointers potentially using prefix `*` for memory dereferencing, I would instead make them use postfix `!`. `!` could become an `unwrapped` pseudo-property that any type can use, democratizing another piece of `Optional` magic and working around the vexing problem of what you name the `Pointer` property for "that thing you're actually pointing to".<br>
<span class="HOEnZb"><font color="#888888"><br></font></span></blockquote><div><br></div><div>I'm curious what the type signature of the splat operator would be? IIUC, one of the primary reasons the Swift core team accepted SE-0029 (remove implicit tuple splat) is because it adds a lot of complexity to the typechecker. That was my experience too, having implemented a hobby language several years ago where every function took a single tuple argument. It made it very difficult to reason about the types in the program, because a function type held no intrinsic type information, and the only way to typecheck it was to know how the function was defined and see whether that was compatible with how it was invoked. That, in turn, made first-class functions and separate module compilation very difficult: you had to carry around full information about the arity of the tuple, each of its types, whether the types were generic type variables, whether they had typeclass (protocol in Swift) constraints, whether the typeclasses themselves had associated types, etc. And then when you try to *infer* types, each of these become cases in the inference engine, and interacted combinatorially.</div><div><br></div><div>I'd start by trying to write down the type of the splat operator. Can it be expressed within the normal Swift type system? I'm not sure...I'm not familiar enough with the intricacies of Swift tuple types to know.</div><div><br></div><div>If it can't, I have a strong preference against the options (#1 & #2) that look like normal function call syntax. Because you won't be able to do several things that you're accustomed to with functions: assign them to variables, store them in containers, pass them as parameters to other functions.</div><div><br></div><div>This is less of a problem with explicit language syntax, because you could have a rule in the typechecker that says "If the expression being splatted is a tuple of type (A, B, x: C), then it must be applied to a function of type (A, B, C) -> Ret, with the result type of the call being Ret." I think you can also get around many of the type inference pitfalls as well, because in most cases the types of the function and tuple are unlikely to need inferring (occasionally this will require explicit type annotations on tuple components, but it seems like most of the time they will have already been inferred when the tuple was declared). And it's much easier to do "partial splat" operations, where, for example, you may want to pass the first couple arguments of a function explicitly but splat the rest.</div><div><br></div><div>Note that there's a loss of expressiveness through *not* making the splat operator first-class; a number of interesting Haskell combinators come out of using $ (the function-application operator) as a function that can itself be passed around. But it's also a question of how much complexity you want to add to the language for the sake of conceptual purity. Python, Ruby, and Javascript all seem to get along fine with just the ability to splat lists & dictionaries into the final position of an argument list.</div></div></div></div>