News for hackers. Stuff that matters.
Re:The Curious Case of Swift's Adoption of Smalltalk Keyword... by skohan on Sunday June 14, 2020 @10:43AM (#23517990)
I don't really get this complaint:

> The already weird-ish addition of Smalltalk/Objective-C keywords inside the f(x) syntax: f(arg:x)

I'm a huge fan of named arguments in Swift. It's one of the things I miss most when working with languages which don't have it.

For instance, I do a lot of work with computer graphics, and in that case you end up with a lot of functions with a lot of arguments for things like configuration. With named arguments, code becomes almost self-documenting. Without them, I just end up using comments in their place, but of course then I don't have the compiler making sure this is correct.

It's a totally optional language feature, and adds a lot of value in some cases.

Re:The Curious Case of Swift's Adoption of Smalltalk Keyword... by kiawe_fire on Sunday June 14, 2020 @11:22AM (#23518318)
Maybe it's shallow of me, but named/keyword arguments are now at the top of my list of things I want in a programming language.

For all the attention given to static typing and unit testing for increasing developer confidence, I think named arguments belong up there as well. Makes reading code so much easier, especially the way they are implemented and encouraged in Swift.

As someone stuck doing PHP for my day job, they could buy an awful lot of goodwill from me by implementing something like this in PHP (well, that, and separating arrays from dictionaries, but that seems far less likely to happen).

Re:The Curious Case of Swift's Adoption of Smalltalk Keyword... by simias on Sunday June 14, 2020 @11:43AM (#23518498)
I like named/keyword arguments too but I think one needs to be careful not to overdo it, especially in statically typed languages. I think it's sort of a last resort when the call syntax can't be disambiguated by other means.

As an example imagine a search function that returns the position of a character `c` in a string `str` that looks like that:

    int search(String str, char c, bool case_sensitive, bool from_end)
I'd say that I would avoid this signature in general, because those two `bool`s make for an awkward call syntax:

    search("foo", 'f', true, false)
That's pretty opaque, even if you know what the two options are it's easy to forget the order. Now you might say "well see, that's where keyword parameters shine!" and you'd be right, it does help a lot:

    search("foo", 'f', case_sensitive: true, from_end: false)
But I'd argue that while this is good enough if you're coding in a dynamically typed language, it's actually sub-obtimal if you're coding in Rust for instance. Here you can do something even better: give these two options different types, this way not only it makes the code more explicit, it also means that it gets enforced by the compiler:

    enum SearchCase { Sensitive, Insensitive };
    enum SearchDirection { FromStart, FromEnd };

    search("foo", 'f', SearchCase::Sensitive, SearchDirection::FromStart);
Now that's not to say that I don't want or like keyword arguments, I just think that it's one of these situations where "when you have a hammer, everything looks like a nail". I sometimes miss keyword arguments in Rust, but it's the exception rather than the rule for me.
Re:The Curious Case of Swift's Adoption of Smalltalk Keyword... by skohan on Sunday June 14, 2020 @12:32PM (#23519043)
I would question that your rust example is better than the named argument example. I think it's situational at best, and a workaround at worst.

For instance, even in the example you gave, it could be argued that the SearchCase type is really just a boolean which is being introduced to do the job of an argument label. If this enum is only used in this function call, that's going to add noise to the docs with fairly tenuous justification.

And this only works in the case of arguments which can be easily converted to enums. For instance if I have a signature which looks like this:

   void search_buffer(int match, int start, int end, int stride)
It's going to be very difficult to look at the call site and infer what the meanings of these arguments are.
Re:The Curious Case of Swift's Adoption of Smalltalk Keyword... by simias on Sunday June 14, 2020 @03:37PM (#23520642)
>For instance, even in the example you gave, it could be argued that the SearchCase type is really just a boolean which is being introduced to do the job of an argument label. If this enum is only used in this function call, that's going to add noise to the docs with fairly tenuous justification.

I don't really agree with this, I think in general it's a good idea to type your parameters as tightly as it's reasonable to do. I don't think that introducing a one-time enum is particularly unreasonable. I don't really get the argument for reducing noise in the docs, typically nowadays API documentations are hyperlinked document, not a big PDF, you either look the symbol up or you don't.

An argument in favour of using types here would be in the situation where the "case_sensitive" parameter is not a literal in the code but something that's being passed as argument from an other function or stored in an object. The names could be slightly different, the conventions could change from one part of the code to an other etc... With dedicated types you can be reasonably certain that if the types match then it's probably safe to pass to the function, with human-level semantics that may require more caution.

