Scala style: function literals

218 views
Skip to first unread message

Philipp Haller

unread,
Jun 5, 2013, 7:38:39 PM6/5/13
to scala-l...@googlegroups.com
Hi all,

Recently, I reviewed code with a mix of function literals and other expressions, such as

    onComplete { v => p complete { v map f } }

I agree with the syntax to pass function literals as follows:

    list map { el => <body> }

It reads very natural, and the function literal is clearly demarcated.

On the other hand, I'd prefer to pass expressions that are *not* function literals to be passed using regular parentheses:

    p.complete(v.map(f))

Note that I didn't write `p.complete(v map f)` because
a) I don't think the infix syntax is a good choice for `v map f`, since neither is `f` is a function literal nor is `map` a symbolic operator, and
b) for consistency `p.complete` should be invoked in the same way as `v.map`. 

Taken together I'd prefer to express the first example as follows:

    onComplete { v => p.complete(v.map(f)) }

What's interesting about this style is that it makes code where function literals appear interspersed with other expressions easy to read:

    that onComplete { c => p.complete(c map { (s, _) }) }

The {}'s demarcate function literals, and the ()'s are used to pass non-lambda arguments.

What do you think?

Cheers,
Philipp

--
See you at Scala Days (June 10–12, NYC)!

Vlad Patryshev

unread,
Jun 5, 2013, 7:58:36 PM6/5/13
to scala-l...@googlegroups.com
These days I tend to believe that as long as others can read and maybe enjoy your code, it's up to you to choose the style.
What you are saying makes sense though... for some.

I'd rather prefer to give v, p, f  more meaningful names unless they are very generic notions (like "a function f") than be bothered about curlies and spaces. The matter of taste (of course).

Thanks,
-Vlad


--
You received this message because you are subscribed to the Google Groups "scala-language" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-languag...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

Paul Phillips

unread,
Jun 5, 2013, 9:23:07 PM6/5/13
to scala-l...@googlegroups.com
On Wed, Jun 5, 2013 at 4:38 PM, Philipp Haller <hal...@gmail.com> wrote:
The {}'s demarcate function literals, and the ()'s are used to pass non-lambda arguments.

Personally I find curly braces make my eyes bleed, and more importantly, curly braces violate the principle of using the least powerful construct which achieves the goal.  If you CAN use parentheses, then there is only a single expression within them. The use of parentheses signals that helpfully to both human and compiler. If you place a single expression inside curly braces, the opportunity is lost. And now you're all set up for the next guy to come along and leave you with this:

def foo(p1: Boolean, p2: Boolean, p3: Boolean, p4: Boolean, p5: Boolean) = {
  p1 && p2 && 
  p3 && p4
  p5
}

Which helpfully does not compile if you use parentheses.

Punctuation in general makes my eyes bleed, so I would write p complete (v map f) and not lose any sleep. Even if we all agreed that using curly braces vs. parentheses signalled something important, you could never trust that signal because who knows who's going to adhere to that rule; but I CAN trust the compiler to fail on syntactically invalid code.

Luke Vilnis

