Automatically wrap parameters in Options - scala

On many occasions I use parameters in form of the Option with None as default - like this:
def foo(bar:Option[String] = None)
This gets handy and allows me to easily omit nulls. However, if I do this, I need to change every invocation of the method to
foo(Some("bar"))
instead of simply
foo("bar")
This, however, looks a bit redundant, because it is obvious, that when I specify a value it is a full option. I'm pretty sure I can try to write some implicit converters to do such wrapping for me - unfortunately, I have no idea how.
Bonus - is this a sane thing to do? Is there any other way of dealing with a problem of "nullable" parameters?

I'll give you some options (pun intended).
Don't use an optional parameter, and instead use Option.apply. This is useful for when the parameter isn't necessarily optional, but you want to deal with possible null values being passed.
def foo(bar: String): ?? = Option(bar)... // operate on the Option[String]
The advantage of this is that Option.apply automatically converts null to None for you, so there's absolutely no need to use if/else.
Use an overload for non-optional parameters. This is more so for when the parameter is truly optional, but gives you the convenience of passing Option wrapped or unwrapped. It won't be possible to pass null here without knowing the type first, however.
def foo(bar: String): ?? = foo(Option(bar))
def foo(bar: Option[String]): ?? = ???
Example:
def foo(bar: String): Option[String] = foo(Option(bar))
def foo(bar: Option[String]): Option[String] = bar.map(_ + "aaa")
scala> foo("bbb")
res7: Option[String] = Some(bbbaaa)
scala> foo(null: String) // The String ascription is necessary here.
res9: Option[String] = None
scala> val str: String = null
scala> foo(str) // No ascription necessary, since we know the type.
res10: Option[String] = None
Implicitly convert anything to Option.
implicit def any2Opt[A](value: A): Option[A] = Option(value)
And keep the current definintion of
def foo(bar: Option[String]): ?? = ???
Implicitly converting to Option, however can result in some unexpected results, so be wary.

You can write the desired generic implicit as
implicit def wrapToOption[T](x: T) = Option[T](x)
Then you can do
def foo(bar: Option[String] = None) = println(bar)
foo("bar") //> Some(bar)
foo() //> None
def fooBar(bar: Option[Int] = None) = println(bar)
fooBar(2) //> Some(2)
About it being sane thing to do, I will say no(personal opinion). Implicits are notoriously hard to debug. A logic gone wrong in the implicits can make your life hell.
Also, each new addition to the team will have to taught about all these "magics" happening behind the scenes.

