As I understand it,
given a:T …
is just a way to define a value of type T which will be used as default value when a T is expected.
def f(x:Int)(using y:T)
is very similar in intent to
which is to provide a default value if none is provided at call site.
summon[T] designates this default value (
I propose to use the word
default T ... or
default a:T ... replaces
given a:T … to define a default value.
def f(x:Int)(default y:T) replaces
def f(x:Int)(using y:T) telling that a default T should be used if no value is given for y at call site.
This could allow the following construct:
def f(x:Int)(default y:T=b)
meaning that if the compiler can’t find a
default T at call site, it uses
summon[T] to reference this default value.
Less keywords, and a clarification of the intent, which is to provide a default value.
For what it’s worth I agree with you this is cleaner. And “default” is a noun.
Because I missed the historical debate I am also unsure why we wouldn’t use “default” in place of both “given” and “using”. Ultimately, on one side (given) you are declaring a default, on the other (using) you are consuming a default. Both are very much connected and as a beginner I would prefer having them aligned with the same keyword.
This is the same kind of reasoning as declaring a case class with keyword “case”, and then pattern matching with same keyword “case”: semantic relation is made explicit and it is easier to relate to it.
using's to me are more useful for putting constraints to functions/classes. If you want default values, just use default parameters? Using another keyword
default seems the same as going back to scala 2’s
" using 's to me are more useful for putting constraints to functions/classes"
Not really. It’s to create a new value, not a new type. But you’re right in the sense that we often do this by instantiating a (subclass of) an abstract class.
“If you want default values, just use default parameters?”
The purpose of
given is the same as a default parameter: to have a default value when none is written at call site. The difference, and the strength, is that the compiler looks for this value in the call site environment.
def f(i:Int)(t:T=default[T]) is not the same as
def f(i:Int)(default t:T). In the first case, the value default[T] is searched in the environment of the definition of f.
“Using another keyword default seems the same as going back to scala 2’s implicit?”
implicit was far more general (conversions, extension methods), and it’s a good thing to distinguish these differents uses with different words.
I think that using the word default would make this concept quite simple and clear; it would not necessitate to understand why we
default[T] is just the name of this default value of type
T, created with
default T ... and used by default with a parameter of the form
default x:T (or
default T when all that counts is the existence of such value).
Implicits are used for so much more than just default parameters. They’re used for typeclasses and providing evidence that one type equals another or that an object is valid for some operation. Not all givens take the form
given foo: Foo = ???
default would make it seem like that’s the only thing they’re supposed to be used for. I’ve never used them for default arguments, and I bet a ton of other people haven’t either. It doesn’t make sense to change the keyword.
For what it’s worth, the places in our codebase where someone has tried to use implicits as default parameters have generally become very hard to read, very quickly.
I wouldn’t go quite as far as to call this an anti-pattern, but I’ve never seen it used in ways that have improved the situation.
Not really. It’s to create a new value, not a new type
Well no but actually yes. With just an implicit conversion and given values we can apply constraints to types.
Here is an example of test a I did.
//Uses an implicit constraint behavior
def printThisNumber(number: Constrained[Double, Positive]): Unit = println(number)
printThisNumber(-3) //Runime error
If inlined, the error is compiletime.
And as said above, implicits are much more than a default argument.