Of course my example is so trivial that it could be argued to be over-engineered, but consider a function that takes angles as floating point numbers vs. a dedicated "Angle" type for instance, with the float you have to make sure that the underlying representation is correct (degrees? radians? turns?) whereas a dedicated type would typically have well-defined semantics.

>And this only works in the case of arguments which can be easily converted to enums. For instance if I have a signature which looks like this:

   void search_buffer(int match, int start, int end, int stride)
I agree completely with you here. Keyword parameters definitely have their use cases. I just think that they should be used parsimoniously and, IMO, can be a code smell if used too often, especially in languages with a decent type system.
Re:The Curious Case of Swift's Adoption of Smalltalk Keyword... by oefrha on Sunday June 14, 2020 @11:49AM (#23518573)
You’re forgetting another important use case of keyword/named arguments: default values. In Rust either every call site needs to specify the default values, or you use a None for the default which is not at all readable.

Also, if Rust were to support named arguments (even better if with default values), you can use explicit types for your bools all the same. It’s not an either or situation.

Re:The Curious Case of Swift's Adoption of Smalltalk Keyword... by kbenson on Sunday June 14, 2020 @03:10PM (#23520417)
Wouldn't a struct for named options that have defaults which is passed as the last option emulate optional named arguments with default values?
Re:The Curious Case of Swift's Adoption of Smalltalk Keyword... by skohan on Sunday June 14, 2020 @03:54PM (#23520781)
Of course in the case of Rust this would mean potentially one type per function being added to your implementation. That’s a lot of boilerplate for a problem which is solved really well by defaultable named parameters
Re:The Curious Case of Swift's Adoption of Smalltalk Keyword... by kbenson on Sunday June 14, 2020 @04:17PM (#23520945)
I agree it seems like a lot of boilerplate, but from what little I've played around with Rust, it seems they've already adopted strategies similar to this for instantiating objects with the builder pattern[1], but the nuts and bolts are abstracted away so the interface is slightly different.

If I understand it correctly, the equivalent builder pattern in Rust (which is essentially using methods to build a struct used to instantiate the object) would be:

    let search = Search::new("foo","f")
      .option_case_sensitive(true)
      .option_from_end(false)
      .build();
Where "new" returns a builder object/struct with passed in and default params, those options methods are optional and can change those defaults, and the build method actually builders the search object from the search builder struct with all the params.

I'm not sure how well this style works with simple functions, unless there's a macro or crate that can do most of this work for you from a a spec.

1: https://doc.rust-lang.org/1.0.0/style/ownership/builders.htm...

Re:The Curious Case of Swift's Adoption of Smalltalk Keyword... by saagarjha on Sunday June 14, 2020 @01:07PM (#23519362)
> Here you can do something even better: give these two options different types, this way not only it makes the code more explicit, it also means that it gets enforced by the compiler

Bool is also enforced by the compiler; adding ad-hoc types for things that have only two values is generally not something you should do without good reason. By the way, constructs like these are fairly common in Swift:

  enum SearchType {
      case literal
      case regex
      case extendedRegex
  }

  extension String {
      func substring(matching needle: String, interpretedAs type: SearchType = .literal) -> Substring
  }
which you'd use as something like

  "foobar".substring(matching: "o*ba", interpretedAs: .regex) // "ooba"
Re:The Curious Case of Swift's Adoption of Smalltalk Keyword... by barrkel on Sunday June 14, 2020 @02:45PM (#23520149)
In the absence of keyword arguments as a language feature, boolean arguments should almost always be avoided, and replaced by enums where possible. Boolean arguments are almost always inscrutable at the call site.
Re:The Curious Case of Swift's Adoption of Smalltalk Keyword... by skohan on Sunday June 14, 2020 @02:59PM (#23520300)
Then it would be very convenient to have keyword arguments, as in the case presented by the previous poster
Re:The Curious Case of Swift's Adoption of Smalltalk Keyword... by kiawe_fire on Sunday June 14, 2020 @11:59AM (#23518710)
I still think there are wider use cases for named arguments. For example, even disambiguating between which argument is the "string" and which is the "substring to be found", or the classic "x, y, width, height" list in graphics programming.

But your point is well taken that, like many tools, you shouldn't abandon one set of good practices for another. There are certainly cases where a builder pattern or enum values are a better fit, which could be obscured as an option because keyword arguments "sorta kinda but don't really" address the same thing.

