There is a note in Cay Horstmann's book "Scala for the Impatient" about the apply method:
Occasionally, the () notation conflicts with another Scala feature:
implicit parameters. For example, the expression "Bonjour".sorted(3)
yields an error because the sorted method can optionally be called
with an ordering, but 3 is not a valid ordering.
The solution is to assign "Bonjour".sorted to a variable and call apply on it, for example:
val result = "Bonjour".sorted
result(3)
Or call apply explicitly:
"Bonjour".sorted.apply(3)
But why this doesn't work and produces a compile error:
("Bonjour".sorted)(3)
The sorted method returns a String, which can be imlicitly converted to a StringOps and parentheses are used to wrap the string expression.
Why compiler doesn't accept to call the apply method of a StringOps?
You can use -Xprint:parser to see that the parens are discarded early:
scala> implicit class x(val s: String) { def scaled(implicit i: Int) = s * i }
defined class x
scala> "hi".scaled(5)
res0: String = hihihihihi
scala> { implicit val n: Int = 5 ; "hi".scaled }
res1: String = hihihihihi
scala> "hi".scaled(5)(3)
res2: Char = i
scala> { implicit val n: Int = 5 ; ("hi".scaled)(3) }
res3: String = hihihi
scala> :se -Xprint:parser
scala> { implicit val n: Int = 5 ; ("hi".scaled)(3) }
[[syntax trees at end of parser]] // <console>
package $line8 {
object $read extends scala.AnyRef {
def <init>() = {
super.<init>();
()
};
object $iw extends scala.AnyRef {
def <init>() = {
super.<init>();
()
};
import $line3.$read.$iw.$iw.x;
object $iw extends scala.AnyRef {
def <init>() = {
super.<init>();
()
};
val res4 = {
implicit val n: Int = 5;
"hi".scaled(3)
}
}
}
}
}
res4: String = hihihi
scala>
The extra parens do nothing. The compiler just sees an application expr(args). Because it's an application, you don't get "implicit application" conversion.
In any case, the meaning of scaled, a method, depends on the expected type.
The reason we expect the extra parens to make a difference is that parens override precedence of operators. But (x) is just x.
Possibly the spec is actually clear about this:
e(args) requires that e be applicable to the args. In particular, the args are typechecked according to the parameter types of e.
e(args) is taken as e.apply(args) if e is a value, but scaled is a method.
You're hoping for "implicit application" to insert the implicit args, but that only applies when e is not already applied. Or that (e)(args) could be taken as (e(_))(args), that is, (x => e(x))(arg).
When written as e.apply(arg), the e is not an application like e(arg), so you benefit from conversions like implicit application.
Related
As far as i understand, #specialized annotation should generate some unboxed code for every primitive type i mentioned, but this doesn't work:
scala> def aaa[#specialized(Int, Double, Float, Long) T] = (5.0).doubleValue.asInstanceOf[T]
aaa: [T]=> T
scala> aaa[Int]
unrecoverable error (inside interpreter/compiler)
This compiles:
scala> def aaa[#specialized(Int, Double, Float, Long) T](a: T) = (5.0).doubleValue.asInstanceOf[T]
aaa: [T]=> T
scala> aaa[Int](0)
ClassCastException
But it still uses boxed type for asInstanceOf[T]. This obviously works:
scala> (5.0).asInstanceOf[Int]
res28: Int = 5
UPDATE:
Type erasure and answers like that Writing a generic cast function Scala has nothing to do with my problem. Type erasure just preventing compiler from adding typecast byte-code operation for generics, but eventually it will be added - see ClassCastException (generated by this op) in my REPL
The problem was in Scala REPL - #specialized doesn't work there. Compiling def aaa[#specialized(Int) T] = (5.0).asInstanceOf[T] with scalac gives:
public <T> T aaa();
Code:
0: ldc2_w #15 // double 5.0d
3: invokestatic #22 // Method scala/runtime/BoxesRunTime
.boxToDouble:(D)Ljava/lang/Double;
6: areturn
public int aaa$mIc$sp();
Code:
0: ldc2_w #15 // double 5.0d
3: d2i
4: ireturn
d2i is exactly what i was expecting. And of course everything works fine with scalac (so I don't need pattern matching for every possible type). So it's just the issue with interpreter.
The method is specialized, but under separate compilation (i.e., different lines), the specialized method isn't invoked.
In the following, b.B.f works, c.B.f is broken.
$ scala -Xprint:typer,cleanup
scala> :pa -raw
// Entering paste mode (ctrl-D to finish)
package a { object A { def aaa[#specialized(Int) T] = (5.0).doubleValue.asInstanceOf[T] }}
package b { object B { def f = a.A.aaa[Int] }}
// Exiting paste mode, now interpreting.
[[syntax trees at end of typer]] // <pastie>
package <empty> {
package a {
object A extends scala.AnyRef {
def <init>(): a.A.type = {
A.super.<init>();
()
};
def aaa[#specialized(scala.Int) T]: T = scala.this.Predef.double2Double(5.0).doubleValue().asInstanceOf[T]
}
};
package b {
object B extends scala.AnyRef {
def <init>(): b.B.type = {
B.super.<init>();
()
};
def f: Int = a.A.aaa[Int]
}
}
}
[[syntax trees at end of cleanup]] // <pastie>
package <empty> {
package a {
object A extends Object {
def aaa(): Object = scala.Double.box(scala.this.Predef.double2Double(5.0).doubleValue());
<specialized> def aaa$mIc$sp(): Int = scala.this.Predef.double2Double(5.0).doubleValue().toInt();
def <init>(): a.A.type = {
A.super.<init>();
()
}
}
};
package b {
object B extends Object {
def f(): Int = a.A.aaa$mIc$sp();
def <init>(): b.B.type = {
B.super.<init>();
()
}
}
}
}
scala> :pa -raw
// Entering paste mode (ctrl-D to finish)
package c { object B { def f = a.A.aaa[Int] }}
// Exiting paste mode, now interpreting.
[[syntax trees at end of typer]] // <pastie>
package c {
object B extends scala.AnyRef {
def <init>(): c.B.type = {
B.super.<init>();
()
};
def f: Int = a.A.aaa[Int]
}
}
[[syntax trees at end of cleanup]] // <pastie>
package c {
object B extends Object {
def f(): Int = scala.Int.unbox(a.A.aaa());
def <init>(): c.B.type = {
B.super.<init>();
()
}
}
}
Perhaps you just need a more recent compiler? here's what I get with 2.11.2:
Welcome to Scala version 2.11.2 (Java HotSpot(TM) 64-Bit Server VM, Java 1.7.0_72).
Type in expressions to have them evaluated.
Type :help for more information.
scala> def aaa[#specialized(Int, Double, Float, Long) T] = (5.0).doubleValue.asInstanceOf[T]
aaa: [T]=> T
scala> aaa[Int]
java.lang.ClassCastException: java.lang.Double cannot be cast to java.lang.Integer
at scala.runtime.BoxesRunTime.unboxToInt(BoxesRunTime.java:105)
... 33 elided
scala> aaa[Float]
java.lang.ClassCastException: java.lang.Double cannot be cast to java.lang.Float
at scala.runtime.BoxesRunTime.unboxToFloat(BoxesRunTime.java:113)
... 33 elided
scala> aaa[Double]
res2: Double = 5.0
scala> 5.0.asInstanceOf[Int]
res3: Int = 5
scala> 5.0.asInstanceOf[Integer]
java.lang.ClassCastException: java.lang.Double cannot be cast to java.lang.Integer
... 33 elided
Note that you can directly do 5.0.asInstanceOf[Int] but not 5.0.asInstanceOf[Integer]. Also note that the ClassCastException that you get with aaa[Int] is referring to java.lang.Integer not Scala's Int class. I suspect what goes on here is that the #specialized annotation is generating a function, aaa, that has an "Int" specialization but because of type erasure and boxing is converting that to java.lang.Integer and there is no automatic conversion with asInstanceOf between Double and Integer.
What I try to do is to come up with a case class which I can use in pattern matching which has exactly one field, e.g. an immutable set. Furthermore, I would like to make use of functions like map, foldLeft and so on which should be passed down to the set. I tried it as in the following:
case class foo(s:Set[String]) extends Iterable[String] {
override def iterator = s.iterator
}
Now if I try to make use of e.g. the map function, I get an type error:
var bar = foo(Set() + "test1" + "test2")
bar = bar.map(x => x)
found : Iterable[String]
required: foo
bar = bar.map(x => x)
^
The type error is perfectly fine (in my understanding). However, I wonder how one would implement a wrapper case class for a collection such that one can call map, foldLeft and so on and still receive an object of the case class. Would one need to override all these functions or is there some other way around?
Edit
I'm inclined to accept the solution of RĂ©gis Jean-Gilles which works for me. However, after Googling for hours I found another interesting Scala trait named SetProxy. I couldn't find any trivial examples so I'm not sure if this trait does what I want:
come up with a custom type, i.e. a different type than Set
the type must be a case class (we want to do pattern matching)
we need "delegate" methods map, foldLeft and so on which should pass the call to our actual set and return the resulting set wrapped arround in our new type
My first idea was to extend Set but my custom type Foo already extends another class. Therefore, the second idea was to mixin the trait Iterable and IterableLike. Now I red about the trait SetProxy which made me think about which is "the best" way to go. What are your thoughts and experiences?
Since I started learning Scala three days ago, any pointers are highly appreciated!
Hmm this sounds promissing to me but Scala says that variable b is of type Iterable[String] and not of type Foo, i.e. I do not see how IterableLike helps in this situation
You are right. Merely inheriting from IterableLike as shown by mpartel will make the return type of some methods more precise (such as filter, which will return Foo), but for others such as map of flatMap you will need to provide an appopriate CanBuildFrom implicit.
Here is a code snippet that does just that:
import collection.IterableLike
import collection.generic.CanBuildFrom
import collection.mutable.Builder
case class Foo( s:Set[String] ) extends Iterable[String] with IterableLike[String, Foo] {
override def iterator = s.iterator
override protected[this] def newBuilder: scala.collection.mutable.Builder[String, Foo] = new Foo.FooBuilder
def +(elem: String ): Foo = new Foo( s + elem )
}
object Foo {
val empty: Foo = Foo( Set.empty[String] )
def apply( elems: String* ) = new Foo( elems.toSet )
class FooBuilder extends Builder[String, Foo] {
protected var elems: Foo = empty
def +=(x: String): this.type = { elems = elems + x; this }
def clear() { elems = empty }
def result: Foo = elems
}
implicit def canBuildFrom[T]: CanBuildFrom[Foo, String, Foo] = new CanBuildFrom[Foo, String, Foo] {
def apply(from: Foo) = apply()
def apply() = new FooBuilder
}
}
And some test in the repl:
scala> var bar = Foo(Set() + "test1" + "test2")
bar: Foo = (test1, test2)
scala> bar = bar.map(x => x) // compiles just fine because map now returns Foo
bar: Foo = (test1, test2)
Inheriting IterableLike[String, Foo] gives you all those methods such that they return Foo. IterableLike requires you to implement newBuilder in addition to iterator.
import scala.collection.IterableLike
import scala.collection.mutable.{Builder, SetBuilder}
case class Foo(stuff: Set[String]) extends Iterable[String] with IterableLike[String, Foo] {
def iterator: Iterator[String] = stuff.iterator
protected[this] override def newBuilder: Builder[String, Foo] = {
new SetBuilder[String, Set[String]](Set.empty).mapResult(Foo(_))
}
}
// Test:
val a = Foo(Set("a", "b", "c"))
val b = a.map(_.toUpperCase)
println(b.toList.sorted.mkString(", ")) // Prints A, B, C
I heard that with Dynamic it is somehow possible to do dynamic typing in Scala. But I can't imagine how that might look like or how it works.
I found out that one can inherit from trait Dynamic
class DynImpl extends Dynamic
The API says that one can use it like this:
foo.method("blah") ~~> foo.applyDynamic("method")("blah")
But when I try it out it doesn't work:
scala> (new DynImpl).method("blah")
<console>:17: error: value applyDynamic is not a member of DynImpl
error after rewriting to new DynImpl().<applyDynamic: error>("method")
possible cause: maybe a wrong Dynamic method signature?
(new DynImpl).method("blah")
^
This is completely logical, because after looking to the sources, it turned out that this trait is completely empty. There is no method applyDynamic defined and I can't imagine how to implement it by myself.
Can someone show me what I need to do to make it to work?
Scalas type Dynamic allows you to call methods on objects that don't exist or in other words it is a replica of "method missing" in dynamic languages.
It is correct, scala.Dynamic doesn't have any members, it is just a marker interface - the concrete implementation is filled-in by the compiler. As for Scalas String Interpolation feature there are well defined rules describing the generated implementation. In fact, one can implement four different methods:
selectDynamic - allows to write field accessors: foo.bar
updateDynamic - allows to write field updates: foo.bar = 0
applyDynamic - allows to call methods with arguments: foo.bar(0)
applyDynamicNamed - allows to call methods with named arguments: foo.bar(f = 0)
To use one of these methods it is enough to write a class that extends Dynamic and to implement the methods there:
class DynImpl extends Dynamic {
// method implementations here
}
Furthermore one need to add a
import scala.language.dynamics
or set the compiler option -language:dynamics because the feature is hidden by default.
selectDynamic
selectDynamic is the easiest one to implement. The compiler translates a call of foo.bar to foo.selectDynamic("bar"), thus it is required that this method has an argument list expecting a String:
class DynImpl extends Dynamic {
def selectDynamic(name: String) = name
}
scala> val d = new DynImpl
d: DynImpl = DynImpl#6040af64
scala> d.foo
res37: String = foo
scala> d.bar
res38: String = bar
scala> d.selectDynamic("foo")
res54: String = foo
As one can see, it is also possible to call the dynamic methods explicitly.
updateDynamic
Because updateDynamic is used to update a value this method needs to return Unit. Furthermore, the name of the field to update and its value are passed to different argument lists by the compiler:
class DynImpl extends Dynamic {
var map = Map.empty[String, Any]
def selectDynamic(name: String) =
map get name getOrElse sys.error("method not found")
def updateDynamic(name: String)(value: Any) {
map += name -> value
}
}
scala> val d = new DynImpl
d: DynImpl = DynImpl#7711a38f
scala> d.foo
java.lang.RuntimeException: method not found
scala> d.foo = 10
d.foo: Any = 10
scala> d.foo
res56: Any = 10
The code works as expected - it is possible to add methods at runtime to the code. On the other side, the code isn't typesafe anymore and if a method is called that doesn't exist this must be handled at runtime as well. In addition this code is not as useful as in dynamic languages because it is not possible to create the methods that should be called at runtime. This means that we can't do something like
val name = "foo"
d.$name
where d.$name would be transformed to d.foo at runtime. But this is not that bad because even in dynamic languages this is a dangerous feature.
Another thing to note here, is that updateDynamic needs to be implemented together with selectDynamic. If we don't do this we will get a compile error - this rule is similar to the implementation of a Setter, which only works if there is a Getter with the same name.
applyDynamic
The ability to call methods with arguments is provided by applyDynamic:
class DynImpl extends Dynamic {
def applyDynamic(name: String)(args: Any*) =
s"method '$name' called with arguments ${args.mkString("'", "', '", "'")}"
}
scala> val d = new DynImpl
d: DynImpl = DynImpl#766bd19d
scala> d.ints(1, 2, 3)
res68: String = method 'ints' called with arguments '1', '2', '3'
scala> d.foo()
res69: String = method 'foo' called with arguments ''
scala> d.foo
<console>:19: error: value selectDynamic is not a member of DynImpl
The name of the method and its arguments again are separated to different parameter lists. We can call arbitrary methods with an arbitrary number of arguments if we want but if we want to call a method without any parentheses we need to implement selectDynamic.
Hint: It is also possible to use apply-syntax with applyDynamic:
scala> d(5)
res1: String = method 'apply' called with arguments '5'
applyDynamicNamed
The last available method allows us to name our arguments if we want:
class DynImpl extends Dynamic {
def applyDynamicNamed(name: String)(args: (String, Any)*) =
s"method '$name' called with arguments ${args.mkString("'", "', '", "'")}"
}
scala> val d = new DynImpl
d: DynImpl = DynImpl#123810d1
scala> d.ints(i1 = 1, i2 = 2, 3)
res73: String = method 'ints' called with arguments '(i1,1)', '(i2,2)', '(,3)'
The difference in the method signature is that applyDynamicNamed expects tuples of the form (String, A) where A is an arbitrary type.
All of the above methods have in common that their parameters can be parameterized:
class DynImpl extends Dynamic {
import reflect.runtime.universe._
def applyDynamic[A : TypeTag](name: String)(args: A*): A = name match {
case "sum" if typeOf[A] =:= typeOf[Int] =>
args.asInstanceOf[Seq[Int]].sum.asInstanceOf[A]
case "concat" if typeOf[A] =:= typeOf[String] =>
args.mkString.asInstanceOf[A]
}
}
scala> val d = new DynImpl
d: DynImpl = DynImpl#5d98e533
scala> d.sum(1, 2, 3)
res0: Int = 6
scala> d.concat("a", "b", "c")
res1: String = abc
Luckily, it is also possible to add implicit arguments - if we add a TypeTag context bound we can easily check the types of the arguments. And the best thing is that even the return type is correct - even though we had to add some casts.
But Scala would not be Scala when there is no way to find a way around such flaws. In our case we can use type classes to avoid the casts:
object DynTypes {
sealed abstract class DynType[A] {
def exec(as: A*): A
}
implicit object SumType extends DynType[Int] {
def exec(as: Int*): Int = as.sum
}
implicit object ConcatType extends DynType[String] {
def exec(as: String*): String = as.mkString
}
}
class DynImpl extends Dynamic {
import reflect.runtime.universe._
import DynTypes._
def applyDynamic[A : TypeTag : DynType](name: String)(args: A*): A = name match {
case "sum" if typeOf[A] =:= typeOf[Int] =>
implicitly[DynType[A]].exec(args: _*)
case "concat" if typeOf[A] =:= typeOf[String] =>
implicitly[DynType[A]].exec(args: _*)
}
}
While the implementation doesn't look that nice, its power can't be questioned:
scala> val d = new DynImpl
d: DynImpl = DynImpl#24a519a2
scala> d.sum(1, 2, 3)
res89: Int = 6
scala> d.concat("a", "b", "c")
res90: String = abc
At the top of all, it is also possible to combine Dynamic with macros:
class DynImpl extends Dynamic {
import language.experimental.macros
def applyDynamic[A](name: String)(args: A*): A = macro DynImpl.applyDynamic[A]
}
object DynImpl {
import reflect.macros.Context
import DynTypes._
def applyDynamic[A : c.WeakTypeTag](c: Context)(name: c.Expr[String])(args: c.Expr[A]*) = {
import c.universe._
val Literal(Constant(defName: String)) = name.tree
val res = defName match {
case "sum" if weakTypeOf[A] =:= weakTypeOf[Int] =>
val seq = args map(_.tree) map { case Literal(Constant(c: Int)) => c }
implicitly[DynType[Int]].exec(seq: _*)
case "concat" if weakTypeOf[A] =:= weakTypeOf[String] =>
val seq = args map(_.tree) map { case Literal(Constant(c: String)) => c }
implicitly[DynType[String]].exec(seq: _*)
case _ =>
val seq = args map(_.tree) map { case Literal(Constant(c)) => c }
c.abort(c.enclosingPosition, s"method '$defName' with args ${seq.mkString("'", "', '", "'")} doesn't exist")
}
c.Expr(Literal(Constant(res)))
}
}
scala> val d = new DynImpl
d: DynImpl = DynImpl#c487600
scala> d.sum(1, 2, 3)
res0: Int = 6
scala> d.concat("a", "b", "c")
res1: String = abc
scala> d.noexist("a", "b", "c")
<console>:11: error: method 'noexist' with args 'a', 'b', 'c' doesn't exist
d.noexist("a", "b", "c")
^
Macros give us back all compile time guarantees and while it is not that useful in the above case, maybe it can be very useful for some Scala DSLs.
If you want to get even more information about Dynamic there are some more resources:
The official SIP proposal that introduced Dynamic into Scala
Practical uses of a Dynamic type in Scala - another question on SO (but very outdated)
kiritsuku's answer is better. This is to show a practical TL;DR use case.
Dynamics can be used to dynamically construct an object with the builder pattern.
import scala.language.dynamics
case class DynImpl(
inputParams: Map[String, List[String]] = Map.empty[String, List[String]]
) extends Dynamic {
def applyDynamic(name: String)(args: String*): DynImpl = {
copy(inputParams = inputParams ++ Map(name -> args.toList))
}
}
val d1 = DynImpl().whatever("aaa", "bbb").cool("ccc")
println(d1.inputParams) // Map(whatever -> List(aaa, bbb), cool -> List(ccc))
val d2 = DynImpl().whatever("aaa", "bbb").fun("haha")
println(d2.inputParams) // Map(whatever -> List(aaa, bbb), fun -> List(haha))
Assume, we have something like:
val x = "foo".charAt(0)
and let us further assume, we do not know the return type of the method charAt(0) (which is, of course, described in the Scala API). Is there a way, we can find out, which type the variable x has after its definition and when it is not declared explicitly?
UPDATE 1:
My initial question was not precise enough: I would like to know (for debugging reasons) what type the variable has. Maybe there is some compiler option to see what type the variable get declared to by Scala's type inference ?
Suppose you have the following in a source file named Something.scala:
object Something {
val x = "foo".charAt(0)
}
You can use the -Xprint:typer compiler flag to see the program after the compiler's typer phase:
$ scalac -Xprint:typer Something.scala
[[syntax trees at end of typer]]// Scala source: Something.scala
package <empty> {
final object Something extends java.lang.Object with ScalaObject {
def this(): object Something = {
Something.super.this();
()
};
private[this] val x: Char = "foo".charAt(0);
<stable> <accessor> def x: Char = Something.this.x
}
}
You could also use :type in the REPL:
scala> :type "foo".charAt(0)
Char
scala> :type "foo".charAt _
Int => Char
Your IDE may also provide a nicer way to get this information, as Luigi Plinge points out in a comment above.
Here's an easier version of Travis first alternative:
dcs#dcs-132-CK-NF79:~/tmp$ scala -Xprint:typer -e '"foo".charAt(0)'
[[syntax trees at end of typer]] // scalacmd8174377981814677527.scala
package <empty> {
object Main extends scala.AnyRef {
def <init>(): Main.type = {
Main.super.<init>();
()
};
def main(argv: Array[String]): Unit = {
val args: Array[String] = argv;
{
final class $anon extends scala.AnyRef {
def <init>(): anonymous class $anon = {
$anon.super.<init>();
()
};
"foo".charAt(0)
};
{
new $anon();
()
}
}
}
}
}
Use this method for problem:
x.getClass
If you are using IntelliJIDEA, to show Type Info action in Editor, navigate to the value and press Alt + = for Windows and Ctrl + Shift + P for Mac:
I find it very handy when writing code.
i have a class with a method that returns a function object. the requirements are that the method is arity 0 and its return type is an Option of a Function0 - whose return type is the original return type. for example:
class MyClass {
def f(): Option[Function[A]] = Some(g _)
def g(): Option[Function[A]] = Some(h _)
... goes on and on, eventually returns Some(z _) ...
def z(): Option[Function[A]] = None
}
Due to the recursion, the issue is that the type A is defined as:
type A = Option[Function0[A]]
but since cyclic references are not allowed, it produces the error:
illegal cyclic reference involving type A
i obviously want to avoid defining a different return type for each of the methods, but having a unified return type doesn't seem possible due to the cycle. is there any way to do this? thanks!
This is not supported by Scala type definitions. See How to define a cyclic type definition?
You can accomplish this with a class instead of a type, although you would have to define your own Option-like class. An example is below (with monadic methods omitted). Also, see this mailing list discussion: http://www.scala-lang.org/node/2541
sealed trait OptionalFunction extends (() => OptionalFunction) {
def get: (() => OptionalFunction)
}
case class SomeFunction(fn: () => OptionalFunction) extends OptionalFunction {
def apply() = fn()
def get = fn
}
case object NoFunction extends OptionalFunction {
def apply() = this
def get = throw new NoSuchElementException
}
class MyClass {
type A = OptionalFunction
def f(): A = SomeFunction(g _)
def g(): A = SomeFunction(h _)
def h(): A = SomeFunction(() => { println("At the end!"); i })
def i(): A = NoFunction
}
scala> new MyClass().f()()()()
At the end!
res0: OptionalFunction[Unit] = <function0>
I'm not sure if this is what you're looking for, but many of these edge-cases can be worked around with explicitly using objects:
abstract class F extends Function0[F]
val p = new F {
def apply() = { println("hi"); this }
}
>> defined class F
>> p: $anon forSome { type $anon <: F{def apply(): $anon} } =
p()
>> hi
>> res2: $anon =
p()()
>> hi
>> hi
>> res3: $anon =
Happy coding.