In Scala (2.7.7final), the Predef.println method is defined as having the following signature:
def println (x : Any) : Unit
How come, then that the following works:
scala> println(1,2)
(1,2)
Does the compiler automatically convert a comma-separated list of arguments into a Tuple? By what magic? Is there an implicit conversion going on here, and if so, which one?
Yes, the compiler will attempt to convert comma separated arguments into tuples, if there are no appropriate multi-argument methods and a single appropriate one-argument method. It's not an implicit conversion, just a compiler hack. This is a somewhat controversial feature, and will probably undergo changes going forward, as work is planned around unifying the treatment of tuples and argument lists.
Related
Let's say I have
public enum MyEnum {
..
}
When I invoke
java.util.Arrays.asList(MyEnum.values)
I get back
java.util.List[Array[MyEnum]]
instead of
java.util.List[MyEnum]
Why is that?
Am I missing some JavaConverter magic?
The signature of the java method is
static <T> List<T> asList(T... a)
, i.e. it takes variable number of arguments. You are passing a single array, so you are getting a list with a single array.
If you want to pass each element of the array as a separate argument, use the _*-annotation:
java.util.Arrays.asList(java.util.concurrent.TimeUnit.values: _*)
If you want a Scala List instead, use toList directly on array:
java.util.concurrent.TimeUnit.values.toList
Thanks to Andrey Tyukin for pointing out the correct answer already.
I'm just copy-pasting the scala documentation for Ascription for completeness
Ascription
Type ascription is often confused with type annotation, as the syntax in Scala is identical. The following are examples of
ascription:
Nil: List[String]
Set(values: _*)
"Daniel": AnyRef
Ascription is basically just an up-cast performed at compile-time for
the sake of the type checker. Its use is not common, but it does
happen on occasion. The most often seen case of ascription is
invoking a varargs method with a single Seq parameter. This is done
by ascribing the _* type (as in the second example above).
Ascription follows the type annotation conventions; a space follows
the colon
Why call to method whose all parameters has default values is not the same than calling a method without parameter in scala?
Example:
scala> def a(a:Int=1)=print(a)
a: (a: Int)Unit
scala> def b=print(1)
b: Unit
scala> a
<console>:13: error: missing argument list for method a
Unapplied methods are only converted to functions when a function type
is expected.
You can make this conversion explicit by writing `a _` or `a(_)`
instead of `a`.
a
^
scala> b
1
However
scala>a()
1
works ok.
Shouldn't be the same call?
Scala enable Arity-0(a) method to omit parentheses.
https://docs.scala-lang.org/style/method-invocation.html#arity-0
I can think of at least one problem caused by not needing to write parenthesis. Consider the following:
val xs = List(1, 2, 3, 4)
def myFunc(x: Int = 42) = 2 * x
val ys = xs.map(myFunc)
Eta expansion is happening in my example, method is lifted into function. But if it was possible to invoke function with default parameters this way, syntax would be ambigous at least in this case. (I know that here invocation would lead to wrong argument type of map function, so in theory it is possible to resolve this ambiguity here, but it would mean that type of expression would have impact on the syntax interpretation, which is handled before type-checking in any language i know)
If you don't add a parenthesis after a, that will have several meanings.
a(): Unit
a(_): Int => Unit
Which one do you mean? Hence it force you to add parenthesis.
In Scala, a method can have zero or more parameter lists, each of which has zero or more parameters. If you want to call a method, you have to supply matching argument lists with matching arguments to the parameters and parameter lists.
In your case, you defined the method with one parameter list, ergo you need to call it with one argument list.
Shouldn't be the same call?
No, they are not the same. The first call has zero argument lists, the second call has one argument list. That's different.
There are some cases where Scala lets you call methods with a single empty parameter list by supplying no argument lists. The reason for this is simple convenience: you want to call Java getters (which are defined with an empty parameter list) the same way as Scala getters (which are defined without a parameter list). But, this doesn't work in general.
Consider the following type:
case class Subscriber(books: List[String])
And its instance wrapped in an option:
val s = Option(Subscriber(List("one", "two", "three")))
And an attempt to println all books for a subscriber:
s.flatMap(_.books).foreach(println(_))
This fails, due to:
Error: type mismatch;
found : List[String]
required: Option[?]
result.flatMap(_.books).foreach(println(_))
^
This is kind of expected, because flatMap must return types compatible to its source object and one can easily avoid this error by doing:
s.toList.flatMap(_.books).foreach(println(_))
I could also avoid flatMap, but its not the point.
But isn't there some smart method of achieving this without explicit toList conversion? Intuitively, None and List.empty have a lot in common. And during compilation of s.flatMap, s is implicitly converted to Traversable.
Something in scalaz, maybe?
I think smart implementation of flatamap is a bit missleading.
Such an implementation, as flatmap is well defined, would break the monadic behavior one expects when using flatmap and be in fact broken.
The problem with the smart method is
How should the compiler know what kind of type to use.
How should it be possible to infer if you wanted a List[_] or and Option[_] as a result?
What to do with other types, unknown types and what kind of conversion to apply on them ?
You could achieve the same result you would with the .list in that way , because for given example types don't matter (except you are aiming for a list of Units) at all as there is just output as a side effect:
s foreach ( _.books foreach println )
A direction to go, might be an implicit conversion using structural types but you would get a performance penalty.
The smarter way to do that would be is by using map.
val s = Option(Subscriber(List("one", "two", "three")))
s.map(_.books.map(println))
foreach has side effects while map doesn't
I am new to Scala, and when I look at different projects, I see two styles for dealing with implicit arguments
scala]]>def sum[A](xs:List[A])(implicit m:Monoid[A]): A = xs.foldLeft(m.mzero)(m.mappend)
sum:[A](xs:List[A])(implicit m:Monoid[A])A
and
scala]]>def sum[A:Monoid](xs:List[A]): A ={
val m = implicitly[Monoid[A]]
xs.foldLeft(m.mzero)(m.mappend)
}
sum:[A](xs:List[A])(implicit evidence$1:Monoid[A])A
Based off the type of both functions, they match. Is there a difference between the two? Why would you want to use implicitly over implicit arguments? In this simple example, it feels more verbose.
When I run the above in the REPL with something that doesn't have an implicit, I get the following errors
with implicit param
<console>:11: error: could not find implicit value for parameter m: Monoid[String]
and
with implicitly and a: Monoid
<console>:11: error: could not find implicit value for evidence parameter of type Monoid[String]
In some circumstances, the implicit formal parameter is not directly used in the body of the method that takes it as an argument. Rather, it simply becomes an implicit val to be passed on to another method that requires an implicit parameter of the same (or a compatible) type. In that case, not having the overt implicit parameter list is convenient.
In other cases, the context bound notation, which is strictly syntactic sugar for an overt implicit parameter, is considered aesthetically desirable and even though the actual parameter is needed and hence the implicitly method must be used to get it is considered preferable.
Given that there is no semantic difference between the two, the choice is predicated on fairly subjective criteria.
Do whichever you like. Lastly note that changing from one to the other will not break any code nor would require recompilation (though I don't know if SBT is discriminting enough to forgo re-compiling code that can see the changed definition).
The following Scala code works correctly:
val str1 = "hallo"
val str2 = "huhu"
val zipped: IndexedSeq[(Char, Char)] = str1.zip(str2)
However if I import the implicit method
implicit def stringToNode(str: String): xml.Node = new xml.Text(str)
then the Scala (2.10) compiler shows an error: value zip is not a member of String
It seems that the presence of stringToNode somehow blocks the implicit conversion of str1 and str2 to WrappedString. Why? And is there a way to modify stringToNode such that zip works but stringToNode is still used when I call a function that requires a Node argument with a String?
You have ambiguous implicits here. Both StringOps and xml.Node have the zip-method, therefore the implicit conversion is ambiguous and cannot be resolved. I don't know why it doesn't give a better error message.
Here are some links to back it up:
http://www.scala-lang.org/api/current/index.html#scala.collection.immutable.StringOps
and
http://www.scala-lang.org/api/current/index.html#scala.xml.Node
edit: it was StringOps, not WrappedString, changed the links :) Have a look at Predef: http://www.scala-lang.org/api/current/index.html#scala.Predef$
to see predefined implicits in Scala.
I would avoid using implicits in this case. You want 2 different implicit conversions which both provide a method of the same name (zip). I don't think this is possible. Also, if you import xml.Text, you can convert with just Text(str) which should be concise enough for anyone. If you must have this implicit conversion to xml.Node, I would pack the implicit def into an object and then import it only in the places where you need it to make your code readable and to, possibly, avoid conflicts where you also need to zip strings. But basically, I would very much avoid using implicits just to make convenient conversions.
Like #Felix wrote, it is generally a bad idea to define implicit conversions between similar data types, like the one you used. Doing that weakens type system, leads to ambiguities like you encountered and may produce extremely unclear ("magic") code which is very hard to analyze and debug.
Implicit conversions in Scala are mostly used to define lightweight, short-lived wrappers in order to enrich API of wrapped type. Implicit conversion that converts String into WrappedString falls into that category.
Twitter's Effective Scala has a section about this issue.