Handling Option[A] where function takes A as a parameter - scala

I have a case class Foo which has a field baz: Option[List[Bar]].
Also, I have a function - def f(baz: List[Bar])
I need to pass the List[Bar] to f().
What would be the best way to do this?

Option is great because it forces you to come to grips when there is no item. In the case of a List, Option may be overkill as there already exists a corresponding empty, i.e. they are both Monads:
f(myOptList getOrElse Nil)
wherein I'd say you should probably only have a List ever. Otherwise you deal with a trinary case: Something that is empty, something that has items and empty.

case class Baz(b: Int)
case class Foo(bazs: Option[List[Baz]])
val foo = Foo(Option(List(Baz(1), Baz(2))))
foo.bazs.map(list => f(list))
Option is a monad, if it's a Some the map will we applied to it, else if it's a None nothing will happen, from the REPL:
scala> def f(b: List[Baz]) = b.foreach(println)
f: (b: List[Baz])Unit
scala> foo.bazs.map(list => f(list))
Baz(1)
Baz(2)
res1: Option[Unit] = Some(())
scala> val foo = Foo(None)
foo: Foo = Foo(None)
scala> foo.bazs.map(list => f(list))
res2: Option[Unit] = None

Related

Scala: read "from outside in" instead of "inside out"

I have something that looks like this:
def a(b:String)(implicit c:String = "") = {println(b); b}
a("1")(a("2")(a("3")))
which prints
3
2
1
How can I get scala to print out this instead?
1
2
3
Laziness is always the way to go to invoke code not before it is used. In your example, though, you are not using c at all, which would mean that when it is lazy it would never be invoked at all.
Changing this a little bit would result in:
scala> def a(b: String)(c: => String = "") = {println(b); c; b}
a: (b: String)(c: => String)String
scala> a("1")(a("2")(a("3")()))
1
2
3
res15: String = 1
Here, c is declared as call-by-name, which results in the lazy behavior. However implicit parameters can't be call-by-name, thus we have to use a more heavyweight approach:
scala> import scala.language.implicitConversions
import scala.language.implicitConversions
scala> def a(b: String)(implicit c: () => String = () => "") = {println(b); c(); b}
a: (b: String)(implicit c: () => String)String
scala> implicit def conv(s: => String) = () => s
conv: (s: => String)() => String
scala> a("1")(a("2")(a("3")))
1
2
3
res0: String = 1
Now, the laziness is even more explicit but we need an implicit conversion to allow your original syntax.
In summary you can't just toggle the evaluating order of your function arguments, you have to understand laziness to benefit from it. Nevertheless laziness comes with syntactic overhead (at least in Scala, in Haskell for example it would already be built-in into the language), therefore it leads to a different design of your code.

Add a parameter to a case class with a default

