It may make things more terrible. The solution introduces two separated type system and one is Swift 3 mode for asterisk syntax.
> Robert Bennett via swift-evolution <swift-evolution@swift.org> 於 2017年6月10日 > 上午6:02 寫道: > > I see. My ideal solution to this would be an explicit tuple packing and > unpacking API, as opposed to implicitly flexible functions. Something akin to > (borrowing Python’s asterisk syntax): > > func compose<T, U, V>(_ g: (*U)->*V, _ f: (*T)->*U) -> (*T)->*V {...} > > The asterisks indicate that the arguments to the function will be packed into > a tuple (or not, in the case of a single-argument function) whose type is > denoted by T, U, V, or conversely that the functions take/return argument > lists that look like *T, *U, *V where T, U, V are tuple types. Then the > function definition would look like > > { > return { x: *T in g(f(x)) } > } > > This would in essence create a new non nominal type: function argument lists. > These would be distinct from tuples, although the two may freely be converted > into one another using the asterisk. This type would be structurally distinct > from tuples by virtue of the fact that single-element argument lists exist > while single-element tuples do not. (An asterisk will convert a > single-element argument list into a single (non-tuple) element and vice > versa.) > > To users, argument lists would be accessed solely through tuples with the > asterisk syntax. The identity **T == T would hold whenever T is a tuple or > argument list. Their usefulness would lie in the ability to call f(*x) when f > takes multiple arguments and x is a tuple. > > I acknowledge that this is probably not going to happen for Swift 4 but I > would sure like it if it did. > >> On Jun 9, 2017, at 5:10 PM, Jens Persson via swift-evolution >> <swift-evolution@swift.org> wrote: >> >> The point of exercise 1 is to show that it is impossible (in Swift 4) to >> write a generic function composition operator (or function) which works as >> expected for any reasonable functions. >> This was possible in Swift 3, but in Swift 4 it will only work for functions >> with exactly one parameter. You'd have to special-case it for every >> combination of parameter counts of f and g that it should be able to handle. >> >> The following program demonstrates how it can be done in Swift 3.1 and 3.2: >> >> func compose<T, U, V>(_ g: @escaping (U) -> V, _ f: @escaping (T) -> U) -> >> (T) -> V { >> return { x in g(f(x)) } >> } >> func sum(_ a: Int, _ b: Int) -> Int { return a + b } >> func square(_ a: Int) -> Int { return a * a } >> let squaredSum = compose(square, sum) >> let result = squaredSum((3, 4)) // A bit unexepected with a tuple here but >> ok ... >> print(result) // 49 >> // Well, it worked, not flawlessly but we did manage to write >> // a function composition function and we composed sum >> // and square, and we could call it and get a correct result. >> >> >> And this program demonstrates what happens if you try it in Swift 4: >> >> func compose<T, U, V>(_ g: @escaping (U) -> V, _ f: @escaping (T) -> U) -> >> (T) -> V { >> return { x in g(f(x)) } >> } >> func sum(_ a: Int, _ b: Int) -> Int { return a + b } >> func square(_ a: Int) -> Int { return a * a } >> // let squaredSum = compose(square, sum) // Error! (without the >> compose-variant below) >> >> // The error message is: >> // Cannot convert value of type `(Int, Int) -> Int` to >> // expected argument type `(_) -> _` >> >> // That's it, it is simply not possible! >> >> // You'd have to write special variants of the compose func for every >> combination >> // of parameter counts! For example, in order to get this sum and square >> // example working, this specific variant must be written: >> func compose<T, U, V, W>(_ g: @escaping (V) -> W, _ f: @escaping (T, U) -> >> V) -> (T, U) -> W { >> return { (x, y) in g(f(x, y)) } >> } >> // Now it will work: >> let squaredSum = compose(square, sum) >> // But only thanks to that awfully specific compose func variant ... >> // We would have to write a lot more variants for it to be practically >> usable on pretty much any common function. >> >> I'm sure some will say: >> "no regular developers use function composition anyway so why ..." >> or >> "It's not very swifty to use free functions and higher order functions like >> that." >> >> My answer is that this is just a simple but telling example. The issue (as I >> see it) exists in all situations involving generics and function types. >> >> I'm a regular programmer and I like to be able to write basic, useful >> abstractions. >> It's no fun when the language forces you to write lots of specific variants >> of your generic code. >> >> I would feel less worried about the parentheses situation if the language >> was going in a direction where you could see how this simple exercise would >> be a no brainer. >> >> Can Swift's parentheses-situation be sorted out before ABI stability? >> Otherwise it would be a bit like if Swift had kept the special rule for the >> first parameter, only much worse. >> >> /Jens >> >> >> >> >>> On Fri, Jun 9, 2017 at 7:17 PM, Gor Gyolchanyan <g...@gyolchanyan.com> >>> wrote: >>> Yes, except why would you need to define `((A, B)) -> C`?, If you need to >>> pass a 2-element tuple into a function that takes two parameters - you can! >>> If you want to pass two values into a function that *looks* like it takes >>> a single 2-element tuple - you can! Seems to me that the difference between >>> `((A, B)) -> C` and `(A, B) -> C` is virtually non-existent. But keep in >>> mind that this only works for bare tuples (the ones that can't have >>> labels). Non-closure functions DO have labels, which is part of their >>> signature, so this is a different story. >>> >>>>> On Jun 9, 2017, at 6:18 PM, Gwendal Roué <gwendal.r...@gmail.com> wrote: >>>>> >>>>> >>>>>> Le 9 juin 2017 à 17:12, Gor Gyolchanyan via swift-evolution >>>>>> <swift-evolution@swift.org> a écrit : >>>>>> >>>>>> >>>>>> So I wonder if any of you have had any thoughts about what Swift's >>>>>> parentheses-related future (or evolutionary baggage) will be? >>>>>> >>>>> >>>>> I really wish swift used the concept of tuples **exclusively** for all >>>>> purposes that involve parentheses, as well as dividing tuples into two >>>>> categories: >>>>> - Bare tuples, which do not have labels. >>>>> - Rich tuples, which do. >>>>> As a consequence, here's a list of statements that would become true: >>>>> - All functions take exactly one parameter, which is a tuple. >>>>> - All closures (a.k.a. function pointers) take exactly one parameter, >>>>> which is a bare tuple. >>>>> - All functions return exactly one parameter, which is a tuple. >>>>> - Pattern matching is done on a single bare tuple using a single bare >>>>> tuple pattern. >>>>> >>>>> The currently ongoing proposal to make a single-element tuple >>>>> auto-flatten would work extremely well with this idea, by making all >>>>> these changes completely backward-compatible. >>>> >>>> If I have well understood, Swift has evolved away from this. >>>> >>>> If what you describe were true, added to the fact that there is no such >>>> thing as a one-element tuple in the language, then (A,B) -> C and ((A, B)) >>>> -> C could not be distinguished, for the simple reason that ((A, B)) -> C >>>> could not be defined. >>>> >>>> For ((A, B)) -> C to be defined, we'd need a function that takes exactly >>>> one parameter, which is a tuple (your idea), whose single element is a >>>> tuple (oops, there is no single-valued tuples). >>>> >>>> No opinion here, just they way I have understood recent Swift history. >>>> Gwendal >>>> >>> >> >> _______________________________________________ >> swift-evolution mailing list >> swift-evolution@swift.org >> https://lists.swift.org/mailman/listinfo/swift-evolution > _______________________________________________ > swift-evolution mailing list > swift-evolution@swift.org > https://lists.swift.org/mailman/listinfo/swift-evolution
_______________________________________________ swift-evolution mailing list swift-evolution@swift.org https://lists.swift.org/mailman/listinfo/swift-evolution