Option.fold proposal

713 views
Skip to first unread message

Jeff Olson

unread,
Apr 4, 2012, 12:27:42 PM4/4/12
to scala-l...@googlegroups.com
With all the awesome new features going into Scala 2.10, I wonder if we could sneak in one minor but important enhancement to the standard Option class:

abstract class Option[+A] {
  @inline final def fold[B](some: A => B, none: => B): B = if (isEmpty) none else some(this.get)
  // ...
}

People have oft wondered and inquired as to why this method is not included:

This question is typically (*not*) answered in one of the following two ways:

1. You can add it yourself with the "pimp my library" pattern (or import a library, such as Scalaz, that does this for you)

However, the same can be said of every other method on Option, so why not get rid of them all? 'fold' is a (arguably "the") fundamental method on the Option class and deserves to be a first class citizen. We have it on Either and List after all--why no love for Option? Besides, I don't want every little Scala script I write to depend on Scalaz.

2. You can already express opt.fold(some, none) at least a dozen different ways:

  opt match { case None => none ; case Some(x) => some(x) }
  if (opt.isEmpty) none else some(opt.get)
  opt.map(some).getOrElse(none)
  opt.foldLeft(none)((_,x) => some(x))
  opt.foldRight(none)((x,_) => some(x))
  (none /: opt)((_,x) => some(x))
  (opt :\ none)((x,_) => some(x))
  opt.toLeft().fold(some, _ => none)
  opt.toRight().fold(_ => none, some)
  opt.toLeft(none).fold(some, identity)
  opt.toRight(none).fold(identity, some)

Alas, I find all the alternatives too verbose, too inefficient, or simply too ugly. Except for the first, they all create unnecessary temporary objects, and/or make an unnecessary number of method calls, and/or involve 'opt' more than once (making it impossible to drop in an expression which you only want evaluated once). The first is just too damn verbose.

So rather than asking why it is not there (I suspect that it was simply an oversight), I would like to formally request that it be added to the standard library.

I believe the impact will be minimal. The only compatibility issue I can think of is the off-chance that someone is using a pimp with the same name and a compatible signature but differing semantics (e.g. passing 'none' by-value instead of by-name). Of course this is an issue when adding any method to the standard library and I think the chances for collisions here are extremely small. 