Re:The Curious Case of Swift's Adoption of Smalltalk Keyword... by ridiculous_fish on Sunday June 14, 2020 @03:10PM (#23520413)
If this were a real API, you would need to add the trimmings:

    /// Doc comment doc comment doc comment
    #[derive(Debug, Copy, Clone, Eq, PartialEq)]
    pub enum SearchCase { Sensitive, Insensitive }
now it starts to feel like heavyweight clutter.
Re:The Curious Case of Swift's Adoption of Smalltalk Keyword... by simias on Sunday June 14, 2020 @03:43PM (#23520691)
I see what you mean, but if that's the problem I'd argue that the weakness is that Rust lacks a shorthand to declare simple enums, not necessarily that it lacks keyword parameters. #[derive] soup aside I don't think too bad at the moment though, and I'm not really sure how you could simplify that without introducing too much magic into the language.

After all, even with keyword parameters there'll always be plenty of opportunity for one-off enums, if only for situations where more than two choices are possible. Take a typical "seek" function for instance, who can usually be performed relative to the current location, from the start or from the end.

Re:The Curious Case of Swift's Adoption of Smalltalk Keyword... by atombender on Sunday June 14, 2020 @02:49PM (#23520202)
In Go (and, I think, Rust?) variadic arguments are often used for optionals:

    search("foo", CaseSensitive, FromStart)
or options that take values:

    search("foo", WithCaseSensitivity(false))
Re:The Curious Case of Swift's Adoption of Smalltalk Keyword... by yoz-y on Sunday June 14, 2020 @12:44PM (#23519145)
That's why Swift does support unnamed parameters as well, and they can interweave with named ones. If the type of the argument is explicit enough, you can make the parameter name at call site optional.
Re:The Curious Case of Swift's Adoption of Smalltalk Keyword... by wool_gather on Sunday June 14, 2020 @01:16PM (#23519438)
Nitpick (I think this is just a miswording rather than a misunderstanding): it's not optional. You can have unlabelled args, but that's enforced too: the label must be included or omitted at the call site according to the function declaration.
Re:The Curious Case of Swift's Adoption of Smalltalk Keyword... by yoz-y on Sunday June 14, 2020 @07:03PM (#23522176)
TBH I was usure and kind of lazy to check. Thanks for pointing it out!
Re:The Curious Case of Swift's Adoption of Smalltalk Keyword... by frou_dh on Sunday June 14, 2020 @01:18PM (#23519449)
A sufficiently smart editor could show names in front of positional arguments, even if named arguments are not part of the language.
Re:The Curious Case of Swift's Adoption of Smalltalk Keyword... by skohan on Sunday June 14, 2020 @01:22PM (#23519469)
Tools are great, but I'm not a fan of the idea of needing special tooling outside of the source code itself in order to be able to understand it.

Maybe it's just me, but I would hate to imagine living in a world where my projects might be incomprehensible if I ever lost my .vimrc

Re:The Curious Case of Swift's Adoption of Smalltalk Keyword... by frou_dh on Sunday June 14, 2020 @01:24PM (#23519482)
In this case it would be a pure value-add, because the fallback is the way everyone can evidently cope with anyway.
Re:The Curious Case of Swift's Adoption of Smalltalk Keyword... by adrianmsmith on Tuesday June 16, 2020 @02:03PM (#23542094)
I'm not sure that's entirely true. If a large proportion of people use a more advanced development tool, it sort of becomes indispensable, because people design the software to be edited with the tool, such that it becomes difficult to edit it without the tool.

For example if, today, I checked in code like performRequest(request, response, null, null, null) you probably wouldn't consider that good code, as it's not clear what the nulls mean there. Most people today would try to not write code like that. But if everyone was using an editor which displayed the parameter names, then it'd be fine. People would write that code, check it in, and so on. Which would mean that those people without the tool would have to confront such code.

Re:The Curious Case of Swift's Adoption of Smalltalk Keyword... by adrianmsmith on Sunday June 14, 2020 @01:44PM (#23519636)
IntelliJ does this in Java. It only does it for those arguments where the meaning could be unclear. For example, true/false or null.
Re:The Curious Case of Swift's Adoption of Smalltalk Keyword... by anchpop on Sunday June 14, 2020 @01:49PM (#23519673)
Rust-analyzer does this, and I find it much more helpful than I thought I would
Re:The Curious Case of Swift's Adoption of Smalltalk Keyword... by frank2 on Thursday June 18, 2020 @03:28PM (#23566796)
What editor or IDE do you use rust-analyzer with?
Re:The Curious Case of Swift's Adoption of Smalltalk Keyword... by mariodiana on Sunday June 14, 2020 @12:10PM (#23518825)
If they could just add square brackets, it would be perfect.
Re:The Curious Case of Swift's Adoption of Smalltalk Keyword... by saagarjha on Sunday June 14, 2020 @01:12PM (#23519395)
I think you might be interested in a little language called Objective-C ;)
Re:The Curious Case of Swift's Adoption of Smalltalk Keyword... by MrBuddyCasino on Sunday June 14, 2020 @11:34AM (#23518420)
Automatically generated builders are also nice, not sure yet which I prefer.
Re:The Curious Case of Swift's Adoption of Smalltalk Keyword... by kevincox on Sunday June 14, 2020 @11:53AM (#23518631)
I have long envisioned a language where these two things were tightly combined. The rough ideas are:

- All arguments are keyword arguments. - Each function implicitly defines a struct type equivalent to its arguments.

I think if you combined this with some nice structural typing you can get a lot of the argument forwarding/builders and similar that people enjoy in dynamic languages without much/any overhead. Rough example:

fn add(a: int, b: int): int { a + b }

fn add3(c: int, rest: add::args): int { add(rest) + 3 }

A somewhat silly example but I think you can see the point. Of course you could also add language-level builder syntax to these structs and have something really nice.

I think the key here is that once you make the arguments a static type you can add loads of convenience like builders very easily.

Re:The Curious Case of Swift's Adoption of Smalltalk Keyword... by wwright on Sunday June 14, 2020 @02:16PM (#23519906)
This makes me wonder if there is some sort of relationship between currying and row polymorphism; that could be pretty sweet to capture succinctly in a language
Re:The Curious Case of Swift's Adoption of Smalltalk Keyword... by MrBuddyCasino on Sunday June 14, 2020 @11:10PM (#23523417)
Args reified as structs, interesting! On the other hand, not exceptional at all when looking at it from a Lisp angle.
Re:The Curious Case of Swift's Adoption of Smalltalk Keyword... by eeereerews on Sunday June 14, 2020 @05:40PM (#23521618)
I've thought about this too, but keeping positional args. The basic data type would be a "blob", consisting of a struct part and a tuple part.
Re:The Curious Case of Swift's Adoption of Smalltalk Keyword... by oefrha on Sunday June 14, 2020 @11:45AM (#23518522)
Builders are nice when you actually need to build something with tons of optional arguments. The vast majority of cases where named arguments shine are function/method calls where builders just don’t make sense. Also, named arguments complement/augment the builder pattern.
Re:The Curious Case of Swift's Adoption of Smalltalk Keyword... by MrBuddyCasino on Sunday June 14, 2020 @11:52AM (#23518627)
Good point. Also, named arguments can be compiler checked for mandatory values, with builders the error happens at runtime.
Re:The Curious Case of Swift's Adoption of Smalltalk Keyword... by swsieber on Sunday June 14, 2020 @12:10PM (#23518829)
You can actually have type safe buildrs in rust where trying to call the method that consumes the builder fails to compile if not all the arguments are set correctly.

https://github.com/idanarye/rust-typed-builder/blob/master/R...

Re:The Curious Case of Swift's Adoption of Smalltalk Keyword... by MrBuddyCasino on Sunday June 14, 2020 @03:21PM (#23520521)
Ah yes, linear types to the rescue! Nice.
Re:The Curious Case of Swift's Adoption of Smalltalk Keyword... by swsieber on Sunday June 14, 2020 @03:46PM (#23520713)
I think technically it's affine types. In this particular case it comes from really nice generics - you start out with a struct that's generic over all fields - one generic bound per field. And that let's you implement methods depending on what fields have been set. So you could even make a builder with mutually exclusive setters. But you'd probably just want to use an enum in that case for the mutually exclusive options.
Re:The Curious Case of Swift's Adoption of Smalltalk Keyword... by MrBuddyCasino on Monday June 15, 2020 @03:21AM (#23524703)
I still don't quite understand the generics magic required in order to not generate exponential amounts of code for it to allow random order of arguments, but I won't complain. That capability would have come in handy on Java/Lombok.
Re:The Curious Case of Swift's Adoption of Smalltalk Keyword... by swsieber on Wednesday June 17, 2020 @12:11PM (#23553060)
> exponential amounts of code for it to allow random order of arguments

The key is that it only generates code for types that actually get used. So if you always call the orders in the same order, it won't generate tons of code. That said, you could actually tweak the type-safe builder to enforce a certain order for calling the methods on the builder.

Also, it's not the order of arguments, it's the order of method calls :)

