I think it’s unlikely that a type would want to support both static and dynamic callable. With that in mind, I think separate attributes make the most sense. If somebody really wanted to expose both static and dynamic calls they could just add both @callable and @dynamicCallable to the type.
I’m not able to work on implementation but I would be happy to collaborate with anyone interested this feature. I’ll spend some time thinking about this (especially motivation) and start a pitch thread in the next week or two.
I noticed that this proposal does not support both positional and keyword arguments in the same call. Some dynamic languages (such as Ruby) do support this. Is there a reason this proposal doesn’t support mixing them or was that an oversight?
The implication (or at least my reading) of para 3 under ‘Ambiguity resolution’ (e: combined with some comments upthread from Lukas + Chris) is that it does support that, that if there are any keywords given then the ‘keywords’ form is used and positional arguments come in with empty keyword strings.
(This doesn’t support compile-time checking of Ruby’s “positional arguments must precede keyword arguments” but that is fairly baroque…)
The current version Swift seems to trap when initializing a type conforming ExpressibleByDictionaryLiteral with multiple equal keys which would be required to use a dynamicCall with multiple arguments (with an empty string key) and keyword arguments.
Similarly, if a type implements both the keywordArguments and the arguments form, the compiler will use the arguments form for call sites that lack keyword arguments, and use the more general form for call sites that do have keyword arguments.
It isn’t clear from this that keyword arguments are allowed for some, but not all arguments. I certainly don’t see anything that indicates that the positional arguments come with any specific keyword string (such as empty). I think this needs to be spelled out in more detail if it is supported, or clearly stated as a limitation if it is not supported.
Well, the @dynamicCallable feature captures a variable amount of arguments and provides them as one argument to a function, just like the existing ... syntax. So we’d have two very similar features next to each other.
Obviously, variadics at the moment cannot capture keyword argument labels. But when there are no keyword arguments, they can already perfectly package the entire list, right? Or is there something I missed?
That’s why I thought adding keyword support to our existing variadics feature might be simpler and also more powerful than introducing a new feature which is just available for structs/classes/etc. but not available for normal functions.
If that is not the case or if the added flexibility is not needed, then so be it.
@rxwei makes an interesting suggestion, although I do believe Swift naming guidelines elide ‘with’ for parameter labels.
I’m on the fence about whether the function itself should be a verb (“dynamically call”) or simply a noun (“dynamic call”); if we’re going to call the attribute @dynamicCallable and not @dynamicallyCallable, I think on balance I’d favor the original.
You can see it in the detailed write-up of how the guidelines are applied in SE-0005 and SE-0006. For example:
In migrating the standard library from Swift 2 to Swift 3 based on the naming guidelines, joinWithSeparator(_:) becomes joined(separator:).
In translating Objective-C names, fillWithBlendMode(_:alpha:) becomes fill(blendMode:alpha:) (and many other examples).
It’s impossible to say whether a dynamic call is more likely to be mutating or not, nor do I think it’s wise to associate that consideration with the name of the underlying method here. At best, the name could be ambiguous, but ultimately I don’t think that the consideration is applicable since a dynamic call self-evidently rules out any way to know for sure.
I think withArguments here conforms with the guidelines. The obj -> swift grand renaming is not part of the guidelines as far as I know. At least I do not see evidence of this in the guidelines.
[Full bikeshed mode enabled]
Shouldn’t it be called withParameters since we are defining the the kind of parameters that the function we are calling can take? I guess it is both parameters (the key) and arguments (the value to the key).
I do think that named could be dropped as Method describes the name.
IMO, withArguments conforms to the official guidelines. The guidelines also have an example using with:.
I don’t have a strong opinion about named:. On one hand, I agree that dropping would make it simpler. OTOH, given that users will implement this method for syntactic sugar someCallableStuff(), there’s no problem with this method being verbose for clarity.
Every function has a function name, which describes the task that the function performs. To use a function, you “call” that function with its name and pass it input values (known as arguments) that match the types of the function’s parameters. A function’s arguments must always be provided in the same order as the function’s parameter list.
It falls under the guideline of “omit useless words”—the Objective-C to Swift renaming was conducted to adopt Swift API naming guidelines and demonstrates how those guidelines are intended to be applied. See SE-0005/6 for more.
Yes, “with:” conforms to the guidelines because, where a label is necessary, it cannot be omitted as then there would be no label. However, where there are other words in the label, “with” is elided, as the parentheses surrounding the arguments imply “with.” See SE-0005/6.