tags:

views:

173

answers:

5

Is this an opportunity to make things a bit more efficient (for the prorammer): I find it gets a bit tiresome having to wrap things in Some, e.g. Some(5). What about something like this:

implicit def T2OptionT( x : T) : Option[T] = if ( x == null ) None else Some(x)
+1  A: 

It would seem that this could be confusing to other developers, as they read your code.

Generally, it seems, implicit works to help cast from one object to another, to cut out confusing casting code that can clutter code, but, if I have some variable and it somehow becomes a Some then that would seem to be bothersome.

You may want to put some code showing it being used, to see how confusing it would be.

James Black
I get your drift.. However, the point of Option[T] is that it can hold a value or a None, so it seems intuitive to me that if a method takes a variable of type Option[T] I should be able to pass a T into it. Can you think of an example where you might have some confusion, e.g. a variable becoming a Some inadvertently?
Alex Black
A: 

That looks good to me, except it may not work for a primitive T (which can't be null). I guess a non-specialized generic always gets boxed primitives, so probably it's fine.

wrang-wrang
+8  A: 

You would lose some type safety and possibly cause confusion. For example:

  val iThinkThisIsAList = 2 
  for (i <- iThinkThisIsAList) yield { i + 1 }

I (for whatever reason) thought I had a list, and it didn't get caught by the compiler when I iterated over it because it was auto-converted to an Option[Int].

I should add that I think this is a great implicit to have explicitly imported, just probably not a global default.

Mitch Blevins
ah, good catch, thx.
Alex Black
+7  A: 

Note that you could use the explicit implicit pattern which would avoid confusion and keep code terse at the same time.

What I mean by explicit implicit is rather than have a direct conversion from T to Option[T] you could have a conversion to a wrapper object which provides the means to do the conversion from T to Option[T].

class Optionable[T <: AnyRef](value: T) {
  def toOption: Option[T] = if ( value == null ) None else Some(value)
}

implicit def anyRefToOptionable[T <: AnyRef](value: T) = new Optionable(value)

... I might find a better name for it than Optionable, but now you can write code like:

val x: String = "foo"
x.toOption // Some("foo")

val y: String = null
x.toOption // None

I believe that this way is fully transparent and aids in the understanding of the written code - eliminating all checks for null in a nice way.

Note the T <: AnyRef - you should only do this implicit conversion for types that allow null values, which by definition are reference types.

Hope it helps :)

-- Flaviu Cipcigan

Flaviu Cipcigan
Hi Flaviu, interesting suggestion. I like it overall - though I think it makes my problem worse not better, now instead of typing Some() I have to type toOption... but it does have the advantage of working with null.
Alex Black
+3  A: 

The general guidelines for implicit conversions are as follows:

  • When you need to add members to a type (a la "open classes"; aka the "pimp my library" pattern), convert to a new type which extends AnyRef and which only defines the members you need.
  • When you need to "correct" an inheritance hierarchy. Thus, you have some type A which should have subclassed B, but didn't for some reason. In that case, you can define an implicit conversion from A to B.

These are the only cases where it is appropriate to define an implicit conversion. Any other conversion runs into type safety and correctness issues in a hurry.

It really doesn't make any sense for T to extend Option[T], and obviously the purpose of the conversion is not simply the addition of members. Thus, such a conversion would be inadvisable.

Daniel Spiewak