Re:The Curious Case of Swift's Adoption of Smalltalk Keyword... by ndotl on Sunday June 14, 2020 @01:26PM (#23519498)
Named arguments are great but should be used with care as they also create a reverse dependency. It prevents you from ever renaming the arguments in the future.
Re:The Curious Case of Swift's Adoption of Smalltalk Keyword... by wool_gather on Sunday June 14, 2020 @01:42PM (#23519624)
Accompanying saagarjha's point, you can freely rename the internal argument names, just not the external labels. Which is basically the same as changing the argument names in say C.
Re:The Curious Case of Swift's Adoption of Smalltalk Keyword... by paublyrne on Sunday June 14, 2020 @01:35PM (#23519566)
In the case of a library that would make this a breaking change you could add the new key rather than changing it, and support both while flagging old key usage with a deprecation warning.
Re:The Curious Case of Swift's Adoption of Smalltalk Keyword... by saagarjha on Sunday June 14, 2020 @01:28PM (#23519511)
Just like you can't ever rename the function in the future?
Re:The Curious Case of Swift's Adoption of Smalltalk Keyword... by dep_b on Sunday June 14, 2020 @02:16PM (#23519897)
You can mark it as deprecated with a reference to the replacing function. As long as the argument types match you can automatically refactor
Re:The Curious Case of Swift's Adoption of Smalltalk Keyword... by DagAgren on Sunday June 14, 2020 @03:23PM (#23520538)
This is already the case with the name of your function. And named arguments are basically just an extension of the name of your function.
Re:The Curious Case of Swift's Adoption of Smalltalk Keyword... by fsloth on Sunday June 14, 2020 @01:39PM (#23519594)
Why would it? When you change the name of nth argument from foo to bar, compile will fail and then you just need to do a global rename. Is there any scenario where this would not be feasible?
Re:The Curious Case of Swift's Adoption of Smalltalk Keyword... by wool_gather on Sunday June 14, 2020 @02:05PM (#23519806)
The caller can't do a global rename if they don't own the source of the function -- because it's in a library. Which is what parent meant by "reverse dependency": the library's interface is constrained by the fact that it has users.
Re:The Curious Case of Swift's Adoption of Smalltalk Keyword... by fsloth on Monday June 15, 2020 @01:06AM (#23523963)
Surely if the library interface changes the users can change their own code? That's why we have versioning of libraries - so that users of the library can take intelligently new versions into use, and especially so they are aware if (and when) the interface changes.
Re:The Curious Case of Swift's Adoption of Smalltalk Keyword... by DagAgren on Sunday June 14, 2020 @03:22PM (#23520531)
But this is already the case for the name of the function. Semantically, named arguments are just part of the name of the function.
Re:The Curious Case of Swift's Adoption of Smalltalk Keyword... by jasondclinton on Sunday June 14, 2020 @12:42PM (#23519121)
It's really weird to me that this is (currently) the top-voted comment on this article. This little quip is not what the article is about nor does it represent the author's views.

Do you have any feedback on that article's thesis that the closure syntax could have been handled better?

Re:The Curious Case of Swift's Adoption of Smalltalk Keyword... by dsabanin on Sunday June 14, 2020 @01:01PM (#23519301)
Hindsight is 20/20.

Every programming language changes as it evolves and matures and people understand how to use it best or its domain changes significantly. Unfortunately, this always means accumulating these syntactic and semantical warts. Personally, I think Swift manages to keep a good balance, and it's a very powerful language, with lots of users and compatibility requirements, so it's much harder for them than for many others.

Alternative is constant redesign of syntax and behavior that just keeps making users unhappy with every release, breaking their code, libraries and obsoleting the docs.

If, to mitigate that, you try to make big changes to the language in big releases, once in a long while, you can easily get into the Python 3, Scala 3, Perl 6 fiasco and that can simply kill the language adoption.

It's a hard problem.

Re:The Curious Case of Swift's Adoption of Smalltalk Keyword... by aduitsis on Monday June 15, 2020 @10:03AM (#23527398)
Very good point, thank you.

As regards Perl 6, a recent development was to rename it to Raku, which (in hindsight) seems like a perfectly sensible decision. The overloading of the name Perl for a language that proved to be something different from Perl 5 caused trouble both ways. Perl 5 was widely considered to be a version that was to be eventually be replaced, whereas Perl 6 was considered a language that was a close and direct iteration of Perl 5. So we basically got the worst of both worlds. Perl 5 is very much in use today, still being actively maintained and is getting new features regularly, while Raku/Perl 6 is a beautiful new different language with interesting ideas being worked on by many brilliant folks, and the notion of trying to be in any way compatible with Perl 5 seems utterly irrelevant today.