I have an existing case class, to which I'd like to add an additional constructor parameter, with a default value, and not disturb existing code that does pattern matching, yet I can't figure out the right approach.
Ie. I have:
case class Foo(a: Int, b: Int)
def bar(n: Foo) = n match {
case Foo(1, 2) => true
case _ => false
}
Now suppose I need to add an additional parameter, c, to Foo. Ie.
case class Foo(a: Int, b: Int, c: Boolean = true)
In all existing use cases, the parameter c would be true, hence it has that default value. Yet in some new use cases, there is a need to pass false for this.
So it seems sensible to add another parameter, with a default value of true. Yet as soon as I do this, the pattern match in bar becomes a syntax error. This seems wrong, since I added the default = true to ensure that existing constructor calls wouldn't need to be modified.
How can I do this and leave the old pattern matches unchanged?
Update: Note that I also don't want to have to rewrite all the existing instantiations of Foo. #som-snytt pointed out that I could add another parameter as Foo(a: Int, b: Int)(c: Boolean = true), which would be perfect except that it causes existing calls, such as Foo(1,2) to fail (they have to be rewritten as Foo(1,2)()). I'm looking for a way to add a new parameter only for some use-cases, and avoid rewriting by having a default which works for everywhere else.
The case Foo syntax is not calling a constructor, rather a method called unapply on object Foo. case classes autogenerate various boilerplate including the companion object and the unapply.
unapply only has one parameter, the object being matched. This keeps you from overloading it since you can't overload on return value in Java/Scala.
So in short you can't do quite what you want.
You can, however, make an extractor with a different name. Here's someone who just added an underscore:
http://x3ro.de/multiple-unapply-methods-for-pattern-matching-in-scala/
perhaps it would be nicer when possible to use a more meaningful name for the extractor variants though.
Here's some more info on how it all works:
http://danielwestheide.com/blog/2012/11/21/the-neophytes-guide-to-scala-part-1-extractors.html
You can write out everything a case class does "by hand" and do it differently, such as a different unapply, but it would be pretty annoying assuming you care about equals, hashCode, toString, and all that. If you did that you could maybe avoid having to change existing code but it seems unlikely to be worth it.
Here is an example someone posted:
https://gist.github.com/okapies/2814608
Maybe you can live with case class Foo(a: Int, b: Int)(val c: Boolean = true).
Update: if you could almost live with that, because you don't want to use the extra param in patterns, then you can make short work of it.
package fooplusplus
case class Foo(a: Int, b: Int) {
def c: Boolean = true
}
object Foo {
def apply(a: Int, b: Int, c: Boolean): Foo =
new {
private[this] val x = c // http://stackoverflow.com/a/12239654
} with Foo(a, b) {
override def c = x
}
}
object Test extends App {
def bar(x: Foo) = x match {
case Foo(1, 2) if !x.c => 3
case Foo(1, 2) => 2 // existing code
case _ => 1
}
Console println bar(Foo(1, 2))
Console println bar(Foo(1, 2, c = false))
Console println bar(Foo(0, 2))
}
If you do want pattern matching with the new param, here is one way:
case class EnhancedFoo(a: Int, b: Int, c: Boolean)
class Foo(a: Int, b: Int, c: Boolean) extends EnhancedFoo(a, b, c)
object Foo {
def apply(a: Int, b: Int, c: Boolean = true): Foo = new Foo(a, b, c)
def unapply(x: Foo): Option[(Int, Int)] = Some(x.a, x.b)
}
object Test extends App {
def bar(x: EnhancedFoo) = x match {
case EnhancedFoo(1, 2, true) => 3
case Foo(1, 2) => 2 // existing code
case _ => 1
}
Console println bar(Foo(1, 2))
Console println bar(Foo(1, 2, c = false))
Console println bar(Foo(0, 2))
}
Since we haven't done anything truly whacky yet, how about the following:
scala> case class Foo(a: Int, b: Int, c: Boolean*)
defined class Foo
scala> import PartialFunction._
import PartialFunction._
scala> val foo = Foo(1,2)
f: Foo = Foo(1,2,WrappedArray())
scala> val goo = Foo(1,2,true)
g: Foo = Foo(1,2,WrappedArray(true))
scala> cond(foo) { case Foo(1,2) => true }
res0: Boolean = true
scala> cond(goo) { case Foo(1,2,false) => true }
res1: Boolean = false
The boolean becomes tri-state, defaulting to old-style empty.
scala> cond(foo) { case Foo(1,2, _ # _*) => true }
res2: Boolean = true
scala> cond(foo) { case Foo(1,2, x) => true }
res3: Boolean = false
scala> cond(goo) { case Foo(1,2, x # _*) if x exists identity => true }
res4: Boolean = true

Hiding closure boilerplate with macros?

Given an example closure, which in this case returns the number of words in a string (with an additional arbitrary operator).
val myfunc = (s: String) => Option(s).map(_.split(" ").size).filter(_ >= 2)
Is there a way I can hide some of the boilerplate such that I can write:
val myfunc = given[String].map(_.split(" ").size).filter(_ >= 2)
If you can live with two parentheses and an underscore extra, you don't need macros for that:
class Given[A] {
def apply[B](f: Option[A] => B): A => B = (a: A) => f(Option(a))
}
def given[A] = new Given[A]
In action:
scala> val myfunc = given[String](_.map(_.split(" ").size).filter(_ >= 2))
myfunc: String => Option[Int] = <function1>
scala> List("salmon cod herring","tuna").map(myfunc)
res4: List[Option[Int]] = List(Some(3), None)
I doubt. A macro replaces the function call it is in with something that type checks. So, what would you replace given[String] with in your example? If you replaced it with (s: String) => Option(s), you'd get this:
((s: String) => Option(s)).map(_.split(" ").size).filter(_ >= 2)
Which doesn't work like you want. You want the whole line to be changed, which is not going to happen.

Is there a way to extract the item type from a Manifest[List[X]] in Scala?

I know something is a List[_] based on the Manifest I've passed into a method, but I need to know what kind of item the list is. Is that information stored in the Manifest somewhere and can you get it out? If not, any suggestions about how to work around the issue?
(Basically, I have a Map[Manifest[_], Blah], where Blah handles cases based on the class type. Handling List[X] is composable based on X, but I need to be able to figure out what X is so I can grab its Blah value out of the map.)
Thanks!
I think you're looking for typeArguments
scala> manifest[List[Int]]
res1: Manifest[List[Int]] = scala.collection.immutable.List[Int]
scala> res1.typeArguments
res2: List[scala.reflect.Manifest[_]] = List(Int)
scala> res2.head
res3: scala.reflect.Manifest[_] = Int
scala> res3.erasure
res4: java.lang.Class[_] = int
It is hard to tell you what to do, without a piece of example code. So from what you wrote I assume you get an A[B] as parameter. This should work like this:
def foo[A[B], B](x: A[B])(implicit outer: ClassManifest[A[B]], inner: ClassManifest[B]) = {
// your code here
}
So you have a Manifest[List[T]] and want to handle based on T? How about
def listType[T](m: Manifest[T]) =
if (m.erasure == classOf[List[_]]) m.typeArguments match {
case List(c) if c.erasure == classOf[Int] => "it's a List[Int]"
case List(c) if c.erasure == classOf[String] => "it's a List[String]"
case _ => "some other List"
} else "not a List"
scala> listType(implicitly[Manifest[List[Int]]])
res29: java.lang.String = it's a List[Int]

Is there anything like Haskell's 'maybe' function built into Scala?

What I'm looking for is this function:
def maybe[A, B](a: Option[A])(f: A => B)(g: () => B): B = a match
{
case Some(x) => f(x)
case None => g()
}
It's in the Haskell prelude so I'm thinking it might be in the Scala standard library somewhere and I've just missed it. I hate having to recode it in projects so I'm wondering if anyone knows where it is, or if it's definitively not there. Or is there a better method for getting this functionality?
Other answers have given the map + getOrElse composition. Just for the record, you can "add" a maybe function to Option in the following way:
implicit def optionWithMaybe[A](opt: Option[A]) = new {
def maybe[B](f: A=>B)(g: =>B) = opt map f getOrElse g
}
It's worth noting that the syntax of higher-order functions in Scala is usually nicer when the function parameter comes last. Thus, a better way to organize maybe would be as follows:
def maybe[B](g: =>B)(f: A=>B) = opt map f getOrElse g
This could be used as follows:
val opt: Option[String] = ...
opt.maybe("") { _.toUpperCase }
You could do
val opt:Option[A] = // ...
val result:B = opt.map(f).getOrElse(g());
getOrElse takes a by-name parameter, so g will only be evaluated if opt is None.
The method would be called fold if it were to adhere to convention (see Either.fold which is the catamorphism for Either).
You can use scalaz, and then you have an implicit conversion to OptionW which has fold, or you can use Scala 2.10.0-M3 and use the builtin Option.fold
scala> Some(1).fold(5)(_ * 2)
res5: Int = 2
scala> (None: Option[Int]).fold(5)(_ * 2)
res7: Int = 5
Note that the scalaz fold signature is fold[X](some: A => X, none: => X), while the builtin seems to be fold[X](none: => X)(some: A => X).
I don't think there is. The best I could come up with is to chain Option's "map" and "getOrElse" together:
scala> var a: Option[String] = Some("hello")
a: Option[String] = Some(hello)
scala> a.map(_.toUpperCase).getOrElse("empty")
res19: java.lang.String = HELLO
scala> a = None
a: Option[String] = None
scala> a.map(_.toUpperCase).getOrElse("empty")
res21: java.lang.String = empty
I don't think there is. However, I'd write it to take g by name:
def maybe[A, B](a: Option[A])(f: A => B)(g: => B): B = a.map(f).getOrElse(g)
This is more Scala- and Haskell-like and a bit nicer to use.
I'd use Option.fold for this:
opt.fold(g)(f)
Note that g is by-name, just like getOrElse. Also note the inversion of the cases.