3 ms·
> fan of named arguments in Swift Keyword parameters are great. The way they are done in x.f() syntax languages is sub-optimal, and Swift is particularly weir
by mpweiher 6y ago
> fan of named arguments in Swift
Keyword parameters are great. The way they are done in x.f() syntax languages is sub-optimal, and Swift is particularly weird.
> code becomes almost self-documenting
Yes, exactly!
Dan Ingalls explains this wonderfully in his Object Oriented Programming talk. Highly recommended:
https://youtu.be/P2mh92d-T3Y?t=515 https://youtu.be/P2mh92d-T3Y?t=515
The problem is that there is the Smalltalk/Objective-C style keyword syntax or the Pascal/C/C++ etc. function syntax. Both are consistent and complete ways of handling this, though I obviously think the Smalltalk way is better.
But it's either/or. When you jam them together, you get a weird mess of special cases and workarounds.
I would agree that the benefits of labels outweigh the messiness, even for the x.f() + labels case. So if you're coming from the x.f() side of things, I can fully understand and sympathize the view that they are a pure benefit without drawbacks. But once you have keyword messages, you no longer need the x.f() part of the syntax, because the syntax is completely self-sufficient. And then all the extra messiness of integrating the two makes no sense whatsoever.
As an example, the colon and the whitespace are sufficient to separate parameters. So is the comma. So we have...both?
There is also the issue that, please correct me if I got this wrong, the label that's in the signature becomes the name of the parameter inside the function. And as far as I can tell it cannot be changed/mapped. That's a horrible coupling of inside and outside.
Because of this, you actually need labels in your function declaration even for parameters that are unlabeled. Wut? And because of this, you need another special bit of syntax that says "despite the fact that I am now about to give a label, this is unlabeled". It also means that a name that is actually purely internal to the function is part of the signature. Wat?
And sometimes you get partial labels that just kind of sit there. It's really weird when you look at things closely.
I guess an analogy would be like a gasoline engine, a hybrid and a fully electric. Yes, the hybrid seems like an obvious improvement to the pure gasoline engine, if at some cost in complexity. But the pure electric car (let's assume a few more years improvement in battery tech) does away with all that extra complexity.
Hmm not entirely sure that analogy is all that good.
- saurik 6y ago> There is also the issue that, please correct me if I got this wrong, the label that's in the signature becomes the name of the parameter inside the function. And as far as I can tell it cannot be changed/mapped. That's a horrible coupling of inside and outside. You can in fact provide names for both, and there at least used to be (I think they might have removed this?) some ludicrous special case on the behavior of the first parameter.
- DagAgren 6y agoThis was to more closely match the behaviour of Objective-C, and it has been removed as better ways of Objective-C interop were developed.
- DagAgren 6y ago> and Swift is particularly weird. The way Swift does them is the least awkward and most robust I have seen in any language. > As an example, the colon and the whitespace are sufficient to separate parameters. So is the comma. So we have...both? Designing a language around what the minimum requirements of a parser is will not get you a good language. Human language is massively redundant, because humans find it more easy to communicate when there is redundancy. Computer code is also communication aimed at humans, and a bit of redundancy does not hurt there, and can often help. > There is also the issue that, please correct me if I got this wrong, the label that's in the signature becomes the name of the parameter inside the function. This is incorrect. You can optionally specify both an internal and external name for any argument. Unlabelled arguments are just a special case of this syntax, where you say "external name does not exist, internal name is this".
- skohan 6y ago> There is also the issue that, please correct me if I got this wrong, the label that's in the signature becomes the name of the parameter inside the function. And as far as I can tell it cannot be changed/mapped. You got that wrong. You can specify a separate internal name like this: foo(externalName internalName: Type) { ... } > you actually need labels in your function declaration even for parameters that are unlabeled. Wut? And because of this, you need another special bit of syntax that says "despite the fact that I am now about to give a label, this is unlabeled" I mean you need to refer to those values inside your function as something and that has to be specified somewhere. How else would you do it? Also the `_` you're complaining about is just a special case of the syntax I described above. This just means the external parameter name is omitted at the call site. It's quite consistent: if two names are given, one is external and one is internal. If only one is given, that means the external and internal names are the same (which is convenient since this is the common case). > It also means that a name that is actually purely internal to the function is part of the signature. Wat? Again, where on earth else would you put it? That's only also half true: the public signature does not include the internal parameter name. For instance I can declare a protocol like this: protocol P { func foo(arg: Int) } And both of these implementations will conform to it just fine despite the fact that the internal argument names are different: struct A: P { func foo(arg internalA: Int) { ... } } struct B: P { func foo(arg internalB: Int) { ... } } > And sometimes you get partial labels that just kind of sit there. Can you give an example? I'm not quite sure what you're talking about.
- mpweiher 6y ago> You got that wrong. Ahh, my bad! But only the "cannot be changed/mapped." part, right? foo(externalName internalName: Type) { ... } Doesn't this strike you as odd at all? The part that looks like the label is not the label, it's the name of the variable. And then there's this extra bit in front that doesn't look like the label, doesn't really look like anything TBH, that will turn into the label. If present. I kind of see how they got there, but boy is it inconsistent.
- skohan 6y ago