Reading this, I still have questions about unapply() that returns Boolean.
If take a look at Scala Programming Book (2nd edition), page 602. There is an example:
case Email(Twice(x # UpperCase()), domain) => ...
Where UpperCase defined as an object that has unapply() returning Boolean and does not have apply()
object UpperCase {
def unapply(s:String): Boolean = s.toUpperCase == s
}
Where Twice is something like this:
object Twice {
def apply(s:String): String = s + s
...
The questions are (must be too many, sorry for that):
How does UpperCase().unapply(..) works here?
If I pass: DIDI#hotmail.com, then x in first code snippet = 'DI'.. then we use '#' ..to bind 'x' to pass it to UpperCase.unapply to invoke unapply(x) i.e unapply('DIDI') (?) Then it returns True.
But why not Option ? I tend to think that unapply returns Option.. kind of one way how it works. That's probably because usually Option wraps some data, but for simple case we should NOT wrap boolean? And because we do not have apply()?
What the difference, when use Boolean / Option ? Based on this example.
And this syntax: x # UpperCase(), is it supposed to substitute value match case (is that way how I suppose to read it?) syntax if we are matching inside one particular case? It doesn't seems as unified way/syntax of doing this.
Usually syntax like (assuming that x,y is Int): case AA(x # myX, y) => println("myX: " + myX) says that x binds to myX, basically myX is alias to x.. in this case. But in our case - x # UpperCase(). x binds to UpperCase().unapply().. putting x as parameter. I mean binding here is quite abstract/wide notion..
This is simple:
1) If you return Boolean, your unapply just tests matching query
scala> object UpperCase {
| def unapply(s: String) = s.toUpperCase == s
| }
defined module UpperCase
scala> "foo" match {
| case UpperCase() => true
| case _ => false
| }
res9: Boolean = false
2) If you return Option[T], you create an extractor, which unwraps T
scala> object IsUpperCase {
| def unapply(s: String) = Option(s).map(x => x.toUpperCase == x)
| }
defined module IsUpperCase
scala> "FOO" match {case IsUpperCase(flag) => flag}
res0: Boolean = true
This is not so simple.
The behavior of "boolean test" match just changed in the latest milestone:
apm#mara:~/clones/scala$ ./build/pack/bin/scala
Welcome to Scala version 2.11.0-20130911-042842-a49b4b6375 (OpenJDK 64-Bit Server VM, Java 1.7.0_25).
Type in expressions to have them evaluated.
Type :help for more information.
scala>
scala> object OK { def unapply(s: String) = Some(s) filter (_ == "OK") }
defined object OK
scala> import PartialFunction._
import PartialFunction._
scala> cond("OK") { case OK() => true }
<console>:12: error: wrong number of patterns for object OK offering String: expected 1, found 0
cond("OK") { case OK() => true }
^
<console>:12: error: wrong number of patterns for object OK offering String: expected 1, found 0
cond("OK") { case OK() => true }
^
scala> cond("OK") { case OK(x) => true }
res1: Boolean = true
scala> :q
Previously, you could use the extractor without extracting any fields, just for a "boolean test", even though the result of the unapply is not Boolean:
apm#mara:~/clones/scala$ scalam
Welcome to Scala version 2.11.0-M4 (OpenJDK 64-Bit Server VM, Java 1.7.0_25).
Type in expressions to have them evaluated.
Type :help for more information.
scala> import PartialFunction._
import PartialFunction._
scala> object OK { def unapply(s: String) = Some(s) filter (_ == "OK") }
defined object OK
scala> cond("OK") { case OK() => true }
res0: Boolean = true
scala> cond("OK") { case OK(x) => true }
res1: Boolean = true
Here is some discussion and here is the change in the way extractor signatures are processed.
Related
I want to write a method that returns true if an Option[Int] contains a specific value and false otherwise. What is the idiomatic way of doing this?
var trueIf5(intOption: Option[Int]): Boolean {
intOption match {
case Some(i) => i == 5
case None => false
}
}
This above solution clearly works, but the Scala docs label this approach as less-idiomatic.
Is there some way I can do the same thing using map, filter, or something else?
I got this far, but it only changes the problem to "Return true if Option contains true", which is effectively the same as "Return true if Option contains 5".
var trueIf5(intOption: Option[Int]): Boolean {
intOption.map(i => i == 5).???
}
Since you're testing whether it contains a value:
scala> Some(42) contains 42
res0: Boolean = true
Don't neglect your -Xlint:
scala> Option(42).contains("")
res0: Boolean = false
scala> :replay -Xlint
Replaying: Option(42).contains("")
<console>:12: warning: a type was inferred to be `Any`; this may indicate a programming error.
Option(42).contains("")
^
res0: Boolean = false
Those built-in warnings aren't as effective with universal equality:
scala> Option(42).exists("" == _) // no warning
res1: Boolean = false
intOption.exists(_ == 5)
The doc
Why has no one suggested:
intOption == Some(5)
According to this answer https://stackoverflow.com/a/8001065/1586965 we can do this in Scala:
val _ = 5
Now I understand the point of ignored parameters in lambda expressions, but I cannot really imagine examples where I would ever want to declare a variable that by definition I cannot reference. The only example I can think of is being lazy about naming implicit values, e.g.
implicit val _: MyNumeric = ...
...
class A[T : MyNumeric] {
...
Is this the only use case? Am I missing something?
If it is the only use case, shouldn't the compiler/IDE give a warning/hint when the val is not implicit as it is utterly pointless?
Clarification
By variable/value I mean a single one, not one that is part of an extraction declaration.
I don't think that this is a feature at all. In any case, it is not an "ignored variable".
By which I mean that if val _ = 5 really introduced an unnamed value, then you could declare as many as you want in the same single scope.
Not so:
scala> object Test {
| val _ = 5
| val _ = 7
| }
<console>:9: error: _ is already defined as value _
val _ = 7
^
From the error message it seems clear that what really happens is that the value is actually named _
(which I'd call a quirk of the compiler that should be fixed). We can verify this:
scala> object Test {
| val _ = 5
| def test() { println( `_` ) } // This compiles fine
| }
defined object Test
scala> Test.test()
5
As for the possible use of preventing a value discarding warning (as shown in som-snytt's answer), I'much prefer to simply return an explicit Unit.
This looks less convoluted and is even shorter:
def g(): Unit = { f(); () }
as opposed to:
def g(): Unit = { val _ = f() }
It uses a value.
$ scala -Ywarn-value-discard
Welcome to Scala version 2.11.2 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_11).
Type in expressions to have them evaluated.
Type :help for more information.
scala> def f() = { println("I ran.") ; 42 }
f: ()Int
scala> def g(): Unit = { f() }
<console>:8: warning: discarded non-Unit value
def g(): Unit = { f() }
^
g: ()Unit
scala> def g(): Unit = { val _ = f() }
g: ()Unit
scala> g
I ran.
scala>
To verify, it also doesn't warn under -Ywarn-unused.
The other use case (that I can think of) is related to extraction (and is called out under "Wildcard patterns" in the linked answer):
val getCartesianPoint = () => (1, 2, 3)
// We don't care about the z axis, so we assign it to _
val (x, y, _) = getCartesianPoint()
val regex = "(.*?)|(.*?)|?.*".r
// Really, any unapply or unapplySeq example will do
val regex(_, secondValue) = "some|delimited|value|set"
I don't think this code should work, but it does (in Scala 2.10):
scala> ((i: Int) => i.toString match {
| case s if s.length == 2 => "A two digit number"
| case s if s.length == 3 => "A three digit number"
| }): PartialFunction[Int,String]
res0: PartialFunction[Int,String] = <function1>
// other interactions omitted
scala> res0.orElse(PartialFunction((i: Int) => i.toString))
res5: PartialFunction[Int,String] = <function1>
scala> res5(1)
res6: String = 1
How does it work? I would expect a MatchError to be thrown inside res0.
The Scala language specification does not seem to explicitly document how res0 should be interpreted.
The trick is that the compiler is not interpreting your definition as a total function converted to a partial function -- it's actually creating a partial function in the first place. You can verify by noting that res0.isDefinedAt(1) == false.
If you actually convert a total function to a partial function, you will get the behavior you expected:
scala> PartialFunction((i: Int) => i.toString match {
| case s if s.length == 2 => "A two digit number"
| case s if s.length == 3 => "A three digit number"
| })
res0: PartialFunction[Int,String] = <function1>
scala> res0 orElse ({ case i => i.toString }: PartialFunction[Int, String])
res1: PartialFunction[Int,String] = <function1>
scala> res1(1)
scala.MatchError: 1 (of class java.lang.String)
// ...
In this example, PartialFunction.apply treats its argument as a total function, so any information about where it's defined is lost.
orElse is defined on PartialFunction so that the argument is treated as a fallback for the cases when the original is not defined. See the API.
You say that if res0 does not match, you want to try your other pf instead. How this essentially works is:
if (res0.isDefinedAt(1)) {
res0(1)
} else {
other(1)
}
The orElse call creates an instance of OrElse, which inherits from PartialFunction: https://github.com/scala/scala/blob/master/src/library/scala/PartialFunction.scala#L159
When you now call apply on this OrElse, it will call f1.applyOrElse(x, f2): https://github.com/scala/scala/blob/master/src/library/scala/PartialFunction.scala#L162
This will call if (isDefinedAt(x)) apply(x) else f2(x): https://github.com/scala/scala/blob/master/src/library/scala/PartialFunction.scala#L117-L118
Therefore you will only get a MatchError, when neither of the pf's matches.
I am hoping to write a Scala method which takes in a tuple of any size and type along with an index, and returns the element in the tuple at that index. I know how to do everything but preserve the type. I haven't yet figured out a way to make the return value be of the dynamic type of the tuple item.
Here is the function I have so far:
def subscript_get(tup: Product, index:Int): Any={
return tup.productElement(index)
}
The usage for example would be:
subscript_get((0,1,2,3),0)
--> Int = 0
subscript_get((0,1,"asdf",3),2)
--> java.lang.String = asdf
I know that I can cast the result back afterwards to what I am looking for, but this doesn't work for me because I can't always know what type I should cast to.
Is something like this even possible ? Thanks!
I'm not sure you want a solution that uses macros, but for the record (and since I've written precisely this method before), here's how you can implement this with the macro system in 2.10.
As I note in a comment above, this approach requires index to be an integer literal, and relies on "underspecified but intended" behavior in 2.10. It also raises some tricky questions about documentation.
import scala.language.experimental.macros
import scala.reflect.macros.Context
object ProductIndexer {
def at[T <: Product](t: T)(index: Int) = macro at_impl[T]
def at_impl[T <: Product: c.WeakTypeTag](c: Context)
(t: c.Expr[T])(index: c.Expr[Int]) = {
import c.universe._
index.tree match {
case Literal(Constant(n: Int)) if
n >= 0 &&
weakTypeOf[T].members.exists {
case m: MethodSymbol => m.name.decoded == "_" + (n + 1).toString
case _ => false
} => c.Expr[Any](Select(t.tree, newTermName("_" + (n + 1).toString)))
case Literal(Constant(_: Int)) => c.abort(
c.enclosingPosition,
"There is no element at the specified index!"
)
case _ => c.abort(
c.enclosingPosition,
"You must provide an integer literal!"
)
}
}
}
And then:
scala> import ProductIndexer._
import ProductIndexer._
scala> val triple = (1, 'a, "a")
triple: (Int, Symbol, String) = (1,'a,a)
scala> at(triple)(0)
res0: Int = 1
scala> at(triple)(1)
res1: Symbol = 'a
scala> at(triple)(2)
res2: String = a
All statically typed as expected, and if you give it an index that's out of range (or not a literal), you get a nice compile-time error.
You cannot do that. If you use Product, the (compile-time) type of the values in the tuples is lost. Further, a method cannot adapt its return type based on an value you pass in (not entirely true, see dependent method types, but true for an Int).
If you do not know what type to cast to, you could use pattern matching:
subscript_get(..., 1) match {
case v: Int => // do something with Int
case v: String => // do something with String
// snip
case _ => sys.error("don't know how to handle this")
}
I wonder why there doesn't exist a literal for partial function types. I have to write
val pf: PartialFunction[Int, String] = {
case 5 => "five"
}
where an literal like :=> would be shorter:
val pf: Int :=> String = {
case 5 => "five"
}
Partial functions are often used and in Scala already some "special" feature, so why no special syntax for it?
Probably in part because you don't need a literal: you can always write your own :=> as a type infix operator if you want more concise syntax:
scala> type :=>[A, B] = PartialFunction[A, B]
defined type alias $colon$eq$greater
scala> val pf: Int :=> String = { case 5 => "five" }
pf: :=>[Int,String] = <function1>
scala> pf.isDefinedAt(0)
res0: Boolean = false
scala> pf.isDefinedAt(5)
res1: Boolean = true
I'm not one of the designers of the Scala language, though, so this is more or less a guess about the "why?". You might get better answers over at the scala-debate list, which is a more appropriate venue for language design questions.