[swift-evolution] [Review] SE-0111: Remove type system significance of function argument labels

T.J. Usiyan griotspeak at gmail.com
Fri Jul 1 12:04:28 CDT 2016


 * What is your evaluation of the proposal?
a reluctant +1
        * Is the problem being addressed significant enough to warrant a
change to Swift?
Yes.
        * Does this proposal fit well with the feel and direction of Swift?
Yes.
        * If you have used other languages or libraries with a similar
feature, how do you feel that this proposal compares to those?
It works well enough
        * How much effort did you put into your review? A glance, a quick
reading, or an in-depth study?
Read a few times over.

The point that actually tipped my opinion came from Jordan Rose " Argument
labels are definitely part of the *name* of the function, but they aren’t
part of the *type*. A few functions happen to have argument labels "

I am of the general opinion that argument labels are part of the type,
which helps explain `stride(to:by:)` vs `stride(through:by:)` in terms of
overloading instead of name lookup. While this proposal would render that
explanation invalid, I realize that I was conflating the ideas of name and
type. I wish we could have the tuple to tuple model but I see how it isn't
tractable when combined with other features.



On Fri, Jul 1, 2016 at 12:56 PM, Michael Ilseman via swift-evolution <
swift-evolution at swift.org> wrote:

>
> On Jul 1, 2016, at 1:30 AM, Taras Zakharko via swift-evolution <
> swift-evolution at swift.org> wrote:
>
> Jordan, Thanks for the very insightful explanation! It all makes a lot of
> sense in perspective.
>
> Apparently I was thinking about this issue a bit while I was sleeping, and
> now it seems to me that part of the problem is because one strives for the
> function signature to be linguistically meaningful (as in natural language
> meaningful). It was mentioned that argument labels often don’t make much
> sense when detached from the function name, and that some function seem to
> have semantically compatible signatures and some don’t, e.g. the example of
>  drawLineTo(x: Float, y: Float) and drawLineWith(angle: Float, distance:
> Float)
>
> So this is actually a linguistic problem. More precisely, its a problem of
> predicate frames/argument semantics. Consider verbs like ‚hit' and ‚kill'.
> In term of precise semantics, we can model them as something like
>
> kill(killer:victim:)
> hit(hitter:victim:)
>
> However, the actual status of the arguments here is compatible. Both verbs
> describe asymmetric actions, with one argument playing an active role in
> (negatively) changing the state of the other , passive one. So both are
> compatible with a broad metatype (what we often call predicate type in
> linguistics)
>
> P(agent:undergoer:)
>
> However, there are plenty of verbs that are quite different. Like
> go(person:to). Also two arguments, but the semantic status of them is very
> different.
>
> If that is really the case, then there is indeed no general solution which
> keeps the argument labels semantically meaningful. But there is still a
> potential conflict with the tuple/function signature labels.
> The only reasonable choice that comes to my mind is to completely drop
> argument labels in closure variables and just look at the argument type.
> Basically, by assigning function variables, we drop any semantics and just
> look at the overall structure (cardinality/argument types)
>
>  In more detail:
>
> 1. Maintain that argument labels are not part of the type, but merely
> hints for the function dispatch/programmer convenience
>
>
> They are not merely hints, they are part of the full name of the function.
> Functions with different names are different functions, even if they share
> the same base name. That is, they are syntactically meaningful.
>
> 2. *Disallow* argument labels in closure variables.  I.e.:
>
>     var fun = drawLineTo(x:y:)
>
>    has type (Float, Float) -> (), which makes the variable explicitly
> compatible with any  function of cardinality 2 that takes Float arguments.
> At the sae time, any declaration like
>
>     var fun : (x: Float, y: Float) -> ()
>
>    should be illegal. This further makes clear that tuples and functions
> are not the same thing.
>
>
> 3. In the long term, maybe consider *removing* *labels from tuples*. At
> the same time, there should be a new mechanism in place that allows one to
> elevate tuples to structs, with properties taking the role of the current
> tuple labels (like Python’s namedtuple)
>
> An alternative, in order to keep the cake and eat it too, would be
> something along the lines of making predicate types explicit. E.g. creating
> some sort of function ‚semantic metatype‘ and declaring function
> conformance to this metatype. But I can’t imagine that it is a good idea.
> Natural languages are really not a good source of inspiration in this
> regard.
>
> Best,
>
>  Taras
>
>
> On 01 Jul 2016, at 05:33, Jordan Rose <jordan_rose at apple.com> wrote:
>
>
> On Jun 30, 2016, at 13:36, Taras Zakharko via swift-evolution <
> swift-evolution at swift.org> wrote:
>
>
> On 30 Jun 2016, at 22:11, Austin Zheng <austinzheng at gmail.com> wrote:
>
> As for the label semantics, Swift's current behavior is actively
> misleading, please see the example in the prior email. There are no
> meaningful semantics in the label, because implicit conversion between
> differently-labeled function types means that there is no way to usefully
> enforce these invariants to begin with.
>
>
> That is a good point. I admit to not knowing this (I strongly expected
> that labels would be semantically meaningful). But what exactly is the
> status of the argument labels than in Swift? Just a documentation device
>  for the programmer and a  hint for the compiler to do function dispatch?
> But if the compiler indeed does dispatch on argument labels, then they are
> not completely void of semantics, are they?  As I mentioned before, I think
> the problem here is much deeper.
>
> The state of affairs I would prefer is something along these lines:
>
> 1. Labels are semantically meaningful
> 2. There is an explicit casting system for function signatures
> 3. This casting system should be in close correspondence to tuples. The
> "function argument lists look sort of like tuples“ is a very compelling
> reason actually, because of the principle of the least surprise. If I have
> two things in the language that look very similar, then its very confusing
> if they  exhibit very different behaviour. Again, I am not proposing that
> one goes back to model functions in terms of tuples. But as long as there
> is a surface resemblance (and an obvious morphisms between the two), at
> least some aspects of their design should be kept in sync.
>
> But again, this touches on some deep design decisions for the language, so
> I — as an amateur — don’t feel in my plate discussing this here. I believe
> that there currently might be some inconsistencies in the language design
> that should be sealed with (but maybe they are no inconsistencies at all
> and I simply have false expectations).
>
>
> Language history, a.k.a. story time!
>
> We started out with the “perfect” model of a function type being a map
> from a tuple to a tuple. Different argument labels were just overloads. It
> really was quite a simple model, other than not having 1-tuples. Well, and
> variadics and default values and trailing closures didn’t make sense
> anywhere but in functions, but still. Very simple.
>
> (And inout. And autoclosure. And maybe a few more.)
>
> Then we hit a snag: naming guidelines. We wanted argument labels to be
> something people felt comfortable using, something that would be encouraged
> over a sea of unlabeled arguments. But even before the Swift 3 naming
> conventions were hammered out, the natural names for argument labels didn’t
> seem to match the names you’d want to use in the function. So we split the
> names of parameters off from the names of tuple elements.
>
> (This was precipitated by wanting to import Objective-C methods, but I
> think it would have come up regardless.)
>
> As seen earlier in the thread, argument labels don’t make for good tuple
> element labels. Especially with the Swift 3 guidelines, argument labels
> usually don’t make sense without the context provided by the base name, and
> two methods that happen to share argument labels might not actually be very
> similar, while two methods that are duals of each other might have
> different argument labels due to, well, English (e.g. 'add(to:)' vs.
> 'remove(from:)’).
>
> The real blow, however, came with that very first idea: that we could
> treat methods with different argument labels as simple overloads in type.
> This led to poor diagnostics where the compiler couldn’t decide whether to
> believe the types or the argument labels, and might tell you you have the
> wrong argument labels rather than a type mismatch. For pretty much every
> Apple API, this was the wrong decision. On top of all that, it was really
> hard to refer to a method when you *didn’t* want to call it. (Most
> methods with the same base name still have unique labels, so you don’t need
> the types to disambiguate.)
>
> So we introduced the notion of “full names”, which are the things you see
> written as ‘move(from:to:)` (and which are represented by DeclName in the
> compiler). Almost immediately diagnostics got better, testing optional
> protocol requirements got shorter, and a lot of compiler implementation got
> simpler.
>
> And then we kind of got stuck here. We have full names used throughout the
> compiler, but tuple labels still appear in types. They’re still used in
> mangling. We got rid of the “tuple splat” feature, but still model
> out-of-order arguments as “tuple shuffles”. And we allow a number of
> conversions that *look* like they should be invalid, but aren’t.
>
> (And it’s important that we continue allowing them, or at least some of
> them, because we want to be able to pass existing functions to things like
> map and reduce without worrying about conflicting labels.)
>
> So we’ve given up the perfect ideal of tuple-to-tuple. But we did it
> because we value other things more than that ideal: variadics, default
> values, trailing closures, inout, autoclosure, distinct argument labels and
> parameter names, referencing a function by full name, and diagnostics that
> better match the user’s likely intent (particularly given the naming
> guidelines and existing libraries). I think that’s a worthwhile trade.
>
> Jordan
>
> P.S. Anyone is allowed to think this is *not* a worthwhile trade! But
> part of the purpose of this story is to show that we’re already 90% of the
> way towards making tuples and function arguments completely separate, even
> if they have similar syntax. This proposal gets us to maybe 95%.
>
>
> _______________________________________________
> swift-evolution mailing list
> swift-evolution at swift.org
> https://lists.swift.org/mailman/listinfo/swift-evolution
>
>
>
> _______________________________________________
> 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/20160701/e5abf71f/attachment.html>


More information about the swift-evolution mailing list