The advantages of adding 'fold' are numerous:
* shorter, more concise code
* the library (and language) will feel a little more complete and consistent
* obvious pedagogical advantages to teaching algebraic data types in Scala (c.f. http://blog.tmorris.net/further-understanding-scalaoption/)
* people (like me) will stop wasting countless hours wondering and asking why it isn't there

The only clear disadvantage I can think of is that if it overused, or used inappropriately it could lead to difficult to read code. Of course, the same can be said of many methods already in the standard library. Naming the method 'fold' might also lead people to wonder "why--what does it have to do with a list.fold?" (actually, I think that's an advantage in disguise--at least if you are pro-education--anyone who pursues that question will learn something).

Cheers, Jeff

P.S. Can be please not bike-shed this proposal to death by arguing over the method name, the name or ordering of the parameters, whether to curry or not, etc, etc, etc? I don't really care about these details. I simply choose a name and signature compatible with Scalaz.

Josh Suereth

unread,
Apr 4, 2012, 12:32:35 PM4/4/12
to scala-l...@googlegroups.com
I'd be for adding it.


- Josh

Rex Kerr

unread,
Apr 4, 2012, 12:58:22 PM4/4/12
to scala-l...@googlegroups.com
I'm in favor, but I think the bike-shedding is important, actually.

I would prefer the same order as the list fold:

  def fold[B](none: => B)(some: A => B)

the reasons being consistency (with Either also, at least in part, as Left = wrong = None is first) and that the some branch is usually longer, so we can

  myOp.fold(0){ x =>
    someComplicatedCalculationYieldingAnInt(x)
  }

The consistency matters because of cognitive burden.  I know people using Scalaz will have to adjust, but I think it's more important to minimize the memorization burden on everyone else.

  --Rex

On Wed, Apr 4, 2012 at 12:27 PM, Jeff Olson <jeff.d...@gmail.com> wrote:

√iktor Ҡlang

unread,
Apr 4, 2012, 1:02:34 PM4/4/12
to scala-l...@googlegroups.com
+1
--
Viktor Klang

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

Twitter: @viktorklang

Paul Phillips

unread,
Apr 4, 2012, 1:05:42 PM4/4/12
to scala-l...@googlegroups.com
On Wed, Apr 4, 2012 at 9:58 AM, Rex Kerr <ich...@gmail.com> wrote:
> I would prefer the same order as the list fold:
>
>   def fold[B](none: => B)(some: A => B)

That would mean we incur the list fold's super annoying issue.

scala> def f[T](xs: List[T]) = xs.foldLeft(Nil)((x, y) => x :+ y)
<console>:7: error: type mismatch;
found : List[T]
required: scala.collection.immutable.Nil.type
def f[T](xs: List[T]) = xs.foldLeft(Nil)((x, y) => x :+ y)
^

Same parameter list avoids this.

Daniel Spiewak

unread,
Apr 4, 2012, 1:12:29 PM4/4/12
to scala-l...@googlegroups.com
Same parameter list avoids that particular inference issue, but in the case of List fold, it is required to avoid a different and more annoying issue inferring the parameter type of the function.  In the case of Option fold, the inference is certainly annoying, but I think it would be vastly more annoying to not be able to use the special syntax for trailing function parameters.  Given that the rest of the standard library observes this convention (of separating function parameters in a trailing block), it would be very odd to do something different for Option fold.

As annoying as the List fold issue is, people understand it now.  The fact that we need to explicitly ascribe is a pain that we've internalized at this point.

Regarding the question of Option fold, I'm cautiously in favor of adding it.  I don't think it costs us anything, and it's definitely nice to have in certain circumstances (e.g. the extremely common (getOrElse . map) pattern).  I would caution us against going too far down this road though for general ADTs due to the performance implications of building unused thunks for every case at every call site.

Daniel

Paul Phillips

unread,
Apr 4, 2012, 1:19:01 PM4/4/12
to scala-l...@googlegroups.com
On Wed, Apr 4, 2012 at 10:12 AM, Daniel Spiewak <djsp...@gmail.com> wrote:
> I would caution us against going too far down this road though for general
> ADTs due to the performance implications of building unused thunks for every
> case at every call site.

If you use -optimise these are all inlined and eliminated.

Paul Phillips

unread,
Apr 4, 2012, 1:21:53 PM4/4/12
to scala-l...@googlegroups.com
On Wed, Apr 4, 2012 at 10:12 AM, Daniel Spiewak <djsp...@gmail.com> wrote:
> Same parameter list avoids that particular inference issue, but in the case
> of List fold, it is required to avoid a different and more annoying issue
> inferring the parameter type of the function.  In the case of Option fold,
> the inference is certainly annoying, but I think it would be vastly more
> annoying to not be able to use the special syntax for trailing function
> parameters.  Given that the rest of the standard library observes this
> convention (of separating function parameters in a trailing block), it would
> be very odd to do something different for Option fold.

You're right about this though.

Daniel Spiewak

unread,
Apr 4, 2012, 1:29:58 PM4/4/12
to scala-l...@googlegroups.com
> I would caution us against going too far down this road though for general
> ADTs due to the performance implications of building unused thunks for every
> case at every call site.

If you use -optimise these are all inlined and eliminated.

In my experience, this works a lot less frequently than one would expect.  Should work pretty universally for Option fold though.  More importantly, we're rapidly approaching a thread hijack.

I vote +1.

Daniel

Paul Phillips

unread,
Apr 4, 2012, 1:31:29 PM4/4/12
to scala-l...@googlegroups.com
OK, complain now or forever fold your peace.

https://github.com/scala/scala/commit/bb4935e92c

Paul Phillips

unread,
Apr 4, 2012, 1:33:37 PM4/4/12
to scala-l...@googlegroups.com
On Wed, Apr 4, 2012 at 10:29 AM, Daniel Spiewak <djsp...@gmail.com> wrote:
> In my experience, this works a lot less frequently than one would expect.

Your experience probably isn't up to date. I would definitely like to
know of any circumstance where Option#getOrElse is not inlined under
-optimise using current trunk. This will inline with the same
frequency, which AFAIK is 100%.

Daniel Spiewak

unread,
Apr 4, 2012, 1:37:11 PM4/4/12
to scala-l...@googlegroups.com

> In my experience, this works a lot less frequently than one would expect.

Your experience probably isn't up to date.  I would definitely like to
know of any circumstance where Option#getOrElse is not inlined under
-optimise using current trunk.  This will inline with the same
frequency, which AFAIK is 100%.

I've never seen issues with anything as simple as getOrElse.  I'll keep an eye out for this though as we upgrade to 2.10.  Will file any such issues as bugs.

Daniel

Erik Osheim

unread,
Apr 4, 2012, 1:38:15 PM4/4/12
to scala-l...@googlegroups.com
_.fold(1)(_ + 1)

Jeff Olson

unread,
Apr 4, 2012, 1:52:51 PM4/4/12
to scala-l...@googlegroups.com
I thought about this some. I don't really buy the consistency argument: Either.fold takes a uncurried parameter list.

The type-inference issue that Paul mentions below is the deal breaker for me. Just try this exercise: http://blog.tmorris.net/further-understanding-scalaoption/ with the curried and the uncurried forms and I think you'll agree. 

Much of the conciseness gains we achieve with adding fold are lost if we need to add ugly type ascriptions.

Also, if I going to write something like 

opt.fold(0) { x => 
  some
  long 
  block of code involving x
  and yielding an Int
}

I don't think its that much worse to write:

opt match {
  case None => 0
  case Some(x) =>
    same
    long
    block of code involving x
    and yielding an Int
}

- Jeff

Paul Phillips

unread,
Apr 4, 2012, 2:00:04 PM4/4/12
to scala-l...@googlegroups.com
On Wed, Apr 4, 2012 at 10:52 AM, Jeff Olson <jeff.d...@gmail.com> wrote:
> I thought about this some. I don't really buy the consistency argument:
> Either.fold takes a uncurried parameter list.

Either is inconsistent in a million different ways, and does not serve
as effective precedent.

Paul Phillips

unread,
Apr 4, 2012, 2:01:29 PM4/4/12
to scala-l...@googlegroups.com
On Wed, Apr 4, 2012 at 10:52 AM, Jeff Olson <jeff.d...@gmail.com> wrote:
> Much of the conciseness gains we achieve with adding fold are lost if we
> need to add ugly type ascriptions.

Having just implemented it, I found the ascribing worse in the same
parameter list, for the reason daniel gave. No longer would a
function type be inferred.

Daniel Spiewak

unread,
Apr 4, 2012, 2:01:05 PM4/4/12
to scala-l...@googlegroups.com
I thought about this some. I don't really buy the consistency argument: Either.fold takes a uncurried parameter list.

Either fold is an exception, since the cases are symmetric.  There is no sane way of currying those parameters separately, nor is there any benefit to be gained by doing so.
 
The type-inference issue that Paul mentions below is the deal breaker for me. Just try this exercise: http://blog.tmorris.net/further-understanding-scalaoption/ with the curried and the uncurried forms and I think you'll agree. 

You face the same issue with List fold.  This is simply a consequence of dispatch polymorphism killing both parameter ordering (see Scala's foldLeft vs Haskell's foldl) and non-local type inference.  In other words, this issue is fundamental, and we can't get away from it.  Currying gives us two things: better syntax and more conventional type inference tradeoffs.  The inference tradeoffs are not evident in Option fold, but they are painfully clear if you try to uncurry List fold.

The final nail in the coffin is consistency.  Aside from Either fold (which is a special case), there are no cases in the standard library of function parameters that are not curried in the trailing position.  If we make our constraints more specific by looking for singular function parameters, Either fold gets kicked out simply by definition.
 
Much of the conciseness gains we achieve with adding fold are lost if we need to add ugly type ascriptions.

I don't agree.  I think your fold example is much easier to read and less error-prone than the match encoding.  Less trivial examples are going to be the same way.

Type ascription is a fundamental consequence of subtyping's interaction with type inference.  There's just no way to get around it.

Daniel

Jeff Olson

unread,
Apr 4, 2012, 2:05:52 PM4/4/12
to scala-l...@googlegroups.com
Perhaps not, but I think it weakens the argument that we need to conform to the List precedent. I think the conciseness argument should weigh more heavily here. 

I'd be curious to hear from the authors of Scalaz as to why they choose an uncurried form for fold.
  

Paul Phillips

unread,
Apr 4, 2012, 2:06:28 PM4/4/12
to scala-l...@googlegroups.com
On Wed, Apr 4, 2012 at 11:01 AM, Daniel Spiewak <djsp...@gmail.com> wrote:
> Type ascription is a fundamental consequence of subtyping's interaction with
> type inference.  There's just no way to get around it.

I should point out there is clearly a way around it in this case. We
infer an overly specific type in the first parameter list, then fail
the compile in the second parameter list. There's no fundamental
reason we could not backtrack to the first parameter list and infer a
less specific type, at which point everything would work with flying
colors. I'm not saying we should do that (or that we shouldn't) or
that there wouldn't be complications in the general case.

Rex Kerr

unread,
Apr 4, 2012, 2:14:50 PM4/4/12
to scala-l...@googlegroups.com
No thanks.  I'd rather have to explicitly annotate than always have it go through and leave me puzzled as to why I have an Any coming back.  (I rely upon the non-backtracking in places to keep me honest.)

  --Rex

Daniel Spiewak

unread,
Apr 4, 2012, 2:15:27 PM4/4/12
to scala-l...@googlegroups.com

I should point out there is clearly a way around it in this case.  We
infer an overly specific type in the first parameter list, then fail
the compile in the second parameter list.  There's no fundamental
reason we could not backtrack to the first parameter list and infer a
less specific type, at which point everything would work with flying
colors.  I'm not saying we should do that (or that we shouldn't) or
that there wouldn't be complications in the general case.