Re:The Curious Case of Swift's Adoption of Smalltalk Keyword... by lizmat on Monday June 15, 2020 @09:20AM (#23527001)
Indeed. In the Perl 6 case, this has been solved by renaming the language to Raku (https://raku.org using the #rakulang tag on social media).
Re:The Curious Case of Swift's Adoption of Smalltalk Keyword... by b2gills on Monday June 15, 2020 @06:23PM (#23533774)
The Python 3 changes aren't big changes. They are breaking changes however.

I know they aren't big because Perl has had to deal with many of those same type of problems, only it didn't have to break old code to do it.

Perl 6 is more of a research project that took Perl 5 as a leap-off point. As it is is such a large departure from every language, it deserves it's own name. So it is now known as Raku.

Re:The Curious Case of Swift's Adoption of Smalltalk Keyword... by skohan on Sunday June 14, 2020 @01:16PM (#23519433)
I have followed the discussion around this on the Swift forums, and I'm actually of the opinion that the debate around this topic amounts to little more than bikeshedding and the proposed syntax for multiple trailing closures is fine.

I'm a bit perplexed by the author's position that Swift should just be small-talk as though this is obviously better.

As far as the idea of getting rid of parens entirely as the author suggests, I'm not a big fan of this approach. In languages like ruby where parens are not used, I tend to find this makes things a lot less readable. That might be a matter of opinion, but at the very least I think it can be said that Swift's approach to arguments, where only closures can be moved out of the parentheses of a function call is a perfectly consistent and defensible approach. For instance I don't think that this:

    foo(someArg: 42) {
         // do something
    }
Is less clear than this:

    foo doSomething: {
        do something
    }
    someArg: 42
In fact I think it's probably the opposite, and the only reason I can imagine to prefer the second example would be out of some appeal to purity/simplicity of the function call syntax over any level of pragmatism.

As far as the whole debate over the inconsistency of the first argument label being removed while the following argument labels are required in multiple-trailing-closure syntax, I just don't think it's that big a deal. I also understand the consistency argument, that it should be handled the same for all arguments (i.e. the author of the function signature should explicitly decide if the label is required or not), and it probably should work that way, but I also understand why it hasn't been proposed that way for the first iteration. It would break a lot of code given how prevalent trailing closures are in Swift.

However there are already proposals in the pipeline to introduce an argument label in the first trailing closure (provided the function author hasn't named it `_`). I suspect in the long term this will eventually make it into the language, and automatic migration tools will make it possible to resolve issues with existing code without much fuss.

So in short I think multiple trailing closures are a good and natural addition to the language which provide real value, and the proposed syntax is absolutely fine.

Re:The Curious Case of Swift's Adoption of Smalltalk Keyword... by gumby on Sunday June 14, 2020 @03:18PM (#23520495)
FWIW I actually like comments that expand on a side point in an article. After all an author expands on their primary topic pretty much by definition.
Re:The Curious Case of Swift's Adoption of Smalltalk Keyword... by jakear on Sunday June 14, 2020 @12:57PM (#23519270)
I like the standard TS/JS approach to this. All arguments are positional and not named at call site, but you can instead pass around object literals.
Re:The Curious Case of Swift's Adoption of Smalltalk Keyword... by dmitriid on Sunday June 14, 2020 @03:21PM (#23520522)
You can't. Unless the function has extra code destructuring those objects.

Passing around objects is precisely the workaround people use for lack of named arguments.

Re:The Curious Case of Swift's Adoption of Smalltalk Keyword... by jakear on Sunday June 14, 2020 @04:18PM (#23520957)
Yes, the function definition must opt-in to accepting named arguments. To me that’s not a big deal, and if it means the same object/array spread syntax can be used everywhere for the same effect, it’s miles better than introducing new syntax for named arguments.

In my opinion, languages should be simple and small, relating on composition of core syntax features over introducing new syntax for each and every new stylistic fad happens to be popular this year.

Re:The Curious Case of Swift's Adoption of Smalltalk Keyword... by dmitriid on Monday June 15, 2020 @01:35AM (#23524129)
> if it means the same object/array spread syntax can be used everywhere for the same effect

It cannot. Because, as you yourself said it: the function must know how to deal with object-as-parameters.

> relating on composition of core syntax features over introducing new syntax

This doesn't work for named arguments. They either exist in a language, and you can use them everywhere, or they don't, and you're left with inconsistently implemented workarounds.

Re:The Curious Case of Swift's Adoption of Smalltalk Keyword... by jakear on Monday June 15, 2020 @01:45AM (#23524160)
It can - you pass objects to functions declared with named parameters, and you pass lists to functions declared with positional parameters. It is true that the function must be written one way one or the other a. priori (it could theoretically detect, but that’s not ideal).

And what I’m saying is that if they don’t exist in a language and you can instead using other more core things in the language to implement them rather than adding new syntax (complexity) to the language itself, that’s (in my opinion) a better language and the one I’d rather work in.

Re:The Curious Case of Swift's Adoption of Smalltalk Keyword... by dmitriid on Monday June 15, 2020 @05:05AM (#23525343)
> It can - you pass objects to functions declared with named parameters, and you pass lists to functions declared with positional parameters.

Once again: these are workarounds and there are no "functions declared with named parameters" in Javascript. There are functions that accept objects as a parameter, and they employ additional code to work with those objects.

Example:

    function add(x, y) {}
No matter how much you try, you cannot "use the core thing in the language" to make this function accept this

    add(x = 1, y = 2)
    // or
    add({x: 1, y: 2})
without writing additional code inside the function itself.

So if a library gives you `function add(x, y)`, that's what you're stuck with, forever. You cannot pretend that named arguments can be solved by "javascript's core language". It cannot.

Re:The Curious Case of Swift's Adoption of Smalltalk Keyword... by jakear on Monday June 15, 2020 @05:33AM (#23525484)
It’s really not as complicated as you’re making it out to be. If I’m making a function that has potentially confusing parameters, I make it accept an object. This forces named parameters, and it does so only using core language features.

Yes, there’s no dedicated syntax to allow people to name parameters that weren’t intended to be named. So what?

Re:The Curious Case of Swift's Adoption of Smalltalk Keyword... by dmitriid on Monday June 15, 2020 @11:36AM (#23528494)
> It’s really not as complicated as you’re making it out to be.

Of course it's not complicated, it's as simple as I showed.

> If I’m making a function that has potentially confusing parameters, I make it accept an object.

It doesn't really matter what you, a single developer, do, does it?

If I have to work with a third-party library that has "confusing parameters", please enlighten me how I can make its functions "accept an object to force named parameters"?

> there’s no dedicated syntax to allow people to name parameters that weren’t intended to be named. So what?

I've clearly shown what in at least three messages.

Re:The Curious Case of Swift's Adoption of Smalltalk Keyword... by mpweiher on Sunday June 14, 2020 @02:14PM (#23519882)
> 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

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.

Re:The Curious Case of Swift's Adoption of Smalltalk Keyword... by DagAgren on Sunday June 14, 2020 @03:28PM (#23520578)
> 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".

Re:The Curious Case of Swift's Adoption of Smalltalk Keyword... by skohan on Sunday June 14, 2020 @06:21PM (#23521870)
> 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.

Re:The Curious Case of Swift's Adoption of Smalltalk Keyword... by mpweiher on Monday June 15, 2020 @03:51AM (#23524904)
> 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.

Re:The Curious Case of Swift's Adoption of Smalltalk Keyword... by skohan on Monday June 15, 2020 @07:09AM (#23526094)
I don’t know it seems fine to me tbh but maybe it’s a matter of taste.

It seems pretty simple to me: everything before the colon is defining the argument name. If you have one label, it means the argument label is the same as the name of the parameter used inside the function. If you have two labels, then the first one is the argument label and the second one is the variable name.

You could also think of it that you’re always specifying the argument label and the variable name, and in the case where they’re identical you have a bit of shorthand to save some typing.

Maybe it seems weird to some people if it’s not familiar, but I got used to it pretty quickly after starting to use Swift, and it felt like a natural extension of the type system and optional handling in terms of the language giving me tools to cross-check things and bake sanity checks into the source code itself.

Re:The Curious Case of Swift's Adoption of Smalltalk Keyword... by mpweiher on Monday June 15, 2020 @11:10AM (#23528087)
> it’s a matter of taste.

Probably. ¯\_(ツ)_/¯

> everything before the colon is defining the argument name.

So the space binds more strongly than the colon. That seems..."unusual".

Re:The Curious Case of Swift's Adoption of Smalltalk Keyword... by renox on Tuesday June 16, 2020 @03:08PM (#23542861)
I have never used a language which allow this, is-it really useful? I don't think I have ever thought if only the external name was different than the internal name or used an 'alias' variable inside the function to 'hide' the external name..
Re:The Curious Case of Swift's Adoption of Smalltalk Keyword... by saurik on Sunday June 14, 2020 @02:34PM (#23520035)
> 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.

Re:The Curious Case of Swift's Adoption of Smalltalk Keyword... by DagAgren on Sunday June 14, 2020 @03:29PM (#23520585)
This was to more closely match the behaviour of Objective-C, and it has been removed as better ways of Objective-C interop were developed.
Re:The Curious Case of Swift's Adoption of Smalltalk Keyword... by CyberDildonics on Sunday June 14, 2020 @03:02PM (#23520331)
I think an IDE that would show the argument names and types when you mouse over a function would give a lot of the benefits of named arguments without putting the responsibility on the language to support them.

I think named arguments is an example of trying to solve issues at the language level, when the real problem is the information that is hidden from you while programming.

Re:The Curious Case of Swift's Adoption of Smalltalk Keyword... by choeger on Sunday June 14, 2020 @10:50AM (#23518033)
Unfortunately, named arguments lead to arbitrary-order arguments which then make partial application quite awkward.

Think: f(fst:x, snd:y), what is the type of f(snd:4)?

I think this can be implemented, but then f(3, fst:5) is either an error or counter-intuitive.

Re:The Curious Case of Swift's Adoption of Smalltalk Keyword... by skohan on Sunday June 14, 2020 @10:59AM (#23518111)
Swift's approach to this is pretty good. Arguments have a fixed order, and whether or not they are named at the call-site is explicitly decided by the author of the function signature.

In practice the order and identity of the arguments is quite clear in Swift.

Re:The Curious Case of Swift's Adoption of Smalltalk Keyword... by codetrotter on Sunday June 14, 2020 @11:09AM (#23518209)
As someone who kind of jumped into Swift coming from other languages, I still find this kind of stuff confusing.

Is there a good intro to Swift that goes through only what is unique/peculiar about Swift and explains that in a good way to someone that already knows how to program?

Re:The Curious Case of Swift's Adoption of Smalltalk Keyword... by bluk on Sunday June 14, 2020 @11:56AM (#23518674)
I don't know if you tried reading The Swift Programming Language book ( https://docs.swift.org/swift-book/LanguageGuide/TheBasics.ht... ). It's a fairly quick read and has brief explanations with simple examples. You can skip some sections if you have prior programming experience, but if you're confused about Swift's function arguments, you may want to skim even the basics since a few things like control flow (e.g. the switch statement) are unique compared to C/C++/Java/C#.
Re:The Curious Case of Swift's Adoption of Smalltalk Keyword... by andrenth on Sunday June 14, 2020 @11:05AM (#23518174)
OCaml supports this:

  # let f ~fst ~snd = fst + snd;;
  val f : fst:int -> snd:int -> int = <fun>
  # f ~snd:4;;
  - : fst:int -> int = <fun>
Re:The Curious Case of Swift's Adoption of Smalltalk Keyword... by Spivak on Sunday June 14, 2020 @11:09AM (#23518212)
I don’t think named arguments are as much a problem as function overloading and optional parameters for this.

Without overloading you could define the answer as

    g(x) { f(fst:x, snd:y) }
always which would make partial application somewhat ergonomic but makes allowing fst without snd horribly ugly when you have to pass in some spiritual null or _ to.

I think these ideas are fundamentally opposed and so I don’t think there’s a good way to have a nice syntax for both.

Re:The Curious Case of Swift's Adoption of Smalltalk Keyword... by tomp on Sunday June 14, 2020 @11:03AM (#23518151)
I generally dislike this kind of _implicit_ partial application anyways. I prefer Scala-like way of partial application with `_`:

    f(fst = _, snd = y)
Re:The Curious Case of Swift's Adoption of Smalltalk Keyword... by marcosdumay on Sunday June 14, 2020 @11:27AM (#23518361)
Yes, this can be implemented. And languages can trust the developers to not write stuff like f(3, fst:5). This is not a large scale pattern where people need help to refactor.

The one largest obstacle for partial application (at least of the Haskell style) is optional arguments. You just can not have both.

Re:The Curious Case of Swift's Adoption of Smalltalk Keyword... by sukilot on Sunday June 14, 2020 @12:55PM (#23519241)
I'd bet 4:1 odds that Haskell supports optional arguments with partial application using something like typeclass magic.
Re:The Curious Case of Swift's Adoption of Smalltalk Keyword... by marcosdumay on Monday June 15, 2020 @12:51AM (#23523906)
If you want optional arguments and partial application, you need some way to declare that the optional arguments are left blank. Haskell-style syntax has no such way.

But yeah, functors are all about building stuff like that. So there are similar things, just with a different syntax.