unread,
Jun 5, 2013, 9:30:48 PM6/5/13
to scala-l...@googlegroups.com
I agree with this - I hate unnecessary use of curly braces (and infix syntax). Especially when the use of infix syntax makes people then have to wrap the entire expression in parentheses when they want to call a 0- or 2-argument method in a chain. I find that using explicit dot syntax for non-symbolic methods and parentheses reduces cognitive load when coding too (less time wondering about "how should i format this, more time coding).


Paul Phillips

unread,
Jun 5, 2013, 9:55:37 PM6/5/13
to scala-l...@googlegroups.com
On Wed, Jun 5, 2013 at 6:30 PM, Luke Vilnis <lvi...@gmail.com> wrote:
I agree with this - I hate unnecessary use of curly braces (and infix syntax). Especially when the use of infix syntax makes people then have to wrap the entire expression in parentheses when they want to call a 0- or 2-argument method in a chain. I find that using explicit dot syntax for non-symbolic methods and parentheses reduces cognitive load when coding too (less time wondering about "how should i format this, more time coding).

I assume you mean "I do not agree with this" because you took a position counter to the one you quoted.
 

Luke Vilnis

unread,
Jun 5, 2013, 10:07:00 PM6/5/13
to scala-l...@googlegroups.com
Yea sorry that was not an incredibly well constructed email. I agree with unnecessary curly braces = bad. And then proceeded to go on an unrelated rant about infix syntax.


Haoyi Li

unread,
Jun 5, 2013, 10:23:53 PM6/5/13
to scala-l...@googlegroups.com
I agree that unnecessary curly braces are bad; it would be nice if we could do some sort of destructuring without them though. Currently we have

x.map{case Success(x) => x.stuff}
x.map{r => val Success(x) = r; x.stuff}

but no way of doing the destructuring pattern match without curly braces, which have their problems mentioned above.

Som Snytt

unread,
Jun 5, 2013, 11:08:34 PM6/5/13
to scala-l...@googlegroups.com

> p complete (v map f)

+1

I propose a shift in vocabulary.  If we call them "spots" instead of "dots", there will be fewer of them.

The remaining question is whether parens are de rigueur here:

f onComplete p.complete

Granted, an ambitious spot-remover might come to grief.

Som Snytt

unread,
Jun 6, 2013, 12:12:50 AM6/6/13
to scala-l...@googlegroups.com
I appreciated the explanation, because I was killing a few minutes earlier before chauffeuring to piano lesson looking at the PR, and I didn't quite get the distinction.  Now I see what you mean, but then I realized I didn't actually see what the code said.

I guess this is what that Latin phrase means, in loco parens.  It must mean: crazy braces!

case Success(s) => that onComplete { c => p complete { c.map((s, _)) } }
case Success(s) => that onComplete (p complete _.map(u => (s, u)))
case Success(s) => that onComplete (p complete _.map((s, _)))
case Success(s) => that onComplete (p complete _.map(s -> _))
case Success(s) => that onComplete (c => p complete (c map (u => (s, u))))
case Success(s) => that onComplete { c =>
  val tu = c map (u => (s, u))
  p complete tu
}


Maybe if you need braces to read it, then it actually needs braces.

I like the minimal paren version most, because it bespeaks job security, but I would probably write the last one and leave it at that, in case I had to read it later.  That's assuming the tests pass.  Nested tupling parens give me pause, obviously.


On Wed, Jun 5, 2013 at 4:38 PM, Philipp Haller <hal...@gmail.com> wrote:

martin odersky

unread,
Jun 6, 2013, 4:13:29 AM6/6/13
to scala-l...@googlegroups.com
My own rule is, use parens if the closure body is a single expression, braces otherwise. 

I sometimes deviate from that if the result is greater uniformity. For instance, the parser has a method atPos, which is usually invoked like this:

  atPos("some position") {
    ... // some parsing code, can be arbitrarily involved
  }

I then write atPos with braces even if its only on a single line. 

Cheers

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

ARKBAN

unread,
Jun 6, 2013, 7:04:11 AM6/6/13
to scala-l...@googlegroups.com
> These days I tend to believe that as long as others can read and maybe enjoy your code, it's up to you to choose the style.

Our style is to use dots and parenthesis and to avoid spaces because it matches our JavaScript code. In our case its consistency over personal preference.

Although I will say if "curly braces make your eyes bleed" then you might want to look at a different font, there are some that make parenthesis less violent ; )

ARKBAN

martin odersky

unread,
Jun 6, 2013, 7:15:17 AM6/6/13
to scala-l...@googlegroups.com
On Thu, Jun 6, 2013 at 10:13 AM, martin odersky <martin....@epfl.ch> wrote:
My own rule is, use parens if the closure body is a single expression, braces otherwise. 

Looking at some code, I have to revise that one;

My own rule is, use parens if the closure body is a single expression _on the same line_, 
braces otherwise.

 - Martin

Mark Derricutt

unread,
Jun 7, 2013, 6:19:19 AM6/7/13
to scala-l...@googlegroups.com
Haoyi Li wrote:
> x.map{case Success(x) => x.stuff}
> x.map{r => val Success(x) = r; x.stuff}

Why not steel from Haskell - there are time I don't like this syntax,
but for this it seems useful:

x map $ r => r.something

everything to the right of the $ is interpreted as being inside parens,
which even nests

x map $ r => r.something flatMap $ i => i.someThingElse.split(' ')

I wonder then, if expanding to use _ could work:

x map $ _.something flatMap $ _.somethingElse.split(' ')

This does however, start to look like an incomprehensible mess tho.

Ken Scambler

unread,
Jun 9, 2013, 7:58:33 AM6/9/13
to scala-l...@googlegroups.com
Personally, I think the cure is worse than the disease in that case.
Reply all
Reply to author
Forward
0 new messages