This is effectively approximating unification based inference on a small scale by iterative convergence.  Given that fold is so restricted and Scala doesn't provide a way to derive types in a dependent fashion through function types, I suspect that algorithm would be decidable and probably not too inefficient (my instinct says it would be cubic in the number of parameter-derived inferences within the function body).  In general though, that sort of thing usually explodes in a hurry (e.g. you cannot implement ML's type system in this fashion).

Daniel

Paul Phillips

unread,
Apr 4, 2012, 2:20:04 PM4/4/12
to scala-l...@googlegroups.com
On Wed, Apr 4, 2012 at 11:14 AM, Rex Kerr <ich...@gmail.com> wrote:
> No thanks.  I'd rather have to explicitly annotate than always have it go
> through and leave me puzzled as to why I have an Any coming back.  (I rely
> upon the non-backtracking in places to keep me honest.)

It doesn't have to turn the dial all the way to Any, nor would it in
any sane scenario. It only has to widen singleton types.

Paul Phillips

unread,
Apr 4, 2012, 2:25:20 PM4/4/12
to scala-l...@googlegroups.com
On Wed, Apr 4, 2012 at 11:20 AM, Paul Phillips <pa...@improving.org> wrote:
> It doesn't have to turn the dial all the way to Any, nor would it in
> any sane scenario.  It only has to widen singleton types.

