I'm looking at this Named Arguments
example in Scala in Depth:
scala> class Parent {
| def foo(bar: Int = 1, baz: Int = 2): Int = bar + baz
| }
defined class Parent
scala> class Child extends Parent {
| override def foo(baz: Int = 3, bar: Int = 4): Int = super.foo(baz, bar)
| }
defined class Child
scala> val p = new Parent
p: Parent = Parent@6100756c
scala> p.foo()
res1: Int = 3
scala> val x = new Child
x: Child = Child@70605759
Calling x.foo()
evaluates to 7 since Child#foo
has default arguments of 3 and 4.
scala> x.foo()
res3: Int = 7
Instantiate a new Child
at run-time, but Parent
at compile-time. This may or may not be correct
scala> val y: Parent = new Child
y: Parent = Child@540b6fd1
Calling x.foo()
evaluates to 7 since Child#foo
has default arguments of 3 and 4.
scala> y.foo()
res5: Int = 7
Calling x.foo()
evaluates to 4 since Child#foo
has a default baz
argument of 3.
scala> x.foo(bar = 1)
res6: Int = 4
However, I don't understand why y.foo(bar = 1)
returns 5. I would've expected Child#foo
to be evaluated since y
is a Child
type. Passing in a bar
of 1 to foo
means that baz
's default is 3. And so it should produce 4. But my understanding is of course incorrect.
scala> y.foo(bar = 1)
res7: Int = 5
Named Arguments allow you to call a function without passing the arguments in the order as they are defined in the function. In a normal function call, we need to pass the arguments with reference to the function's parameters.
In Scala when arguments pass through call-by-value function it compute the passed-in expression's or arguments value once before calling the function . But a call-by-Name function in Scala calls the expression and recompute the passed-in expression's value every time it get accessed inside the function.
One function can be passed to another function as a function argument (i.e., a function input parameter). The definition of the function that can be passed in as defined with syntax that looks like this: "f: Int > Int" , or this: "callback: () > Unit" .
Keyword arguments (or named arguments) are values that, when passed into a function, are identifiable by specific parameter names. A keyword argument is preceded by a parameter and the assignment operator, = . Keyword arguments can be likened to dictionaries in that they map a value to a keyword.
There are 2 reasons:
scala
compiler creates helper methods for default parameters:
val p = new Parent()
val c = new Child()
p.`foo$default$1`
// Int = 1
p.`foo$default$2`
// Int = 2
c.`foo$default$1`
// Int = 3
c.`foo$default$2`
// Int = 4
This is why you could use not only constants, but also fields and methods for default parameters:
def test(i: Int = util.Random.nextInt) = i
test()
// Int = -1102682999
test()
// Int = -1994652923
There are no named parameters after compilation - all parameters are positional.
So since bar
is second parameter of Child#foo
this code:
c.foo(bar = 1)
// Int = 4
is translated by compiler to this:
c.foo(c.`foo$default$1`, /*bar = */1)
// Int = 4
But since bar
is first parameter of Parent#foo
this code:
val tmp: Parent = c
tmp.foo(bar = 1)
// Int = 5
is translated to this:
tmp.foo(/*bar = */1, tmp.`foo$default$2`)
// Int = 5
As we already know c.foo$default$2
returns 4
, so c.foo(1, 4)
returns 5.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With