"orElse" for empty collections?

7,656 views
Skip to first unread message

JND

unread,
Mar 10, 2012, 9:54:47 AM3/10/12
to scala...@googlegroups.com
Hi all,

Is there an idiomatic convention for achieving this effect ("orElse") with the Scala library:

List("A", "B", "C").orElse("Default element") = List("A", B", "C")
List[String]().orElse("Default element") = List("Default element")
Nil || "Default element" = List("Default element")

The use-case is user interfaces, where a list containing a default element should be emitted instead of an empty list.

Cheers!

JND

unread,
Mar 10, 2012, 9:58:10 AM3/10/12
to scala...@googlegroups.com
On Saturday, March 10, 2012 10:54:47 PM UTC+8, JND wrote:
Is there an idiomatic convention for achieving this effect ("orElse") with the Scala library:
 
Of course there actually is a def called "orElse" for PartialFunctions but I'm not sure if this is actually the right thing to use.

Vlad Patryshev

unread,
Mar 10, 2012, 2:39:55 PM3/10/12
to JND, scala...@googlegroups.com
I would not call it a list. List has a pretty specific definition (a fixpoint for 1+TxX).
You probably will have to add a couple of classes and a couple of implicits to provide (pimp) this functionality.

Thanks,
-Vlad

Eugen Labun

unread,
Mar 10, 2012, 3:20:13 PM3/10/12
to scala...@googlegroups.com
> The use-case is user interfaces, where a list containing a default element should be emitted instead
> of an empty list.

How should the definition of that interface look like?

Christopher Currie

unread,
Mar 10, 2012, 3:46:22 PM3/10/12
to JND, scala...@googlegroups.com
On Sat, Mar 10, 2012 at 6:54 AM, JND <jndev...@gmail.com> wrote:
> Is there an idiomatic convention for achieving this effect ("orElse") with
> the Scala library:
>
> List("A", "B", "C").orElse("Default element") = List("A", B", "C")
> List[String]().orElse("Default element") = List("Default element")
> Nil || "Default element" = List("Default element")

The cleanest way I could think to do this is:

Option(List("A", "B', "C")).filterNot(_.isEmpty).getOrElse(List("Default"))

If you find yourself doing this a lot it's probably worth writing a pimp for it.

√iktor Ҡlang

unread,
Mar 10, 2012, 4:55:15 PM3/10/12
to Christopher Currie, JND, scala...@googlegroups.com
On Sat, Mar 10, 2012 at 9:46 PM, Christopher Currie <chris...@currie.com> wrote:
On Sat, Mar 10, 2012 at 6:54 AM, JND <jndev...@gmail.com> wrote:
> Is there an idiomatic convention for achieving this effect ("orElse") with
> the Scala library:
>
> List("A", "B", "C").orElse("Default element") = List("A", B", "C")
> List[String]().orElse("Default element") = List("Default element")
> Nil || "Default element" = List("Default element")

The cleanest way I could think to do this is:

Option(List("A", "B', "C")).filterNot(_.isEmpty).getOrElse(List("Default"))

List("A", "B', "C") match {
  case Nil => List("Default")
  case other => other
}
 

If you find yourself doing this a lot it's probably worth writing a pimp for it.



--
Viktor Klang

Akka Tech Lead
Typesafe - The software stack for applications that scale

Twitter: @viktorklang

Kevin Wright

unread,
Mar 10, 2012, 6:05:55 PM3/10/12
to √iktor Ҡlang, Christopher Currie, JND, scala...@googlegroups.com
Or even:

if(someList.isEmpty) List("Default") else someList

I doubt there'd be any appreciable difference performance-wise though.



2012/3/10 √iktor Ҡlang <viktor...@gmail.com>



--
Kevin Wright
mail: kevin....@scalatechnology.com
gtalk / msn : kev.lee...@gmail.com
vibe / skype: kev.lee.wright
steam: kev_lee_wright

"My point today is that, if we wish to count lines of code, we should not regard them as "lines produced" but as "lines spent": the current conventional wisdom is so foolish as to book that count on the wrong side of the ledger" ~ Dijkstra

Tony Morris

unread,
Mar 11, 2012, 4:06:00 AM3/11/12
to JND, scala...@googlegroups.com

See Scalaz.

Option.orElse generalises to a semigroup and a default element is the identity for any monoid.

Vlad Patryshev

unread,
Mar 11, 2012, 1:03:40 PM3/11/12
to Tony Morris, JND, scala...@googlegroups.com
On Sun, Mar 11, 2012 at 12:06 AM, Tony Morris <tmo...@tmorris.net> wrote:

See Scalaz.

Option.orElse generalises to a semigroup and a default element is the identity for any monoid


Oh. Talking about monoids. What do you think of the habits of popular mapreduce implementations to return an empty resultset if you, say, count the number of records in an empty dataset? I'm still struggling figuring out what kind of monoid this can possibly be. It must be a monoid, or else the whole mapreduce thing makes no sense.

Luke Vilnis

unread,
Mar 11, 2012, 5:01:56 PM3/11/12
to Vlad Patryshev, Tony Morris, JND, scala...@googlegroups.com
This might be overkill, but if you really wanted a special data structure to deal with this funny default behavior you could do something like:

  sealed abstract class ListWithDefault[+A] {
    def toList: List[A]
  }

  case class ListDefault[A](default: A)
    extends ListWithDefault[A] {
    def toList: List[A] = List(default)
  }

  case class ConsWithDefault[+A](hd: A, tl: ListWithDefault[A])
    extends ListWithDefault[A] {
    def toList: List[A] = hd :: (tl match {
      case ConsWithDefault(_, _) => tl.toList
      case _ => Nil
    })
  }

  object ListWithDefault {
    def fromList[A](xs: List[A], default: A): ListWithDefault[A] =
      xs.foldRight(ListDefault(default): ListWithDefault[A])(ConsWithDefault(_, _))
  }

  def main(args: Array[String]) {
    assert(ListWithDefault.fromList(List("A", "B", "C"), "Default element").toList == List("A", "B", "C"))
    assert(ListWithDefault.fromList(List[String](), "Default element").toList == List("Default element"))
    assert(ListWithDefault.fromList(Nil, "Default element").toList== List("Default element"))
  }

It's sort of a funny variant on a NonEmptyList. And you could add map, flatmap, filter, etc. methods on it, or an apply method on the companion object, as you wished.

Thanks,
Luke

ps. Pardon any mistakes, I'm still learning Scala

Tony Morris

unread,
Mar 11, 2012, 6:58:38 PM3/11/12
to Vlad Patryshev, JND, scala...@googlegroups.com

I'm not sure what you mean. Option.orElse and same again but flipped both form a monoid with an identity of None. They might be called "the first option monoid" and "the last option monoid" or something like that.

Do you mean something else?

Chris Marshall

unread,
Mar 16, 2012, 11:05:24 AM3/16/12
to jndev...@gmail.com, scala...@googlegroups.com
scala> import scalaz._; import Scalaz._
import scalaz._
import Scalaz._

scala> List(1, 2, 3).toNel
res8: Option[scalaz.NonEmptyList[Int]] = Some(NonEmptyList(1, 2, 3))

scala> nil[Int].toNel
res9: Option[scalaz.NonEmptyList[Int]] = None

scala> List("Hello", "World") <^> (_.foldMap(_.length))
res12: Int = 10

scala> nil[String] <^> (_.foldMap(_.length))
res13: Int = 0



Date: Sat, 10 Mar 2012 06:54:47 -0800
From: jndev...@gmail.com
To: scala...@googlegroups.com
Subject: [scala-user] "orElse" for empty collections?
Reply all
Reply to author
Forward
0 new messages