In fact, I wonder if one could annotate fold's signature...

def foldLeft[B](z: B)(op: (B, A) => B)(implicit ev: B !<:< Singleton): B

I invented a syntax for "is not a subtype of" which as far as I know
we can't express directly but can using the create-an-ambiguity trick.
If you can exclude Nil.type from valid inferences for B then I think
it will just work.

Daniel Spiewak

unread,
Apr 4, 2012, 2:37:07 PM4/4/12
to scala-l...@googlegroups.com
This doesn't cover the (almost as common) case where you're folding with a non-singleton seed:

xs.foldLeft(Some(42)) { (a, b) => a filter (b ==) }

Obviously facetious example, but you get the idea.

Daniel

Paul Phillips

unread,
Apr 4, 2012, 2:40:53 PM4/4/12
to scala-l...@googlegroups.com
On Wed, Apr 4, 2012 at 11:37 AM, Daniel Spiewak <djsp...@gmail.com> wrote:
> This doesn't cover the (almost as common) case where you're folding with a non-singleton seed:

Okay, how about widening final types. I understand this is rather ad
hoc, something I am not nearly so allergic to as are some other
people, when I think the circumstances call for it.

Daniel Spiewak

unread,
Apr 4, 2012, 2:46:06 PM4/4/12
to scala-l...@googlegroups.com
What happens if the final type is inferred from the parameter type that you're trying to pin down? What if it is determined by a nested fold where its seed is the parameter to the outer fold? What if the type you are widening is not a simple type? For example:

xs.foldRight(List(Nil)) { _ :: _ }

Daniel

Paul Phillips

unread,
Apr 4, 2012, 3:31:31 PM4/4/12
to scala-l...@googlegroups.com
On Wed, Apr 4, 2012 at 11:46 AM, Daniel Spiewak <djsp...@gmail.com> wrote:
> What happens if the final type is inferred from the parameter type that you're trying to pin down?  What if it is determined by a nested fold where its seed is the parameter to the outer fold?  What if the type you are widening is not a simple type?

I don't feel the need to solve the universe's problems when we're
talking about going from "does not compile, despite obvious meaning"
to "does compile, with obvious meaning" for some set of common cases.
That was my point about not being overly allergic to ad hoc measures.
Anyone who thinks we don't already apply heuristics of this kind
should look through the compiler source sometime.

martin odersky

unread,
Apr 4, 2012, 5:45:31 PM4/4/12
to scala-l...@googlegroups.com
I think fold has only a chance of being accepted if it follows the collection parameter convention. Options follow collections in all other respects, making fold an exception would ruin much more in coherence than it could ever gain us in conciseness.

So, I am happy with

  fold(none: => B)(some: A => B)

on Option[A]. If we think that the need to sometimes type-annotate the none branch is so awkward that it's better to do without, then maybe it's better to do without. But I tend to think it's probably not that large a problem.

Cheers

 - Martin


Daniel Spiewak

unread,
Apr 4, 2012, 5:53:48 PM4/4/12
to scala-l...@googlegroups.com
on Option[A]. If we think that the need to sometimes type-annotate the none branch is so awkward that it's better to do without, then maybe it's better to do without. But I tend to think it's probably not that large a problem.

We're not taking away match/case, or even (getOrElse . map) for that matter, so other options are always open.  I expect I will only use fold in cases where it actually works out to be cleaner than these alternatives.  So, this is strictly increasing the flexibility of the API at a cost of slightly increasing the surface area.

Daniel

Jeff Olson

unread,
Apr 4, 2012, 6:35:02 PM4/4/12
to scala-l...@googlegroups.com
Then I am all for the curried version. Like I said, the details are much less important to me than the existence of the method. The consensus here seems heavily in favor of the curried form, so by all means, let's do it.

-Jeff

Tony Morris

unread,
Apr 4, 2012, 6:13:57 PM4/4/12
to scala-l...@googlegroups.com

Actually, this order of parameters is correct, but not for the reasons you mention.

While we are at out, let's add Boolean.fold (if/else with the argument order dunrite).

Tony Morris

