Why is this Option transformed to a String? [Scala] - scala

I'm still a Scala noob, and this confuses me:
import java.util.regex._
object NumberMatcher {
def apply(x:String):Boolean = {
val pat = Pattern.compile("\\d+")
val matcher = pat.matcher(x)
return matcher.find
}
def unapply(x:String):Option[String] = {
val pat = Pattern.compile("\\d+")
val matcher = pat.matcher(x)
if(matcher.find) {
return Some(matcher.group())
}
None
}
}
object x {
def main(args : Array[String]) : Unit = {
val strings = List("geo12","neo493","leo")
for(val string <- strings) {
string match {
case NumberMatcher(group) => println(group)
case _ => println ("no")
}
}
}
}
I wanted to add pattern matching for strings containing digits ( so I can learn more about pattern matching ), and in unapply I decided to return a Option[String]. However, in the println in the NumberMatcher case, group is seen as a String and not as an Option. Can you shed some light? The output produced when this is ran is:
12,493,no

Take a look at this example.
The unapply method returns Some value if it succeeded in extracting one, otherwise None. So internally the
case NumberMatcher(group) => println(group)
invokes unapply and looks whether it returns some value. If it does, we already have to true result and therefore no Option type remains. The pattern matching extracts the returned value from the option.

Related

Scala macros: Emit for comprehensions from macros

Trying to emit a for yield block from a blackbox macro, but I'm failing to understand how you can create the block with valid syntax.
So below source is a hardcoded param name as this block is later inserted inside a method that will have the matching param name. params is just params: Seq[c.universe.ValDef], enclosing the case class fields.
def extract(source: Source): Option[CaseClass] = { ... }
val extractors = accessors(c)(params) map {
case (nm, tpe) => {
val newTerm = TermName(nm.toString + "Opt")
q"""$newTerm <- DoStuff[$tpe].apply("$nm", source)"""
}
}
val extractorNames = accessors(c)(params) map {
case (nm, tpe) => TermName(nm.toString + "Opt")
}
This is basically taking a case class, and outputting a for yield black to basically recreate the case class from a comprehension.
Every field in the case class of the form name: Type is transformed to a set of extractors that yield the same case class instance back if the for comprehension is successful.
case class Test(id: Int, text: String)
Will be macro transformed to the following, where Extract is just a type class and Extract.apply[T : Extract] is just materialising the context bound with implicitly[Extract[T]]:
for {
idOpt <- Extract[Int].apply("id", source): Option[Int]
textOpt <- Extract[String].apply("text", source): Option[String]
} yield Test(idOpt, textOpt)
The problem comes in having to quote the inner for yield expressions with and output a <- b blocks.
def extract(source: Source): Option[$typeName] = {
for {(..$extractors)} yield $companion.apply(..$extractorNames)
}
The error is ';' expected but '<-' found, which is pretty obvious as a <- b is invalid Scala by itself. What is the correct way to generate and quasiquote the expression block such that the above would work?
Here is a list of all the different kinds of quasiquotes.
There you can see that to express the a <- b syntax you need the fq interpolator.
So that code will probably become:
val extractors = accessors(c)(params) map {
case (nm, tpe) => {
val newTerm = TermName(nm.toString + "Opt")
fq"""$newTerm <- DoStuff[$tpe].apply("$nm", source)"""
}
}
And then with the normal interpolator:
q"for (..$extractors) yield $companion.apply(..$extractorNames)"

Scala: Create object only if it doesn't exist yet

