Why does a function call require the parameter name in Swift? - methods

I have this Function in a class:
func multiply(factor1:Int, factor2:Int) -> Int{
return factor1 * factor2
}
I try to call the function using this:
var multResult = calculator.multiply(9834, 2321)
The problem is that the compiler wants it to look more like this:
var multResult = calculator.multiply(9834, factor2: 2321)
Why does the first one cause an error?

Update for Swift 2.0: Now functions behave identically to methods, and for both, by default:
the first parameter has no external name; and
the other parameters have an external name identical to the internal name.
Other than that, the rules below still apply, except that the # shorthand syntax is now gone.
Here's a more general answer: functions behave differently when defined as true functions outside a class, and when defined as methods. Moreover, init methods have a special rule.
Functions
Suppose you define this:
func multiply1(f1: Double, f2: Double) -> Double {
return f1 * f2
}
Parameter names are here only local to the function, and cannot be used when calling the function:
multiply1(10.0, 10.0)
If you want to force using named parameters when calling the function, you can. Prefix each parameter declaration with its external name. Here, the external name of f1 is f1param, and for f2, we use the shorthand where we prefix it by # to indicate that the local name is to be used as the external name as well:
func multiply2(f1param f1: Double, #f2: Double) -> Double {
return f1 * f2
}
Then, named parameters must be used:
multiply2(f1param: 10.0, f2: 10.0)
Methods
Things are different for methods. By default, all but the first parameter are named, as you've discovered. Suppose we have this, and consider the multiply1 method:
class Calc {
func multiply1(f1: Double, f2: Double) -> Double {
return f1 * f2
}
func multiply2(f1param f1: Double, f2: Double) -> Double {
return f1 * f2
}
func multiply3(f1: Double, _ f2: Double) -> Double {
return f1 * f2
}
}
Then, you have to use the name of the second (and following, if any) parameters:
let calc = Calc()
calc.multiply1(1.0, f2: 10.0)
You can force to use a named param for the first argument by providing an external name for it, like for functions (or prefixing its local name with # if you want to use the same external name as its local name). Then, you have to use it:
calc.multiply2(f1param: 10.0, f2: 10.0)
Finally, you can declare an external name of _ for the other following arguments, indicating that you want to call your method without using named parameters, like this:
calc.multiply3(10.0, 10.0)
Interoperability note: If you prefix class Calc with the #objc annotation, then you can use it from Objective-C code, and it is equivalent to this declaration (look at parameter names):
#interface Calc
- (double)multiply1:(double)f1 f2:(double)f2;
- (double)multiply2WithF1param:(double)f1 f2:(double)f2;
- (double)multiply3:(double)f1 :(double)f2;
#end
Init Methods
The rule differs a bit for init methods, where all parameters have an external name by default. For instance, this works:
class Calc {
init(start: Int) {}
init(_ start: String) {}
}
let c1 = Calc(start: 6)
let c2 = Calc("6")
Here, you have to specify start: for the overload that accepts an Int, but you must omit it for the overload that accepts a String.
Interoperability note: this class would get exported to Objective-C like this:
#interface Calc
- (instancetype)initWithStart:(NSInteger)start __attribute__((objc_designated_initializer));
- (instancetype)init:(NSString *)start __attribute__((objc_designated_initializer));
#end
Closures
Assume you define a closure type like this:
typealias FancyFunction = (f1: Double, f2: Double) -> Double
The parameter names will behave very similar to those in a method. You will have to provide the names to the parameters when calling the closure unless you explicitly set the external name to _.
For example, executing the closure:
fund doSomethingInteresting(withFunction: FancyFunction) {
withFunction(f1: 1.0, f2: 3.0)
}
As a rule of thumb: even if you dislike them, you should probably try to keep using named parameters at least whenever two parameters have the same type, in order to disambiguate them. I'd also argue that it's good to also name at least all Int and Boolean parameters.

The parameter names in the function call are called keyword names, and they are trace their roots back to the Smalltalk language.
Classes and objects are often re-used from somewhere else, or form part of very large complex systems, and will not have active maintenance attention for long periods at a time.
Improving the clarity and legibility of the code is very important in these situations, as code often ends up as the only documentation, when developers are under deadline pressure.
Giving each parameter a descriptive keyword name allows maintainers to quickly see what the purpose of a function call by glancing at the function call, as opposed to delving deeper into the function code itself. It makes the implied meaning of the parameters explicit.
The latest language to adopt keyword names for parameters in function calls is Rust (link) - described as "a systems programming language that runs blazingly fast, prevents segfaults, and guarantees thread safety."
High uptime systems require greater code quality. Keyword names allow development and maintenance teams much more opportunity to avoid and to catch errors from sending the wrong parameter, or calling parameters out of order.
They can be wordy or terse, but Smalltalkers prefer wordy and descriptive to terse and meaningless. They can afford to be, because their IDE will do the bulk of such typing for them.

since you used calculator.multiply() in the example code I'm assuming this function is a method of the calculator object.
Swift inherits a lot of things from objective-c and this is one of them:
When in objective-c you would do (hypothetically):
[calculator multiply:#9834 factor2:#2321];
the equivalent in Swift is:
calculator.multiply(9834, factor2:2321);

Because your "multiply" function is a method, and like Objective-c, the parameters in methods are part of the name.
For example you can do this.
class Calculator {
func multiply(factor1:Int, factor2:Int) -> Int{
return factor1 * factor2
}
func multiply(factor1:Int, factor2:Int, factor3:Int) -> Int{
return factor1 * factor2 * factor3
}
}
Here there are two different methods, with different names, multiply(factor2) and multiply(factor2 factor3).
This rule only apply to methods, if you declare this like a functions outside of a class, then the function call don't require parameter name.

The reason is historical. This is how it worked in Smalltalk and it survived into its descendants. Squeak, Scratch, Blockly, Objective C and Swift.
The kiddy languages (Squeak, Scratch and Blockly) held to it, because beginning programmers tend to struggle with the arity and parameter order. That was the original reason why Smalltalk did it that way. I do not know why ObjC and Swift decided to adopt the convention, but they did.

A note about passing in a method as an argument that returns no value:
func refresh(obj:Obj, _ method: (Obj)->Void = setValue) {
method(element)
}
func setValue(obj:Obj){
obj.value = "someValue"
}
refresh(someObj,setValue)

Related

Two structs having same receiver function implementations, how to remove the duplications

I have two structs that are having same receiver function implementations:
type A struct {
name string
// other fields
}
type B struct {
name string
// other fields
}
type AA struct {
resource A
}
func (a *AA) Get() string {
// process something with a.resource.name
return a.resource.name
}
type BB struct {
resource B
}
func (b *BB) Get() string {
// process something with b.resource.name
return b.resource.name
}
type I interface {
Get() string
}
both structs AA and BB have Get function, in order to satisfy the interface I, this might be a dumb question, but I dont know how I can simplify them to remove the duplications of two Get functions, tried:
having a generic struct and embedded in A & B - cant do this due
to json serializations in the system I use.
embedded AA in BB and calling AA.Get - wont work since name is inside B instead of A
Combine AA and BB with both fields like resourceA and resourceB - this complicates the Get function, since then it needs to handle
create a non-receiver function and use it for both AA and BB - this can work but since there are quite some fields I need, not just name, so the function will end up with quite many parameters.
I cant stop feeling there should be an easier way, and also trying/googling a way to simplify it, but non of them seems to work, could someone point me some directions or hints?
much appreciated!
[UPDATE]
I'm trying to create a Kubernetes operator, which has some CRDs (Custom Resource Definitions), and since I create a generic controller that just take the CRDs and calling their functions (that's why I have interface), but I found I need to implement functions that are exactly the same, like GetName, GetObject, or some functions that manipulate the data and get back the results, and they're all the same across those CRD structs.
I've decided to just create a function that takes required parameters, and reuse the function across the structs, thanks for all the comments.
If you have other suggestions, please feel free to comment or suggest, thanks!

What is the difference between method call syntax `foo.method()` and UFCS `Foo::method(&foo)`?

Is there any difference in Rust between calling a method on a value, like this:
struct A { e: u32 }
impl A {
fn show(&self) {
println!("{}", self.e)
}
}
fn main() {
A { e: 0 }.show();
}
...and calling it on the type, like this:
fn main() {
A::show(&A { e: 0 })
}
Summary: The most important difference is that the universal function call syntax (UFCS) is more explicit than the method call syntax.
With UFCS there is basically no ambiguity what function you want to call (there is still a longer form of the UFCS for trait methods, but let's ignore that for now). The method call syntax, on the other hand, requires more work in the compiler to figure out which method to call and how to call it. This manifests in mostly two things:
Method resolution: figure out if the method is inherent (bound to the type, not a trait) or a trait method. And in the latter case, also figure out which trait it belongs to.
Figure out the correct receiver type (self) and potentially use type coercions to make the call work.
Receiver type coercions
Let's take a look at this example to understand the type coercions to the receiver type:
struct Foo;
impl Foo {
fn on_ref(&self) {}
fn on_mut_ref(&mut self) {}
fn on_value(self) {}
}
fn main() {
let reference = &Foo; // type `&Foo`
let mut_ref = &mut Foo; // type `&mut Foo`
let mut value = Foo; // type `Foo`
// ...
}
So we have three methods that take Foo, &Foo and &mut Foo receiver and we have three variables with those types. Let's try out all 9 combinations with each, method call syntax and UFCS.
UFCS
Foo::on_ref(reference);
//Foo::on_mut_ref(reference); error: mismatched types
//Foo::on_value(reference); error: mismatched types
//Foo::on_ref(mut_ref); error: mismatched types
Foo::on_mut_ref(mut_ref);
//Foo::on_value(mut_ref); error: mismatched types
//Foo::on_ref(value); error: mismatched types
//Foo::on_mut_ref(value); error: mismatched types
Foo::on_value(value);
As we can see, only the calls succeed where the types are correct. To make the other calls work we would have to manually add & or &mut or * in front of the argument. That's the standard behavior for all function arguments.
Method call syntax
reference.on_ref();
//reference.on_mut_ref(); error: cannot borrow `*reference` as mutable
//reference.on_value(); error: cannot move out of `*reference`
mut_ref.on_ref();
mut_ref.on_mut_ref();
//mut_ref.on_value(); error: cannot move out of `*mut_ref`
value.on_ref();
value.on_mut_ref();
value.on_value();
Only three of the method calls lead to an error while the others succeed. Here, the compiler automatically inserts deref (dereferencing) or autoref (adding a reference) coercions to make the call work. Also note that the three errors are not "type mismatch" errors: the compiler already tried to adjust the type correctly, but this lead to other errors.
There are some additional coercions:
Unsize coercions, described by the Unsize trait. Allows you to call slice methods on arrays and to coerce types into trait objects of traits they implement.
Advanced deref coercions via the Deref trait. This allows you to call slice methods on Vec, for example.
Method resolution: figuring out what method to call
When writing lhs.method_name(), then the method method_name could be an inherent method of the type of lhs or it could belong to a trait that's in scope (imported). The compiler has to figure out which one to call and has a number of rules for this. When getting into the details, these rules are actually really complex and can lead to some surprising behavior. Luckily, most programmers will never have to deal with that and it "just works" most of the time.
To give a coarse overview how it works, the compiler tries the following things in order, using the first method that is found.
Is there an inherent method with the name method_name where the receiver type fits exactly (does not need coercions)?
Is there a trait method with the name method_name where the receiver type fits exactly (does not need coercions)?
Is there an inherent method with the name method_name? (type coercions will be performed)
Is there a trait method with the name method_name? (type coercions will be performed)
(Again, note that this is still a simplification. Different type of coercions are preferred over others, for example.)
This shows one rule that most programmers know: inherent methods have a higher priority than trait methods. But a bit unknown is the fact that whether or not the receiver type fits perfectly is a more important factor. There is a quiz that nicely demonstrates this: Rust Quiz #23. More details on the exact method resolution algorithm can be found in this StackOverflow answer.
This set of rules can actually make a bunch of changes to an API to be breaking changes. We currently have to deal with that in the attempt to add an IntoIterator impl for arrays.
Another – minor and probably very obvious – difference is that for the method call syntax, the type name does not have to be imported.
Apart from that it's worth pointing out what is not different about the two syntaxes:
Runtime behavior: no difference whatsoever.
Performance: the method call syntax is "converted" (desugared) into basically the UFCS pretty early inside the compiler, meaning that there aren't any performance differences either.

Function parameter error - Missing Argument Label Anomaly - SWIFT

I have a strange issue (which I can overcome however I would like to get a proper understanding of my error).
I have a small random number generator function which I use often:
func ranNum(low: Int, high:Int) -> UInt32 {
var result = arc4random_uniform(UInt32((high+1)-low)) + low
return result
}
When I use this in XCode playgrounds it works just fine if I pass in something like:
ranNum(1, 10)
However, in a regular Swift file it generates the error message : Missing argument label 'hi:' in call. Now I can overcome this by calling the function this way:
ranNum(1, hi:10)
Apart from it just being a little harder to read, it just isn't making sense why it works in Playgrounds but also why it requires only the 2nd argument label and not both. Any help as to what I am not understandinh would be greatly appreciated.
That's called external parameter name, and by default:
global functions: don't have implicit external names
class/struct methods: external names are automatically defined for all parameters after the first
initializers: external names are automatically defined for all parameters
If not explicitly specified, external names take the same name as the local parameter.
You can override that by prefixing a local parameter name with _. In your case:
func ranNum(low: Int, _ high:Int) -> UInt32 {
...
}
You mentioned that in playground calling the function works without any external parameter name - I may argue that:
in playground you have that function as a global function
in other tests, that function is a class/struct method
Am I right?

What does it mean to pass `_` (i.e., underscore) as the sole parameter to a Dart language function?

I'm learning Dart and see the following idiom a lot:
someFuture.then((_) => someFunc());
I have also seen code like:
someOtherFuture.then(() => someOtherFunc());
Is there a functional difference between these two examples?
A.k.a., What does passing _ as a parameter to a Dart function do?
This is particularly confusing given Dart's use of _ as a prefix for declaring private functions.
It's a variable named _ typically because you plan to not use it and throw it away. For example you can use the name x or foo instead.
The difference between (_) and () is simple in that one function takes an argument and the other doesn't.
DON’T use a leading underscore for identifiers that aren’t private.
Exception: An unused parameter can be named _, __, ___, etc. This
happens in things like callbacks where you are passed a value but you
don’t need to use it. Giving it a name that consists solely of
underscores is the idiomatic way to indicate the value isn’t used.
https://dart.dev/guides/language/effective-dart/style
An underscore (_) is usually an indication that you will not be using this parameter within the block. This is just a neat way to write code.
Let's say I've a method with two parameters useful and useless and I'm not using useless in the code block:
void method(int useful, int useless) {
print(useful);
}
Since useless variable won't be used, I should rather write the above code as:
void method(int useful, int _) { // 'useless' is replaced with '_'
print(useful);
}
From the Dart Doc - PREFER using _, __, etc. for unused callback parameters.
Sometimes the type signature of a callback function requires a
parameter, but the callback implementation doesn't use the
parameter. In this case, it's idiomatic to name the unused parameter
_. If the function has multiple unused parameters, use additional
underscores to avoid name collisions: __, ___, etc.
futureOfVoid.then((_) {
print('Operation complete.');
});
This guideline is only for functions that are both anonymous and
local. These functions are usually used immediately in a context
where it's clear what the unused parameter represents. In contrast,
top-level functions and method declarations don't have that context,
so their parameters must be named so that it's clear what each
parameter is for, even if it isn't used.
Copy paste the following code in DartPad and hit Run -
void main() {
Future.delayed(Duration(seconds: 1), () {
print("No argument Anonymous function");
});
funcReturnsInteger().then((_) {
print("Single argument Anonymous function " +
"stating not interested in using argument " +
"but can be accessed like this -> $_");
});
}
Future<int> funcReturnsInteger() async {
return 100;
}
That expression is similar to "callbacks" in node.js, the expression have relation to async task.
First remember that => expr expression is shorthand for {return *expr*}, now in someFuture.then((_) => someFunc()), someFuture is a variable of type Future, and this keeps your async task, with the .then method you tell what to do with your async task (once completed), and args in this method you put the callback ((response) => doSomethingWith(response)).
You learn more at Future-Based APIs and Functions in Dart. Thanks
Very common use, is when we need to push a new route with Navigator but the context variable in the builder is not going to be used:
// context is going to be used
Navigator.of(context).push(MaterialPageRoute(
builder: (context) => NewPage(),
));
// context is NOT going to be used
Navigator.of(context).push(MaterialPageRoute(
builder: (_) => NewPage(),
));
I think what people are confusing here is that many think the _ in
someFuture.then((_) => someFunc());
is a parameter provided to the callback function which is wrong, its actually a parameter passed back from the function that you can give a name that you want (except reserved keywords of course), in this case its an underscore to show that the parameter will not be used. otherwise, you could do something like in example given above:((response) => doSomethingWith(response))

Liftable for function literal

Is there a way to make a Liftable for a functional literal (with 2.11)? If I have
case class Validator[T](predicate: T => Boolean)
val predicate = (s: String) => s.startsWith("Hi")
then I want to be able to quasiquote predicate too:
q"new Validator($predicate)"
I hoped to magically create a Liftable with an underscore. But that was a little too optimistic:
implicit def liftPredicate[T: Liftable](f: T => Boolean) =
Liftable[T => Boolean]{ f => q"$f(_)" }
I couldn't figure out from looking at StandardLiftables how I could solve this one.
Another way of looking at it:
Say I want to create instances from the following class at compile time with a macro:
abstract class ClassWithValidation {
val predicate: String => Boolean
def validate(s: String) = predicate(s)
}
and I retrieve a functional literal from somewhere else as a variable value:
val predicate = (s: String) => s.startsWith("Hi")
Then I want to simply quasiquote that variable into the construction:
q"""new ClassWithValidation {
val predicate = $predicate
// other stuff...
}"""
But it gives me this error:
Error:(46, 28) Can't unquote String => Boolean, consider providing an
implicit instance of Liftable[String => Boolean]
Normally I can just make such implicit Liftable for a custom type. But I haven't found a way doing the same for a functional literal. Is there a way to do this or do I need to look at it another way?
From what I understand, you're trying to go from a function to an abstract syntax tree that represents its source code (so that it can be spliced into a macro expansion). This is a frequent thing that people request (e.g. it comes up often in DSLs), but there's no straightforward way of achieving that in our current macro system.
What you can do about this at the moment is to save the AST explicitly when declaring a function and then load and use it in your macro. The most convenient way of doing this is via another macro: https://gist.github.com/xeno-by/4542402. One could also imagine writing a macro annotation that would work along the same lines.
In Project Palladium, there is a plan to save typechecked trees for every program being compiled. This means that there will most likely be a straightforward API, e.g. treeOf(predicate) that would automatically return abstract syntax tree comprising the source of the predicate. But that's definitely not something set in stone - we'll see how it goes, and I'll report back on the progress during this year's ScalaDays.

Resources