unread,
Apr 4, 2012, 6:43:16 PM4/4/12
to scala-l...@googlegroups.com
We have recently adopted the idea of uncurried first, optionally curried
over the top. The reasons are immensely drawn out and bring up
contentions between sound library design, Scala's type inference, JVM
target and more.

--
Tony Morris
http://tmorris.net/


Daniel Spiewak

unread,
Apr 4, 2012, 6:52:48 PM4/4/12
to scala-l...@googlegroups.com
We have recently adopted the idea of uncurried first, optionally curried
over the top. The reasons are immensely drawn out and bring up
contentions between sound library design, Scala's type inference, JVM
target and more.

Actually, there's a more fundamental reason which trumps all of those (very valid) reasons: Scala is an object-oriented language.  Among many other contentious things, this means that Scala uses dispatch polymorphism as its primary function dispatch mechanism.  This is very significant and fundamentally different from a functional language.  It means that in Scala, you must order parameters from most- to least-specific, since your most specific parameter will always be the dispatch receiver.  This is fundamentally at odds with a parameter ordering optimized for partial application, which orders parameters from least- to most-specific for maximum generality at each point of application.  There is no way around this issue aside from completely ignoring dispatch polymorphism and invoking all functions on either `this` or some imported object.

In general, function parameters tend to be the least-specific parameter.  This is nearly a maxim, just because of how higher-order functions generally fall out.  As a result, they usually come first in Haskell type signatures and last in Scala.  The fact that Scala lends special syntactic precedence and nicer type inference to such forms is merely a bonus.

Daniel

Jason Zaugg

unread,
Apr 5, 2012, 1:14:59 AM4/5/12
to scala-l...@googlegroups.com

Yep, the rationale for parameter grouping in Scalaz 7 goes like:

1. By default, use a single parameter section.
2. Split this into multiple parameter sections if there is a type
inference benefit. (I prefer not to call this 'curried' to avoid
confusion with #3)
3. Avoid currying like: def foo(a: A): B => C => D.

Why?

- #2 compiles to normal method dispatch, #3 involves indirection at
runtime through Function1.
- #1 and #2 allow names on the parameters, which I find easier to
document and use than #3.

I didn't consider the type inference benefit of inferring the *return*
type of the closure argument to Option#fold until it was pointed out
in this thread; until now I've only considered changes to help infer
the *parameter* type.

-jason

Alois Cochard

unread,
Apr 5, 2012, 10:32:22 AM4/5/12
to scala-l...@googlegroups.com
+1, would be cool to have it on Boolean as well in stb-lib

nuttycom

unread,
Apr 5, 2012, 11:00:29 AM4/5/12
to scala-l...@googlegroups.com


On Wednesday, April 4, 2012 4:13:57 PM UTC-6, Tony Morris wrote:

Actually, this order of parameters is correct, but not for the reasons you mention.

While we are at out, let's add Boolean.fold (if/else with the argument order dunrite).

Agreed - inlinable boolean folds would make a number of expressions nicer, in particular creation of Option instances based on boolean expressions.

Daniel Spiewak

unread,
Apr 5, 2012, 11:04:35 AM4/5/12
to scala-l...@googlegroups.com
Inlinable boolean folds…like if/else?

Daniel

Daniel Sobral

unread,
Apr 5, 2012, 11:32:09 AM4/5/12
to scala-l...@googlegroups.com
On Thu, Apr 5, 2012 at 12:04, Daniel Spiewak <djsp...@gmail.com> wrote:
> Inlinable boolean folds…like if/else?

This is the problem with if/else:

scala> val x = if (true) 1 else 2
x: Int = 1

scala> val x = 1 + if (true) 1 else 2
<console>:1: error: illegal start of simple expression

--
Daniel C. Sobral

I travel to the future all the time.

Daniel Spiewak

unread,
Apr 5, 2012, 11:42:31 AM4/5/12
to scala-l...@googlegroups.com
Wouldn't a fold invocation and the associated thunks be more verbose than a simple pair of parentheses?

Daniel

Daniel Sobral

unread,
Apr 5, 2012, 11:56:17 AM4/5/12
to scala-l...@googlegroups.com
On Thu, Apr 5, 2012 at 12:42, Daniel Spiewak <djsp...@gmail.com> wrote:
> Wouldn't a fold invocation and the associated thunks be more verbose than a
> simple pair of parentheses?

val x = true.fold(1)(2)
val x = 1 + true.fold(1)(2)

The point is not verbosity, the point is that I can move it around an
expression at will without worrying about adding parenthesis. Sure, I
could put every if statement inside parenthesis, but does anyone?

Jonas Bonér

unread,
Apr 5, 2012, 12:01:44 PM4/5/12
to scala-l...@googlegroups.com
I like it a lot. Been missing it for years. +1
--
Jonas Bonér
CTO
Typesafe - Enterprise-Grade Scala from the Experts
Phone: +46 733 777 123
Twitter: @jboner

Erik Post

unread,
Apr 5, 2012, 12:32:17 PM4/5/12
to scala-l...@googlegroups.com
+1!

On Thursday, 5 April 2012 00:13:57 UTC+2, Tony Morris wrote:

Rex Kerr

unread,
Apr 5, 2012, 1:08:26 PM4/5/12
to scala-l...@googlegroups.com
On Thu, Apr 5, 2012 at 11:56 AM, Daniel Sobral <dcso...@gmail.com> wrote:
On Thu, Apr 5, 2012 at 12:42, Daniel Spiewak <djsp...@gmail.com> wrote:
> Wouldn't a fold invocation and the associated thunks be more verbose than a
> simple pair of parentheses?

val x = true.fold(1)(2)
val x = 1 + true.fold(1)(2)

The biggest problem with this is that  the natural order with fold is (onFalse)(onTrue), while the natural order for if is (onTrue)(onFalse).

I'm fine with having the method, but I think it will be confusing regardless of parameter order if we call it fold.  Call it "pick" or "?" or something instead; then you can agree with if-ordering without running into any cognitive dissonance.

This is just the ternary operator, after all:

class Ternary(b: Boolean) { def ?[A](t: => A, f: => A) = if (b) t else f }
implicit def boolean_has_ternary(b: Boolean) = new Ternary(b)

scala> val x = 1 + true ? (1,2)
x: Int = 2

  --Rex

Erik Post

unread,
Apr 5, 2012, 5:04:32 PM4/5/12
to scala-l...@googlegroups.com


On Thursday, 5 April 2012 19:08:26 UTC+2, Rex Kerr wrote:

On Thu, Apr 5, 2012 at 11:56 AM, Daniel Sobral wrote:

On Thu, Apr 5, 2012 at 12:42, Daniel Spiewak wrote:
> Wouldn't a fold invocation and the associated thunks be more verbose than a
> simple pair of parentheses?

val x = true.fold(1)(2)
val x = 1 + true.fold(1)(2)

The biggest problem with this is that  the natural order with fold is (onFalse)(onTrue), while the natural order for if is (onTrue)(onFalse).

Right, but we were discussing fold, whose arguments, as you point out, are reversed wrt if.
 
I'm fine with having the method, but I think it will be confusing regardless of parameter order if we call it fold. 

If is if and fold is fold; how is that confusing?

Cheers,
Erik

martin odersky

unread,
Apr 5, 2012, 6:50:31 PM4/5/12
to scala-l...@googlegroups.com
Unlike options, booleans do not yet posses a collection-like interface. So adding one is a lot more work and one has to ask whether it's worth it. More than one way to do it is not necessarily better! And if one does it one would have to look at what other operations also need to be added. Filter, for example is a clear case. Overall, I am not particularly keen on adding more stuff to primitive types.

 - Martin


--
Martin Odersky
Prof., EPFL and Chairman, Typesafe
PSED, 1015 Lausanne, Switzerland
Tel. EPFL: +41 21 693 6863
Tel. Typesafe: +41 21 691 4967

Reply all
Reply to author
Forward
0 new messages