I'm new to Scala, and this probably a very simple question, but I'm struggling to figure out how to make an object only if one doesn't exist yet.
I would like to query a database, and find out if there's anything present, if so, store it in an object, otherwise create a new one. In Java I know that this would be something like
PushMessage push = null;
if(GetFromDatabase() == null) {
push = new PushMessaage(param1, param2...);
}
else {
push = GetFromDatabase();
}
But, how do I do this in Scala. When I try and do the same thing, it tells me that GetFromDatabase() doesn't conform to expected type Null. Similarly, I tried doing pattern matching and doing something like
val push = GetFromDatabase match {
case Some(pushMessage) => pushMessage
case None => new PushMessage(param1, param2...)
}
But, that also didn't work as it told me that
Constructor cannot be instantiated to expected type, found: Some[A], expected: PushMessage
So, how do I do this? Any and all help would be really appreciated.
I assume your GetFromDatabase returns either null or PushMessage, so in order to pattern match correctly, you need to wrap it into Option:
val push = Option(GetFromDatabase) match {
case Some(pushMessage) => pushMessage
case None => new PushMessage(param1, param2...)
}
Or (bad style, but gives an understanding of how it works):
// Option(null) === None, Option(notNull) === Some(notNull):
// same as `if (x ne null) Some(x) else None
val pushMaybe: Option[PushMessage] = Option(GetFromDatabase)
val push: PushMessage =
if (pushMaybe.isEmpty) new PushMessage(param1, param2...)
else pushMaybe.get
You can simplify it all with:
val push = Option(GetFromDatabase).getOrElse(new PushMessage(param1, param2...))
P.S. If GetFromDatabase isn't some external method, it's better to rewrite it as returning Option[PushMessage] instead of PushMessage, something like:
def getFromDatabase = {
val rs = driver.getResulSet(query)
if (!rs.isBeforeFirst()) None else Some(parse(rs))
}
Here's a little demonstration why "cool" things are not always cool. Let's see Scala generated code for two cases (I made them very simple):
def getMessage: String = null
val m = getMessage
val push = if (m == null) new AnyRef else m
=>
iw.this.m = iw.this.getMessage();
iw.this.push = if (iw.this.m().==(null))
new Object()
else
iw.this.m();
vs
def getMessage: String = null
val push = Option(getMessage) match {
case Some(x) => x
case None => new AnyRef
}
=>
iw.this.push = {
case <synthetic> val x1: Option = scala.Option.apply(iw.this.getMessage());
case6(){
if (x1.$isInstanceOf[Some]())
{
<synthetic> val x2: Some = (x1.$asInstanceOf[Some](): Some);
{
val x: String = x2.x().$asInstanceOf[String]();
matchEnd5(x)
}
}
else
case7()
};
case7(){
if (scala.None.==(x1))
matchEnd5(new Object())
else
case8()
};
case8(){
matchEnd5(throw new MatchError(x1))
};
matchEnd5(x: Object){
x
}
};
So as long as we are not propagating null (and we don't) I don't see any advantages of the second option.
UPDATE
As requested:
val path = Option(m).getOrElse(new AnyRef)
=>
final <artifact> private[this] def $anonfun$1(): Object = new Object();
...
iw.this.path = scala.Option.apply($line13.iw.m()).getOrElse({
(() => iw.this.$anonfun$1())
});
I wouldn't consider it much better than the second option above. getOrElse hides about the same logic, and we have anonymous function since getOrElse takes by-name argument.
In fact it's not just about saving cycles. Constructing and deconstructing Option object for the sake of avoiding local null? Or saving one line? I would totally accept it if we used Option for passing it further.

Filtering inside `for` with pattern matching

I am reading a TSV file and using using something like this:
case class Entry(entryType: Int, value: Int)
def filterEntries(): Iterator[Entry] = {
for {
line <- scala.io.Source.fromFile("filename").getLines()
} yield new Entry(line.split("\t").map(x => x.toInt))
}
Now I am both interested in filtering out entries whose entryType are set to 0 and ignoring lines with column count greater or lesser than 2 (that does not match the constructor). I was wondering if there's an idiomatic way to achieve this may be using pattern matching and unapply method in a companion object. The only thing I can think of is using .filter on the resulting iterator.
I will also accept solution not involving for loop but that returns Iterator[Entry]. They solutions must be tolerant to malformed inputs.
This is more state-of-arty:
package object liner {
implicit class R(val sc: StringContext) {
object r {
def unapplySeq(s: String): Option[Seq[String]] = sc.parts.mkString.r unapplySeq s
}
}
}
package liner {
case class Entry(entryType: Int, value: Int)
object I {
def unapply(s: String): Option[Int] = util.Try(s.toInt).toOption
}
object Test extends App {
def lines = List("1 2", "3", "", " 4 5 ", "junk", "0, 100000", "6 7 8")
def entries = lines flatMap {
case r"""\s*${I(i)}(\d+)\s+${I(j)}(\d+)\s*""" if i != 0 => Some(Entry(i, j))
case __________________________________________________ => None
}
Console println entries
}
}
Hopefully, the regex interpolator will make it into the standard distro soon, but this shows how easy it is to rig up. Also hopefully, a scanf-style interpolator will allow easy extraction with case f"$i%d".
I just started using the "elongated wildcard" in patterns to align the arrows.
There is a pupal or maybe larval regex macro:
https://github.com/som-snytt/regextractor
You can create variables in the head of the for-comprehension and then use a guard:
edit: ensure length of array
for {
line <- scala.io.Source.fromFile("filename").getLines()
arr = line.split("\t").map(x => x.toInt)
if arr.size == 2 && arr(0) != 0
} yield new Entry(arr(0), arr(1))
I have solved it using the following code:
import scala.util.{Try, Success}
val lines = List(
"1\t2",
"1\t",
"2",
"hello",
"1\t3"
)
case class Entry(val entryType: Int, val value: Int)
object Entry {
def unapply(line: String) = {
line.split("\t").map(x => Try(x.toInt)) match {
case Array(Success(entryType: Int), Success(value: Int)) => Some(Entry(entryType, value))
case _ =>
println("Malformed line: " + line)
None
}
}
}
for {
line <- lines
entryOption = Entry.unapply(line)
if entryOption.isDefined
} yield entryOption.get
The left hand side of a <- or = in a for-loop may be a fully-fledged pattern. So you may write this:
def filterEntries(): Iterator[Int] = for {
line <- scala.io.Source.fromFile("filename").getLines()
arr = line.split("\t").map(x => x.toInt)
if arr.size == 2
// now you may use pattern matching to extract the array
Array(entryType, value) = arr
if entryType == 0
} yield Entry(entryType, value)
Note that this solution will throw a NumberFormatException if a field is not convertible to an Int. If you do not want that, you'll have to encapsulate x.toInt with a Try and pattern match again.

How to make this first-not-null-result function more elegant/concise?

getFirstNotNullResult executes a list of functions, until one of them returns a not null value.
How to implement getNotNullFirstResult more elegantly/concise?
object A {
def main(args: Array[String]) {
println(test());
}
def test(): String = {
getFirstNotNullResult(f1 _ :: f2 _ :: f3 _ :: Nil);
}
def getFirstNotNullResult(fs: List[() => String]): String = {
fs match {
case head::tail =>
val v = head();
if (v != null) return v;
return getFirstNotNullResult(tail);
case Nil => null
}
}
// these would be some complex and slow functions; we only want to execute them if necessary; that is, if f1() returns not null, we don't want to execute f2 nor f3.
def f1(): String = { null }
def f2(): String = { "hello" }
def f3(): String = { null }
}
I like Rex's answer, but your question brings up so many things, I'd like to expand on it, to add:
Using Scala's Option/Some/None classes to clarify what should be returned when no match is found. Your example returned null, Rex's threw an exception. Using Option makes it immediately clear that we will return a match or "None".
Use type parameters so you don't have to operate just on functions that return a String.
Here's the code:
object A extends App {
def getFirstNNWithOption[T](fs: List[() => Option[T]]): Option[T] = fs
.view //allows us to evaluate your functions lazily: only evaluate as many as it takes to find a match
.flatMap(_()) //invoke the function, discarding results that return None
.headOption // take the first element from the view - returns None if empty
def f1 = { println("f1"); None }
def f2 = Some("yay!")
def f3 = { println("f2"); None }
println(getFirstNNWithOption(List(f1 _, f2 _, f3 _)))
}
Note that when this code runs, f2 never prints, demonstrating that, thanks to the .view call, we evaluate the minimum number of functions before returning a match.
Note that callers of this method now must consider the fact that a match might not be found: instead of returning T, we return Option[T]. In our case above, it would return Some("yay"). When all functions return None, the return value would be None. No more NullPointerExceptions when you mistake a null for an actual match!
def getFirstNN(fs: List[() => String]): String = fs.iterator.map(_()).find(_ ne null).get
You'll probably want the type passed into getFirstNotNullResult to be a Stream[String] instead of List[() => String] and construct it something like:
Stream.cons(f1, Stream.cons(f2, Stream.cons(f3, Stream.empty)))
Then getFirstNotNullResult changes to be:
fs.filter(_ != null).headOption
Which will also mean that it should really return Option[String] as well, as you can't guarantee that something will be non-null.
As suggested, the reason why I suggest a Stream is that it only evaluates the "tail" of the Stream on demand. So if getFirstNotNullResult finds that the first element is not null then the second parameter to the first Stream.cons call is never actually executed.

Can extractors be customized with parameters in the body of a case statement (or anywhere else that an extractor would be used)?

Basically, I would like to be able to build a custom extractor without having to store it in a variable prior to using it.
This isn't a real example of how I would use it, it would more likely be used in the case of a regular expression or some other string pattern like construct, but hopefully it explains what I'm looking for:
def someExtractorBuilder(arg:Boolean) = new {
def unapply(s:String):Option[String] = if(arg) Some(s) else None
}
//I would like to be able to use something like this
val {someExtractorBuilder(true)}(result) = "test"
"test" match {case {someExtractorBuilder(true)}(result) => result }
//instead I would have to do this:
val customExtractor = someExtractorBuilder(true)
val customExtractor(result) = "test"
"test" match {case customExtractor(result) => result}
When just doing a single custom extractor it doesn't make much difference, but if you were building a large list of extractors for a case statement, it could make things more difficult to read by separating all of the extractors from their usage.
I expect that the answer is no you can't do this, but I thought I'd ask around first :D
Parameterising extractors would be cool, but we don't have the resources to implement them right now.
Nope.
8.1.7 Extractor Patterns
An extractor pattern x (p 1 , . . . ,
p n ) where n ≥ 0 is of the same
syntactic form as a constructor
pattern. However, instead of a case
class, the stable identifier x denotes
an object which has a member method
named unapply or unapplySeq that
matches the pattern.
One can customize extractors to certain extent using implicit parameters, like this:
object SomeExtractorBuilder {
def unapply(s: String)(implicit arg: Boolean): Option[String] = if (arg) Some(s) else None
}
implicit val arg: Boolean = true
"x" match {
case SomeExtractorBuilder(result) =>
result
}
Unfortunately this cannot be used when you want to use different variants in one match, as all case statements are in the same scope. Still, it can be useful sometimes.
Late but there is a scalac plugin in one of my lib providing syntax ~(extractorWith(param), bindings):
x match {
case ~(parametrizedExtractor(param)) =>
"no binding"
case ~(parametrizedExtractor(param), (a, b)) =>
s"extracted bindings: $a, $b"
}
https://github.com/cchantep/acolyte/blob/master/scalac-plugin/readme.md
Though what you are asking isn't directly possible,
it is possible to create an extractor returning a contaner that gets evaluated value in the if-part of the case evaluation. In the if part it is possible to provide parameters.
object DateExtractor {
def unapply(in: String): Option[DateExtractor] = Some(new DateExtractor(in));
}
class DateExtractor(input:String){
var value:LocalDate=null;
def apply():LocalDate = value;
def apply(format: String):Boolean={
val formater=DateTimeFormatter.ofPattern(format);
try{
val parsed=formater.parse(input, TemporalQueries.localDate());
value=parsed
true;
} catch {
case e:Throwable=>{
false
}
}
}
}
Usage:
object DateExtractorUsage{
def main(args: Array[String]): Unit = {
"2009-12-31" match {
case DateExtractor(ext) if(ext("dd-MM-yyyy"))=>{
println("Found dd-MM-yyyy date:"+ext())
}
case DateExtractor(ext) if(ext("yyyy-MM-dd"))=>{
println("Found yyyy-MM-dd date:"+ext())
}
case _=>{
println("Unable to parse date")
}
}
}
}
This pattern preserves the PartialFunction nature of the piece of code. I find this useful since I am quite a fan of the collect/collectFirst methods, which take a partial function as a parameter and typically does not leave room for precreating a set of extractors.