When trying to define a generic method def f[T] (x:T) = x + 1 Scala gives below error
<console>:8: error: type mismatch;
found : Int(1)
required: String
def f[T] (x:T) = x + 1
^
The question is why Scala is assuming that it should be a String?
What if we want a function that can do +1 to Int, Char and String. I know I can do something like below, but it would work only on Int and Char.
def f[T <% Int](x:T) = x + 1
So what's the reason of this error and how to handle it in generic way.
The question is why Scala is assuming that it should be a String?
I can't guarantee this analysis, but it appears that Scala is applying the Predef.any2stringadd() implicit conversion to x, in an attempt to turn it into something that supports the + operator.
Here's a variant that will compile, and which demonstrates that implicit conversion:
scala> def f(x:Any) = { x + "1" }
f: (x: Any)String
scala> f("foo")
res3: String = foo1
scala> f(123)
res0: String = 1231
scala> f(classOf[String])
res2: String = class java.lang.String1
What if we want a function that can do +1 to Int, Char and String.
What does it mean to add 1 to any of these values?
If you simply want to invoke the + operator, then you need to use the match operator to select different behaviors depending on the actual type. This is because, while the name + is used for both, there's no common behavior between strings and numbers.
On the other hand, perhaps you want to deal with numbers that can be provided as either strings or numeric values (in which case, why Char?). To make that work, you need an implicit function that converts Any to a number.
scala> implicit def any2int(x:Any) : Int = { x.toString.toInt }
warning: there were 1 feature warning(s); re-run with -feature for details
any2int: (x: Any)Int
scala> def f(x:Any) : Int = { x + 1 }
f: (x: Any)Int
scala> f(123)
res0: Int = 124
scala> f("123")
res1: Int = 124
The return type of the function will always be Int as I assume so it should be that the compiler choose Int but why String.
Related
Suppose I want to create a NonZero type so that my integer division function is total:
def div(numerator: Int, denominator: NonZero): Int =
numerator / denominator.value
I can implement this by creating a NonZero class with a private constructor:
class NonZero private[NonZero] (val value : Int) { /*...*/ }
And a helper object to hold a Int => Option[NonZero] constructor, and an unapply so it can be used in match expressions:
object NonZero {
def build(n:Int): Option[NonZero] = n match {
case 0 => None
case n => Some(new NonZero(n))
}
def unapply(nz: NonZero): Option[Int] = Some(nz.value)
// ...
}
build is fine for runtime values, but having to do NonZero.build(3).get for literals feels ugly.
Using a macro, we can define apply only for literals, so NonZero(3) works, but NonZero(0) is a compile-time error:
object NonZero {
// ...
def apply(n: Int): NonZero = macro apply_impl
def apply_impl(c: Context)(n: c.Expr[Int]): c.Expr[NonZero] = {
import c.universe._
n match {
case Expr(Literal(Constant(nValue: Int))) if nValue != 0 =>
c.Expr(q"NonZero.build(n).get")
case _ => throw new IllegalArgumentException("Expected non-zero integer literal")
}
}
}
However this macro is less useful than it could be, as it only allows literals, not compile-time constant expressions:
final val X: Int = 3
NonZero(X) // compile-time error
I could pattern match on Expr(Constant(_)) in my macro, but then what about NonZero(X + 1)? I'd rather not have to implement my own scala expression evaluator.
Is there a helper or some easy way to determine if the value of an expression given to a macro is known at compile time (what C++ would call constexpr)?
If you ignore macros, then in Scala, only types exist at compile time, and only values exist at runtime. You can do type-level tricks to encode numbers as types at compile time, e.g. Type Level Programming in Scala
Here's a simplified version of the above Peano arithmetic example. First, we define a typeclass that shows how some type can convert to an integer.
#annotation.implicitNotFound("Create an implicit of type TValue[${T}] to convert ${T} values to integers.")
final class TValue[T](val get: Int) extends AnyVal
Then, we define the Peano 'zero' type and show how it can convert to a runtime integer 0:
case object TZero {
implicit val tValue: TValue[TZero.type] = new TValue(0)
}
Then the Peano 'successor' type and how it can convert to a runtime integer 1 + previous value:
case class TSucc[T: TValue]()
object TSucc {
implicit def tValue[TPrev](implicit prevTValue: TValue[TPrev]): TValue[TSucc[TPrev]] =
new TValue(1 + prevTValue.get)
}
Then test safe division:
object Test {
def safeDiv[T](numerator: Int, denominator: TSucc[T])(implicit tValue: TValue[TSucc[T]]): Int =
numerator / tValue.get
}
Trying it out:
scala> Test.safeDiv(10, TZero)
<console>:14: error: type mismatch;
found : TZero.type
required: TSucc[?]
Test.safeDiv(10, TZero)
^
scala> Test.safeDiv(10, TSucc[String]())
<console>:14: error: Create an implicit of type TValue[String] to convert String values to integers.
Test.safeDiv(10, TSucc[String]())
^
scala> Test.safeDiv(10, TSucc[TZero.type]) // 10/1
res2: Int = 10
scala> Test.safeDiv(10, TSucc[TSucc[TZero.type]]) // 10/2
res3: Int = 5
As you can imagine though, this can get verbose fast.
som-snytt's advice to check out ToolBox.eval led me to Context.eval, which the helper I'd been wanting:
object NonZero {
// ...
def apply(n: Int): NonZero = macro apply_impl
def apply_impl(c: Context)(n: c.Expr[Int]): c.Expr[NonZero] = try {
if (c.eval(n) != 0) {
import c.universe._
c.Expr(q"NonZero.build(n).get")
} else {
throw new IllegalArgumentException("Non-zero value required")
}
} catch {
case _: scala.tools.reflect.ToolBoxError =>
throw new IllegalArgumentException("Unable to evaluate " + n.tree + " at compile time")
}
}
So now I can pass NonZero.apply constants and expressions made with constants:
scala> final val N = 3
scala> NonZero(N)
res0: NonZero = NonZero(3)
scala> NonZero(2*N + 1)
res1: NonZero = NonZero(7)
scala> NonZero(N - 3)
IllegalArgumentException: ...
scala> NonZero((n:Int) => 2*n + 1)(3))
IllegalArgumentException: ...
While it'd be nice if eval could handle pure functions like the last example above, this is good enough.
Embarrassingly, reviewing and retesting my earlier code from the question proved that my original macro handled the same expressions just as well!
My assertion that final val X = 3; NonZero(X) // compile-time error was just wrong, since all the evaluation was being handled by inlining (as som-snytt's comment implied).
In scala if I have a declaration such as this:
val i: Float = 5
Is this the same like in this line:
val i = 5: Float
?
Recently I encountered an expression with such type annotation on the right side and I wonder what its usage is as I could not find it in the specs.
This is called type ascription and it's meant to disambiguate types when several options might be available.
A typical example is a fold:
val l = 1 to 5
val stringyfied = l.foldLeft(Nil)((list, elem) => elem.toString :: list)
What is the type of Nil in that case? If you try that example, the compile will bark with an error:
error: type mismatch;
found : List[String]
required: scala.collection.immutable.Nil.type
We can make the specific type known to the compiler by using type ascription:
val stringyfied = l.foldLeft(Nil:List[String])((list, elem) => elem.toString :: list)
// stringyfied: List[String] = List(5, 4, 3, 2, 1)
Another common use is to view a collection as a vararg as in:
def varargs(a:Int*) = a.sum
// common use:
varargs(1,2,3,4,5) //15
// now we have a collection of elements:
val intlist = 1 to 5
// we cannot call varagrs with a list
varargs(intlist)
> found : List[Int]
> required: Int
// then using type ascription:
varargs(intlist: _*)
To my knowledge, there's not much specific documentation about type ascription other than the specification of the algebra of expressions SLS#Chapter6
This syntax is used to assign types to expressions (while val i: Float = 5 assigns a type to a term). It can make a difference when you do it with a part of a bigger expression.
scala> implicit class WeirdFloat(f: Float) {
| def +(ff: Float) = new WeirdFloat(f + ff * 2)
| override def toString = s"$f"
| }
defined class WeirdFloat
scala> val i: WeirdFloat = 5 + 7
i: WeirdFloat = 12.0
scala> val i = (5: WeirdFloat) + 7
i: WeirdFloat = 19.0
I believe the only difference is that the type of i is inferred (by the compiler) from the value in the second example, whereas in the first you are being explicit about the type of i.
The stye guidelines encourage the use of type of inference wherever possible. However, it also mentions that the syntax whereby you follow the value with the type is the approach when you are using ascription - a compile time upcast.
scala> val s = "Jane"
s: String = Jane
scala> val p = s: Object
p: Object = Jane
I'm trying to figure out the difference between def and var/val when declaring a function in Scala.
Say we have a function:
scala> def f(x: Int) = { x * 2 }
f: (x: Int)Int
And another function g:
scala> var g = (x:Int) => x*2
g: Int => Int = <function1>
Apparently they are the same in the following way:
scala> f(2)
res0: Int = 4
scala> g(2)
res1: Int = 4
However, I could do
g = f
g: Int => Int = <function1>
but not
scala> f = g
<console>:13: error: missing arguments for method f;
follow this method with `_' if you want to treat it as a partially applied function
val $ires6 = f
^
<console>:10: error: reassignment to val
f = g
^
Question 1: why does this happen? I'm guessing that def maps to val.
Question 2: if I use val instead of var in declare g, are they equivalent? If not, what is the difference then?
I then try:
scala> def three( timetwo:(Int) => Int ) = { timetwo(3) }
three: (timetwo: Int => Int)Int
scala> three(g)
res47: Int = 6
scala> three(f)
res48: Int = 6
Question 3: does it mean (x: Int)Int is the same as Int => Int = <function1>? If so, is there some situation that we should favor one over the other?
Things is getting wired with the _ (underscore),
scala> three(f _)
res49: Int = 6
scala> three(g _)
<console>:11: error: type mismatch;
found : () => Int => Int
required: Int => Int
three(g _)
^
Question 4: why does this happen? What's the usage of _(underline) in Scala?
why does this happen? I'm guessing that def maps to val.
def is a method (in JVM terms) so it doesn't make sense to assign it.
The parser is then confused and it ultimately tries to save the day by interpreting the assignment f = g as
val $ires6 = f
f = g
Both statements are illegal, so you get two errors:
you can't assign a method to a val without an explicit type annotation or a _ expansion - see below)
you can't reassign a val (in case you are wondering, $ires6 is a fresh val introduced by the REPL)
if I use val instead of var in declare g, are they equivalent? If not, what is the difference then?
The difference is that val cannot be reassigned (i.e. it's a constant reference), whereas var can (i.e. it's a mutable reference).
More on the subject here: What is the difference between a var and val definition in Scala?
does it mean (x: Int)Int is the same as Int => Int = ? If so, is there some situation that we should favor one over the other?
Methods and functions are not the same, although the compiler does its best to make you believe they are, through a transformation called eta-expansion. In some cases such transformation can be performed automatically, in some others you need to be explicit and trigger it with a trailing _.
In your specific example (passing a method where a function is expected) the expansion can been performed automatically.
You can read this Q/A for a more in-depth discussion about which style to prefer.
why does this happen? What's the usage of _(underline) in Scala?
The underscore (_) has many uses in scala, one of which is the one I mentioned before, i.e. triggering the eta expansion of a method into a function.
That's a special syntax for methods, so you simply can't apply it to a function, as it would make no sense.
That's why you can do f _ (which will turn the f method into a function), but you can't do g _ (since g it's already a function).
Inspired by this, I was wondering if we can have type-safe string interpolations in Scala (maybe using macros)?
For example, I want to have something like this
def a[A] = ???
val greetFormat = f"Hi! My name is ${a[String]}. I am ${a[Int]} years old"
greetFormat.format("Rick", 27) // compiles
//greetFormat.format("Rick", false) // does not compile
//greetFormat.format(27, "Rick") // does not compile
//greetFormat.format("Rick", 27, false) // does not compile
//greetFormat.format("Rick") // does not compile or is curried?
The f string interpolator is already implemented with a macro.
This can be demonstrated inside of the REPL:
scala> val b = "not a number"
b: String = not a number
scala> f"$b%02d"
<console>:9: error: type mismatch;
found : String
required: Int
f"$b%02d"
^
Just wrap it in a function.
def greet(name: String, age: Int) = s"Hi! My name is $name. I am $age years old"
You can supply implicits to the f-interpolator:
scala> case class A(i: Int)
defined class A
scala> implicit def atoi(a: A): Int = a.i
warning: there were 1 feature warning(s); re-run with -feature for details
atoi: (a: A)Int
scala> f"${A(42)}%02d"
res5: String = 42
See also Travis Brown's examples and solution for using regex group names in extractions. It took me about a minute to steal that great idea.
"a123bc" match {
case res # xr"(?<c>a)(?<n>\d+)(?<s>bc)" => assert {
res.c == 'a' && res.n == 123 && res.s == "bc"
}
}
For the record, on the composition side, I would like:
val a = A(Rick, 42)
val greeter = f"Hi! My name is $_. I am ${_}%d years old"
greeter(a, a)
But it was deemed too much for the poor underscore. You'll have to write the function as in the other answer.
Your form, in which your macro sees "${a[Int]}" and writes a function with an Int param, doesn't look hard to implement.
Other features of the f-interpolator include other static error checking:
scala> f"$b%.02d"
<console>:19: error: precision not allowed
f"$b%.02d"
^
and support for Formattable:
scala> val ff = new Formattable { def formatTo(fmtr: Formatter, flags: Int, width: Int, precision: Int) = fmtr.format("%s","hello, world") }
ff: java.util.Formattable = $anon$1#d2e6b0b
scala> f"$ff"
res6: String = hello, world
A quick macro might emit (i: Int) => f"${ new Formattable {...} }".
Being relatively new at Scala, I was playing around with partially-applied function syntax on sbt console. I ran into a very weird issue in which I do not understand Scala's behavior.
The example is contrived and would unlikely be encountered in reality. That said, here it is. Suppose I define the following function:
scala> def f(x: Int, y: Int) = "%d %d".format(x, y)
Now if I type in
scala> f(1, _:Int)(2)
res: Int => Char = <function1>
The result is a Int => Char function, which is very unusual. In other words, Scala is (temporarily) treating f(1, _:Int) as a String (vs. its actual type: Int => String) when applying the parameter (i.e., 2).
If, instead, parentheses are used, what I expect to happen occurs:
scala> (f(1, _:Int))(2)
res: String = 1 2
However, this does not appear to be an order-of-operations issue, as I cannot find a way to add parentheses to achieve the unexpected behavior (i.e., having the result be of type Int => Char).
Any ideas?
At first about the result type of:
scala> f(1, _:Int)(2)
res: Int => Char = <function1>
Check this out:
scala> val str = "hello"
str: String = hello
scala> str(2)
res12: Char = l
I think this is clear.
No to the function itself, as it also easy. When you are lifting it to a function with an underscore you are lifting not only f, but also with a call (2) on a string (first result), which is why you get:
res: Int => Char = <function1>
Added
More explicit version. You function f is of type (Int, Int) => String, when you write f(1, _: Int), you are partially applying it to the argument one and returning a function of type Int => String, where Int is the second argument. Then your argument (2) call apply method on the result string from the function Int => String which returns you a Char, from here you get function of type Int => Char, where Int is a second argument to your f function and Char is a char from the resulting string
In the second case, where you have:
scala> (f(1, _:Int))(2)
res: String = 1 2
by parenthesis you are spliting this into to things, the first one is a function Int => String and (2) calls this function, you are passing an argument 2 into this function Int => String:
val ff = f(1, _: Int)
val res = ff(2)