It is a perfectly reasonable approach to set the type of your parameters to Option[_], if they really can be optional. However, I do not recommend using implicits to convert directly to Option[_].
You can make the syntax a little easier on the eye by including Scalaz and using some:
foo("hello".some)
If you don't want to bring in Scalaz just for that it's very easy to write your own implicit to do so. This implicit is better because you explicitly call the some method to "trigger" the implicit, as opposed to a "magical" conversion.
Another alternative, if you often call a function with parameters set to Some[_] is to overload it (again, I'm not a fan of overloading either):
def foo(x: Option[String] = None, y: Option[Int] = None, z: Option[String] = None) { /* do stuff */ }
def foo(x: String, y: Int, z: Option[String] = None) = foo(x.some, y.some, z)
On a final note, I don't think there is anything wrong with wrapping your arguments in Some if the function clearly defines them as optional. I wouldn't worry to much about this syntax.

you can define an implicit converter as :
implicit def conv(str: String): Option[String] = {
if (str == null) None else Some(str)
}
def foo(bar: Option[String] = None) = {
bar
}
Output:
scala> foo("xyz")
res55: Option[String] = Some(xyz)
scala> foo()
res1: Option[String] = None

Implicitly converting everything to an Option is a dangerous game that I would avoid! You might prefer simply having some method overloads:
object Foos {
private def foo(bar: Option[String]): Unit = println(bar.getOrElse("foobar"))
def foo(bar: String): Unit = foo(Some(bar))
def foo(): Unit = foo(None)
}
And then you can do:
Foos.foo("barfoo") //prints "barfoo"
Foos.foo() //prints "foobar"
While still only really implementing the method once. Furthermore, you can hide the Option overload this way.

Related

Convert Option[String] to Map[String,trait] in SCALA

I am new to Scala and searched for the same as to how can we change from Option[String] to a Map[String,trait] but could not find much .
The thing is I have a field of type Option[String] and I have to pass that value to a case class which takes input as a Map[String,User Defined trait].
That's what I want to know as to how can I convert the value of Option[String] to Map[]
Can we use Option.fold in this?
Could you please guide me further on this.
TIA
Consider using toMap as shown in the following example:
trait UDTrait[A] {
def len(s: A): Int
}
case class MyClass(m: Map[String, UDTrait[String]])
def myOptionToMap(opt: Option[String]): Map[String, UDTrait[String]] =
opt.map((_, new UDTrait[String]{ def len(s: String) = s.length })).toMap
MyClass(myOptionToMap(Some("a")))
// res1: MyClass = MyClass(Map(a -> $anonfun$myOptionToMap$1$$anon$1#10aabada))
MyClass(myOptionToMap(None))
// res2: MyClass = MyClass(Map())
Alternatively, you can use fold, as follows:
def myOptionToMap(opt: Option[String]): Map[String, UDTrait[String]] =
opt.fold(Map.empty[String, UDTrait[String]])(s =>
Map(s -> new UDTrait[String]{ def len(s: String) = s.length })
)
Option[ T ] is a container for zero or one element of a given type. An Option[T] can be either Some[T] or None object, which represents a missing value.
A Map is an Iterable consisting of pairs of keys and values. If you want to construct a map with one key value pair from an option which is non-empty, you can do the following:
trait Foo
def convertNonEmptyOptionToMap(a:Some[String], t: Foo): Map[String, Foo] = Map(a.get -> t)
That said, I don't completely understand what you're trying to do. More context with examples would be helpful.

Scala - implicit conversion from T to Some[T]

Consider this piece of code
def foo(b: Int) = ???
val a = 3
foo(a)
It works fine of course, but let's say that later I decided that foo should support an empty input, so I change it's signature to
def foo(b: Option[Int]) = ???
Now foo(a) won't compile, because a isn't an Option[Int], it's an Int. So you have to say a = Some(3) or foo(Some(a)), which seems redundant to me.
My question is, why doesn't the language have an implicit conversion from T to Some[T] (and vice versa)?
Is it a good idea to implement one yourself?

Lifting Functions using Cats Functor

with Cats, I can write this simple program
def foo(x: Int) = x + 1
val bar = Functor[Future](foo)
and Now I can do a bar(future(1)) and get a Future.Success(2) as a result. Very good.
But suppose my function was
def foo[T](x: T)(implicit m: Manifest[T]) : String = {...}
Now if I try to lift this function
def futureFoo = Functor[Future].lift(foo)
I get a compiler error No Manifest available for T.
So how do I lift this function?
I searched and found this thread (which is for scalaz)
Lifting a function which takes implicit parameter using functor (Scalaz7)
But I still couldn't create anything which worked for me. I tried
val futureFoo = Functor[T].lift2(foo[T] _)
but this doesn't compile
Functions in Scala cannot have implicit parameters, so when you try to eta-expand a method with an implicit parameter into a function, the implicit needs to be resolved before the function itself is applied. That is, at the time of eta-expansion. The compiler doesn't have a generic Manifest[T] in scope, but futureFoo can require one.
def foo[T](x: T)(implicit m: Manifest[T]) : String = ""
scala> def optionFoo[T: Manifest] = Functor[Option].lift(foo[T] _)
optionFoo: [T](implicit evidence$1: Manifest[T])Option[T] => Option[String]
I used Option because I didn't have a Functor[Future] readily available, the the same concept applies. Note that in order to use this, you'll need to supply the type parameter manually for it to return the correct function.
scala> optionFoo[Int].apply(Option(1))
res2: Option[String] = Some()

REPL could not find implicit

Hi I have an implicit method like:
implicit def strToOpt(str: String): Option[String] = Option(str)
and it works for simple conversion, but when I type
implicitly[String]
I get
error: could not find implicit value for parameter e: String
Does REPL have some limitations in term of finding implicits?
I think you have misunderstood implicitly. It is defined as:
def implicitly[T](implicit e: T): T = e
Which roughly means, that implicitly[T] will return you an object of type T which is available in current scope (scope is not the precise word. Compiler looks at many places)
In your case doing implicitly[String] simply means that some object of type String is available.
For example this is valid:
scala> implicit val x = "Hey"
x: String = Hey
scala> implicitly[String]
res12: String = Hey
But what you rather need to do is:
scala> implicitly[(String) => Option[String]]
res10: String => Option[String] = <function1>
scala> res10("asd")
res11: Option[String] = Some(456)
PS: Note answer by #Ende Neu works as:
implicitly[Option[String]]("123")
Doing implicitly[Option[String]]("123"), in the implicitly function it takes T as argument which is String. But you have manually provided Option[String] as type parameter of method. So the compiler searches for a function again (by using implicitly again) that does String => Option[String] which it finds in your function.

Scala short and type safe cast operator

I don't like Scala isInstanceOf and asInstanceOf methods - they are long and asInstanceOf can throw exception so we need to use it in couple. Better way is to use pattern matching: Scala: How do I cast a variable? but for really simple operations it can be relatively long too. In C# we have 'is' and 'as' operators so I wanted to implement implicit definition with this in Scala. My code look like this:
scala> class TypeCast(x:Any){
| def is[T](t:Class[T]) = t.isInstance(x)
| def as[T](t:Class[T]):Option[T] = if(t.isInstance(x)) Option(t.cast(x)) else None
| }
defined class TypeCast
scala> implicit def TypeCastID(x:Any)=new TypeCast(x)
TypeCastID: (x: Any)TypeCast
scala> 123 as classOf[String]
res14: Option[String] = None
scala> "asd" as classOf[String]
res15: Option[String] = Some(asd)
It has one advantage - implement null-object pattern but also have disadvantages:
need to use classOf[T] operator - it's too long
overhead connected with implicit def for such simple operation
so there is no practical reason to use it.
I would like to know is there any way to implement this without need to use classOf[T]?
Well you could shorten it down inside the def you made in the TypeCast class. So instead of feeding it a parameter you could just rely on the type. This would shorten it down a lot. As an example this could look something like:
class TypeCast(x : Any) {
def is[T : Manifest] = manifest.erasure.isInstance(x)
def as[T : Manifest] : Option[T] = if (manifest.erasure.isInstance(x)) Some(x.asInstanceOf[T]) else None
}
Future calls could look like:
scala> 123.as[String]
res0: Option[String] = Some(123)
scala> class A; class B extends A
defined class A
defined class B
scala> new B
res1: B
scala> res1.is[Int]
res2: Boolean = false
scala> res1.as[Int]
res3: Option[Int] = None
Update: I added Manifests to avoid type-check errors