def foo { println(1) } warning: Procedure syntax is deprecated. Use `: Unit =` instead.

2,614 views
Skip to first unread message

Simon Ochsenreither

unread,
May 27, 2013, 10:54:18 AM5/27/13
to scala-i...@googlegroups.com
— Or: Can we decide on one-true-procedure-style instead of three?

I have been focusing on beginner-level issues for the last few weeks and one large chunk of popular problems which comes up a lot is the different declaration style for procedures.

Scala has
  • its own special syntax for procedures, def foo { println(1) }
  • Unit-returning methods with inference, def foo = { println(1) }
  • has explicit Unit-returning methods, def foo: Unit = { println(1) }

Imho, that's at least one option too many.

The first option is especially troubling, because we reward people who use side-effects with special, less verbose syntax, while we claim that the language nudges people toward a more value-driven style of programming.

The second option is pretty bad from a different perspective: Those who actually want to return a value, but have forgotten the equals sign fall into this trap. This comes up a lot. (We have at least a warning for that now.)

The third option is explicit and the style I think should be preferred in traits, too. (E.g. trait Foo { def foo: Unit } instead of trait Foo { def foo }, I think it's mind-boggling and invites errors that we even allow the second option.)

What about

  • deprecating and removing option number one,
  • adding a warning if a method's result type is inferred to be Unit for option number two and
  • guiding users towards specifying the return type explicitly, like in option number three?

Imho this would improve consistency of the language, remove confusing variations in style, reduce the amount of special-cases users have to learn and prevent a lot of beginner mistakes.

Better ideas, opinions, criticism?

Simon

Roland Kuhn

unread,
May 27, 2013, 10:59:25 AM5/27/13
to scala-i...@googlegroups.com
FWIW this proposal matches our Akka coding guidelines, so it sounds good from over here.

Regards,

Roland

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



Dr. Roland Kuhn
Akka Tech Lead
Typesafe – Empowering professional developers to build amazing apps.
twitter: @rolandkuhn

See you at Scala Days 2013 in NYC!
June 10th - June 12th
www.scaladays.org

Kevin Wright

unread,
May 27, 2013, 11:19:11 AM5/27/13
to scala-i...@googlegroups.com
The exact opposite is annoyingly advocated by the "official" style guide: http://docs.scala-lang.org/style/types.html#void_methods

Worse still, the suggestions of the style guide are encapsulated in scalariform defaults, syntax checking tools (Yes intelliJ, I'm looking at YOU), etc.


For what it's worth, I've always favoured the explicit `: Unit` syntax, but if we're going to make this change then surely the style guide MUST be the right place to start?


--
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

Jason Zaugg

unread,
May 27, 2013, 12:00:56 PM5/27/13
to scala-i...@googlegroups.com
On Mon, May 27, 2013 at 4:54 PM, Simon Ochsenreither <simon.och...@gmail.com> wrote:

What about

  • deprecating and removing option number one,
  • adding a warning if a method's result type is inferred to be Unit for option number two and
  • guiding users towards specifying the return type explicitly, like in option number three?

Imho this would improve consistency of the language, remove confusing variations in style, reduce the amount of special-cases users have to learn and prevent a lot of beginner mistakes.

Better ideas, opinions, criticism?

I don't have a particularly strong opinion on this one. 

But in general, I do feel strongly that we mustn't create unnecessary busy work for people that have invested into writing hundreds of thousands of lines of Scala code. We should strive to accompany these sort of changes with a robust refactoring tool.

-jason

Paul Phillips

unread,
May 27, 2013, 12:38:05 PM5/27/13
to scala-i...@googlegroups.com

On Mon, May 27, 2013 at 8:19 AM, Kevin Wright <kev.lee...@gmail.com> wrote:
The exact opposite is annoyingly advocated by the "official" style guide

The "official" style is loaded with things I would change. I don't even know where this style originates.

martin odersky

unread,
May 27, 2013, 12:41:28 PM5/27/13
to scala-internals
I think it would be good to get rid at some point of specialized procedure syntax. It goes with the general desire of making the language simpler. But I also agree we have to be careful not to create busywork for people. So, as a first step, it would be good to update the style guide and IntelliJ's syntax checking tool. 

Cheers

 - Martin

-jason

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



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

Jason Zaugg

unread,
May 27, 2013, 12:41:54 PM5/27/13
to scala-i...@googlegroups.com
I think it came out of Daniel Spiewak’s project at Novell a few years back.


-jason

 

Rex Kerr

unread,
May 27, 2013, 12:43:30 PM5/27/13
to scala-i...@googlegroups.com
On Mon, May 27, 2013 at 10:54 AM, Simon Ochsenreither <simon.och...@gmail.com> wrote:
— Or: Can we decide on one-true-procedure-style instead of three?

I have been focusing on beginner-level issues for the last few weeks and one large chunk of popular problems which comes up a lot is the different declaration style for procedures.

Scala has
  • its own special syntax for procedures, def foo { println(1) }
  • Unit-returning methods with inference, def foo = { println(1) }
  • has explicit Unit-returning methods, def foo: Unit = { println(1) }

Imho, that's at least one option too many.


Scala has

  val x = 7
  val x: Int = 7
  val x = 7: Int
  val x: Int = 7: Int

That's at least two options too many, no?  Especially the first one, where people have forgotten to specify that they want a long or double or something.

Or maybe we shouldn't make people do unnecessary busywork because some people when learning make common mistakes.

If you want to add

  -Xverbose-types

that disallows any shortcutting, fine.

Otherwise, I think this is a horrible idea.  If people get tripped up on "def blah = ... returns something, def blah { ... } doesn't", I think the solution is to have people practice this more until they become familiar with it, not make everyone adopt a more unwieldy solution.

Also, I hear operators are confusing.  Maybe we should disallow symbols, too.

The first option is especially troubling, because we reward people who use side-effects with special, less verbose syntax

No it doesn't.

  def f = println
  def f { println }

Which one is more compact?  When the code is verbose anyway (multiple lines) ought not care about an extra = .

The second option is pretty bad from a different perspective: Those who actually want to return a value, but have forgotten the equals sign fall into this trap. This comes up a lot. (We have at least a warning for that now.)

Sure, if you wrote = you probably meant it not to be Unit (unless you said it was Unit).  I'd rather have it under -Xwarn-def-unit, but on by default would be tolerable.

The third option is explicit and the style I think should be preferred in traits, too. (E.g. trait Foo { def foo: Unit } instead of trait Foo { def foo }, I think it's mind-boggling and invites errors that we even allow the second option.)

I agree that traits might be better off explicit.

But really--aren't almost all of these things caught at compile time, and pretty quickly?  Why have a strongly-typed language if you don't use the strong typing to help catch your silly mistakes and instead change the syntax?
 

What about

  • deprecating and removing option number one,
Strongly opposed.
 
  • adding a warning if a method's result type is inferred to be Unit for option number two
Okay.

  • guiding users towards specifying the return type explicitly, like in option number three?
Strongly opposed.

Explicit return types, like explicit types on vars and vals, are an unnecessary and annoying burden in the majority of cases.  In the minority of cases, they help.  Much of the painfulness of Java is exactly because it gets this calculus wrong: always favor the rare case where verbosity is an improvement, and force everyone to be that verbose all the time.

I object--I think this is exactly wrong.  Stuff which isn't important should disappear to the extent possible.  If people make mistakes, train them.  Only when it is the kind of thing that even experts routinely get wrong and without sensible ways to detect/fix it should we favor verbosity.

  --Rex

Simon Ochsenreither

unread,
May 27, 2013, 12:49:25 PM5/27/13
to scala-i...@googlegroups.com

I think it would be good to get rid at some point of specialized procedure syntax. It goes with the general desire of making the language simpler. But I also agree we have to be careful not to create busywork for people. So, as a first step, it would be good to update the style guide and IntelliJ's syntax checking tool. 

I agree with that. We shouldn't force people to do useless work to “fix” working code which could be done by tools more easily. That's pretty much the only thing Go managed to do right: They have go fix, which can rewrite existing code without user input.

I'll have a look into it. Documentation/style guide first, then tools, then language.

Simon Ochsenreither

unread,
May 27, 2013, 1:03:54 PM5/27/13
to scala-i...@googlegroups.com
In a sense, I think the idea about recommending : Unit = is quite similar to the reason why we started to emit a warning for catching exceptions with case _: “If you really want that, please think about future readers of your code and be explicit about your intention.”.

Rex Kerr

unread,
May 27, 2013, 1:11:01 PM5/27/13
to scala-i...@googlegroups.com
Indeed.  Note that NonFatal was introduced at the same time to make it easier to do the right thing instead of just slapping your hand when you do the wrong thing.

But that's what def f { } already is--a slightly longer way to do the right thing--and why I don't object to def f = println generating a warning.

  --Rex



On Mon, May 27, 2013 at 1:03 PM, Simon Ochsenreither <simon.och...@gmail.com> wrote:
In a sense, I think the idea about recommending : Unit = is quite similar to the reason why we started to emit a warning for catching exceptions with case _: “If you really want that, please think about future readers of your code and be explicit about your intention.”.

Paul Phillips

unread,
May 27, 2013, 1:15:34 PM5/27/13
to scala-i...@googlegroups.com

On Mon, May 27, 2013 at 9:49 AM, Simon Ochsenreither <simon.och...@gmail.com> wrote:
That's pretty much the only thing Go managed to do right: They have go fix, which can rewrite existing code without user input.

Let us not believe ourselves too superior to Go. They did this:

"The Go language has always been defined by a spec, not an implementation. The Go team has written two different compilers that implement that spec: gc and gccgo. Having two different implementations helps ensure that the spec is complete and correct: when the compilers disagree, we fix the spec, and change one or both compilers accordingly."

I would give my left arm to see things prioritized in this fashion, instead of like this. https://groups.google.com/forum/?fromgroups=#!topic/scala-language/SMru3oz2gc4 

Som Snytt

unread,
May 27, 2013, 2:43:49 PM5/27/13
to scala-internals
And this:

> Since Go 1.0, the core received more than 2600 commits from 161 people outside Google.

So long as I'm bike-shedding, I agree with Rex, except that the warnings should be under -Xlint, which everyone should be using.  The utility of procedural syntax is that Scala doesn't disallow side-effectiveness, and in my limited experience, ": Unit =" is too verbose unless it facilitates a one-liner.  That would be one line of side effect.

Also, how did the wrong wrong wrong scaladoc style leak over to:

http://docs.scala-lang.org/style/scaladoc.html

I say "wrong" because the correct style is a way for the closing slash not to impinge typographically on the comment text.

Possibly, before the doc sprint, the code didn't include enough doc to set a precedent.

(As a total noob/nuli, I adopted the first style as advocated by the style doc, which is mathematically (alignment on multiples of two columns) and rectilinearly cleaner.  Neither style solves the problem of switching to non-scaladoc without a formatter. But the second style now looks to me like a flag planted atop the code. Happy Memorial Day.)

/** Foo is something useful.
  * Too bad the PR is rejected because the
  * Scaladoc comment is wrong wrong wrong.
  */
class Foo {
}

/** Bar is a refinement of Foo.
 *  In the Scala type system, refinement = improvement.
 */
class Bar extends Foo {
}

/***** .........
 ***** .........
 ***** .........
 ...............
 ...............
 *
 *
 */




--

Kevin Wright

unread,
May 27, 2013, 5:29:41 PM5/27/13
to scala-i...@googlegroups.com
Personally, I LIKE that facilitation of one liners.
Aiming for small single-responsibility methods is a Good Thing™, and I do so strive towards single statement methods where possible.

If `: Unit` is like a flag at the top of such a method, then surely a trailing `}` must be the exposed outlet of the garderobe chute.  Ruining the nice clean lines of an otherwise elegant tower, until such time as modern plumbing is installed.

Also… Shouldn't we be subtly discouraging code that's ripe with side effects as a not-best practice, in much the same way as we discourage casting with the purposely verbose `asInstanceOf`?


Simon Ochsenreither

unread,
May 27, 2013, 6:38:20 PM5/27/13
to scala-i...@googlegroups.com

"The Go language has always been defined by a spec, not an implementation. The Go team has written two different compilers that implement that spec: gc and gccgo. Having two different implementations helps ensure that the spec is complete and correct: when the compilers disagree, we fix the spec, and change one or both compilers accordingly."

Well, writing a spec for a language whose expressiveness is slightly above Brainfuck isn't _that_ hard ... :-P ... but hey, I completely agree with you.
 
I would give my left arm to see things prioritized in this fashion, instead of like this. https://groups.google.com/forum/?fromgroups=#!topic/scala-language/SMru3oz2gc4 

I think I've done my share of work. Note the "... opened this pull request " bit.

Simon Ochsenreither

unread,
May 27, 2013, 6:54:18 PM5/27/13
to scala-i...@googlegroups.com

The utility of procedural syntax is that Scala doesn't disallow side-effectiveness, and in my limited experience, ": Unit =" is too verbose unless it facilitates a one-liner.  That would be one line of side effect.

The only thing I can say is that it's not my experience, but that it is the experience I gained from having worked with "beginners", sitting down with them and asking them about their experience: the confusion about the difference between def-with-= vs. def-with-no-= is a _huge_ issue.

The question is, why are we causing this huge confusion for basically no tangible benefit? Imho, it would be a lot easier to explain and more consistent if one could say "every member implementation consists of an =, separating the signature to the left and the body to the right".

 
Also, how did the wrong wrong wrong scaladoc style leak over to:

http://docs.scala-lang.org/style/scaladoc.html

I say "wrong" because the correct style is a way for the closing slash not to impinge typographically on the comment text.

Oooops, it's possible that could have been adapted/caused by me. That was at the time where I was working on ScalaDoc and realized that basically _no_ one understands the rules around the "Java-style" comments and code-in-comments, with the result that pretty much all the code examples to this day have an unintended, wrong indentation in the HTML output.

I tried to fix it by replacing the imho extremely unintuitive rules with something more consistent, but as far as I remember, it was shot down in the end because it was "not enough like Java".

Rex Kerr

unread,
May 27, 2013, 7:10:51 PM5/27/13
to scala-i...@googlegroups.com
On Mon, May 27, 2013 at 6:54 PM, Simon Ochsenreither <simon.och...@gmail.com> wrote:

The utility of procedural syntax is that Scala doesn't disallow side-effectiveness, and in my limited experience, ": Unit =" is too verbose unless it facilitates a one-liner.  That would be one line of side effect.

The only thing I can say is that it's not my experience, but that it is the experience I gained from having worked with "beginners", sitting down with them and asking them about their experience: the confusion about the difference between def-with-= vs. def-with-no-= is a _huge_ issue.

I am not sure how these beginners learned Scala, but I see this mistake very rarely in StackOverflow questions.  I suspect that your sample is biased.  (Mine may be also.)

Questions around def f() vs def f come up way more often, as do questions about map(_ + 5) vs map((_ + 5)*2).  A question which is basically "why don't we have tap and/or pipe" comes up every few months.  Then there's the "what's f(x: Int)(y: Int) anyway" question, and the how-the-heck-do-you-use-Option question, and the I-don't-know-how-to-use-Try question, and so on.  I have seen the f {} vs f = question a few times, but its way down the list, and unlike some of the others, I haven't seen people go, "Wha, huh, I still don't get it?!" or "Arrrrgh, my life would be so much easier if you would just make me type : Unit = every time" after a two-line explanation:
  When you write def f { }, f will run the enclosed code and return () (i.e. nothing, Unit).
  When you write def f: X = expr, f will run the expr and produce X; omit the type X to have it inferred
For beginners to whom that explanation doesn't make sense, you need a few more words, of course (e.g. an intro to types and return values).  But it's really simple.
 

The question is, why are we causing this huge confusion for basically no tangible benefit? Imho, it would be a lot easier to explain and more consistent if one could say "every member implementation consists of an =, separating the signature to the left and the body to the right".

If it really is a huge confusion, I'd reconsider.  But I think it's a small confusion.  And I don't know how you develop in Scala, but I would notice typing : Unit = a bunch of extra times.  And it's really easy to pick out the side-effecting methods visually now (obligatory) because they have no return type.  If you write everything with : Unit =, suddenly the visual difference goes way down.

The Unit type is the unique return type that signals that side effects are the whole point (even if it's just warming up the CPU).  I like the visual difference as well as the brevity.

  --Rex

 

Simon Ochsenreither

unread,
May 27, 2013, 7:28:31 PM5/27/13
to scala-i...@googlegroups.com
Hi!


I am not sure how these beginners learned Scala, but I see this mistake very rarely in StackOverflow questions.  I suspect that your sample is biased.  (Mine may be also.)

Questions around def f() vs def f come up way more often, as do questions about map(_ + 5) vs map((_ + 5)*2).  A question which is basically "why don't we have tap and/or pipe" comes up every few months.  Then there's the "what's f(x: Int)(y: Int) anyway" question, and the how-the-heck-do-you-use-Option question, and the I-don't-know-how-to-use-Try question, and so on.  I have seen the f {} vs f = question a few times, but its way down the list, and unlike some of the others, I haven't seen people go, "Wha, huh, I still don't get it?!" or "Arrrrgh, my life would be so much easier if you would just make me type : Unit = every time" after a two-line explanation:
  When you write def f { }, f will run the enclosed code and return () (i.e. nothing, Unit).
  When you write def f: X = expr, f will run the expr and produce X; omit the type X to have it inferred
For beginners to whom that explanation doesn't make sense, you need a few more words, of course (e.g. an intro to types and return values).  But it's really simple.

The point between all these examples you made and the procedure syntax is that there is a reasonable explanation for them. People benefit from knowing why things work this way.
That's just not the case for the procedure thing. It's just some random public-static-void-main bullshit we throw at them for absolutely no good reason. I want to reduce exactly that beginner-hostile non-sense, because I believe a person shouldn't need to become some "elite" coder who remembers all weird gotchas to leverage Scala for his/her projects.

The point is that I have taken my time, sat down with those learning the language and asked them _explicitly_ "from your limited experience, what part of Scala sucks?" and the procedure-vs.-method thing is one of the main points where everyone says "yes, one can learn it, but there seems to be no apparent reason why it is that way, apart from being a pointless nuisance". I assume that people are often too embarrassed/frustrated to ask that question online, because they probably think that a) it's so basic that it should just work and b) assume that the IDE/REPL is somehow broken c) they didn't install things correctly.


If it really is a huge confusion, I'd reconsider.  But I think it's a small confusion.  And I don't know how you develop in Scala, but I would notice typing : Unit = a bunch of extra times.  And it's really easy to pick out the side-effecting methods visually now (obligatory) because they have no return type.  If you write everything with : Unit =, suddenly the visual difference goes way down

If there would be an alternative which prevents people from mistakenly creating procedures instead of methods AND wouldn't introduce yet another syntactic inconsistency, I would love to hear about it.

Bye,

Simon

Paul Phillips

unread,
May 27, 2013, 7:43:23 PM5/27/13
to scala-i...@googlegroups.com
On Mon, May 27, 2013 at 4:28 PM, Simon Ochsenreither <simon.och...@gmail.com> wrote:
The point between all these examples you made and the procedure syntax is that there is a reasonable explanation for them. People benefit from knowing why things work this way.
That's just not the case for the procedure thing. It's just some random public-static-void-main bullshit we throw at them for absolutely no good reason.

I don't find this distinction so easy to draw. I think we throw plenty of it at them for absolutely no good reason.

Rex Kerr

unread,
May 27, 2013, 8:04:23 PM5/27/13
to scala-i...@googlegroups.com
On Mon, May 27, 2013 at 7:28 PM, Simon Ochsenreither <simon.och...@gmail.com> wrote:
Hi!


I am not sure how these beginners learned Scala, but I see this mistake very rarely in StackOverflow questions.  I suspect that your sample is biased.  (Mine may be also.)

Questions around def f() vs def f come up way more often, as do questions about map(_ + 5) vs map((_ + 5)*2).  A question which is basically "why don't we have tap and/or pipe" comes up every few months.  Then there's the "what's f(x: Int)(y: Int) anyway" question, and the how-the-heck-do-you-use-Option question, and the I-don't-know-how-to-use-Try question, and so on.  I have seen the f {} vs f = question a few times, but its way down the list, and unlike some of the others, I haven't seen people go, "Wha, huh, I still don't get it?!" or "Arrrrgh, my life would be so much easier if you would just make me type : Unit = every time" after a two-line explanation:
  When you write def f { }, f will run the enclosed code and return () (i.e. nothing, Unit).
  When you write def f: X = expr, f will run the expr and produce X; omit the type X to have it inferred
For beginners to whom that explanation doesn't make sense, you need a few more words, of course (e.g. an intro to types and return values).  But it's really simple.

The point between all these examples you made and the procedure syntax is that there is a reasonable explanation for them. People benefit from knowing why things work this way.
That's just not the case for the procedure thing.

"It's to more clearly distinguish procedures, which presumably have side effects, from functions, which often do not."

That's not a reasonable explanation?  Not at least as reasonable as why (_ + 5) works but ((_ + 5)*2) doesn't?  Why we don't have tap or pipe in the standard library?
 
It's just some random public-static-void-main bullshit we throw at them for absolutely no good reason. I want to reduce exactly that beginner-hostile non-sense, because I believe a person shouldn't need to become some "elite" coder who remembers all weird gotchas to leverage Scala for his/her projects.

If people can't remember something this simple, something else is badly wrong.  Maybe they're being asked to remember too much in one go.  As far as easy and obvious goes, this is way up there.

A method-procedure doesn't return a value.  So, don't write =.
A method-function does return a value.  So, write =.
So we don't need to special-case procedures, we pretend they return a value we call () of type Unit, and fill it in if we convert a procedural method into a Function.
 
 

If there would be an alternative which prevents people from mistakenly creating procedures instead of methods AND wouldn't introduce yet another syntactic inconsistency, I would love to hear about it.

No, no, you're missing my point.  In order to clarify what's side-effecting you WANT a syntactic inconsistency.  This is exactly what tells you at a glance to be careful!

I suppose we could name Unit

ImSoSorryButIJustWantThisToWorkIKnowItsSideEffectingImNotABadPersonOkay

which would also let you tell at a glance that something is going on.

  --Rex
 

Simon Ochsenreither

unread,
May 27, 2013, 8:17:24 PM5/27/13
to scala-i...@googlegroups.com
Hi,


A method-procedure doesn't return a value.  So, don't write =.
A method-function does return a value.  So, write =.

I think that reasoning could be used in Java, but in Scala, where Unit actually has a value, it's blatantly wrong and misleading.
If there was a type, which should qualify to work without =, it's Nothing, but weirdly a method of type Nothing requires the =.

 
So we don't need to special-case procedures, we pretend they return a value we call () of type Unit, and fill it in if we convert a procedural method into a Function.

I think the thing above is not only a special-case, but it is one for which one can't find a decent explanation. Every point why Unit shouldn't require = applies even more to Nothing.

 
If there would be an alternative which prevents people from mistakenly creating procedures instead of methods AND wouldn't introduce yet another syntactic inconsistency, I would love to hear about it.

No, no, you're missing my point.  In order to clarify what's side-effecting you WANT a syntactic inconsistency.  This is exactly what tells you at a glance to be careful!

There are tons of people who DON't WANT to have a side-effect at all, but keep falling into the procedure-trap. If this wouldn't happen at the rate I'm seeing, I wouldn't care that much about procedures.


I suppose we could name Unit

ImSoSorryButIJustWantThisToWorkIKnowItsSideEffectingImNotABadPersonOkay

which would also let you tell at a glance that something is going on.

Sure, you could even pick some nice Unicode symbol as a type alias which stands out in your code. Or just let the IDE do its job, just like it does for val vs. var.

Rex Kerr

unread,
May 27, 2013, 8:35:51 PM5/27/13
to scala-i...@googlegroups.com
On Mon, May 27, 2013 at 8:17 PM, Simon Ochsenreither <simon.och...@gmail.com> wrote:
Hi,


A method-procedure doesn't return a value.  So, don't write =.
A method-function does return a value.  So, write =.

I think that reasoning could be used in Java, but in Scala, where Unit actually has a value, it's blatantly wrong and misleading.

class Proc {
  var x = 0
  def proc { x += 1 }
}

public void proc();
  Code:
   0:    aload_0
   1:    aload_0
   2:    invokevirtual    #22; //Method x:()I
   5:    iconst_1
   6:    iadd
   7:    invokevirtual    #24; //Method x_$eq:(I)V
   10:    return

Get us off the JVM entirely and to something where this isn't the sensible encoding and fine, I'll accept "blatantly wrong and misleading".  I know you'd _like_ to, but there really is no return value and there's no harm in reflecting that until the time when there actually is a return value under the hood.  For now it reflects reality *better* than the fiction of Unit.

Just ask f(i: Int)(j: Int) and its good friend f(i: Int, j: Int) about fictions.

If there was a type, which should qualify to work without =, it's Nothing, but weirdly a method of type Nothing requires the =.

There's nowhere convenient to put the type ascription without the =.
 

 
So we don't need to special-case procedures, we pretend they return a value we call () of type Unit, and fill it in if we convert a procedural method into a Function.

I think the thing above is not only a special-case, but it is one for which one can't find a decent explanation. Every point why Unit shouldn't require = applies even more to Nothing.

But sure.  It's a bit ugly, I think it'd be fine to be able to declare Nothing instead of Unit, if you really wanted to.  Does that come up much?
 

 
If there would be an alternative which prevents people from mistakenly creating procedures instead of methods AND wouldn't introduce yet another syntactic inconsistency, I would love to hear about it.

No, no, you're missing my point.  In order to clarify what's side-effecting you WANT a syntactic inconsistency.  This is exactly what tells you at a glance to be careful!

There are tons of people who DON't WANT to have a side-effect at all, but keep falling into the procedure-trap. If this wouldn't happen at the rate I'm seeing, I wouldn't care that much about procedures.

If they don't want to have side-effects and think it's not null, how do they get past the type system later on when they have Unit where they expect some other type?  And I said long ago that I'm okay with f = println giving a warning.

For everything else, I'd be way more worried if Scala was dynamic.

Anyway, I think we've made our positions clear.

  --Rex

P.S. If your IDE can color it for you, it can rewrite f { } into f: Unit = { } for you.
 

Simon Ochsenreither

unread,
May 27, 2013, 8:56:03 PM5/27/13
to scala-i...@googlegroups.com

Get us off the JVM entirely and to something where this isn't the sensible encoding and fine, I'll accept "blatantly wrong and misleading".  I know you'd _like_ to, but there really is no return value and there's no harm in reflecting that until the time when there actually is a return value under the hood.  For now it reflects reality *better* than the fiction of Unit.

Arguing about implementation details is incredibly pointless, imho. Using the same argument you could say that all methods which return a tuple return a single value when you look behind the covers. Yes, but it's utterly useless distinction. The point I was making with the Java vs. Scala comparison is that Java looks at it from a how-does-it-mutate-the-stack POV where Scala adopts an (imho) better data-flow POV ("how much data goes into and out of a method?").

 
But sure.  It's a bit ugly, I think it'd be fine to be able to declare Nothing instead of Unit, if you really wanted to.  Does that come up much?

No, because Nothing doesn't make it so incredibly convenient to mistakenly use it.

 
If they don't want to have side-effects and think it's not null, how do they get past the type system later on when they have Unit where they expect some other type?  And I said long ago that I'm okay with f = println giving a warning.

Because they are still learning the language and often write some methods down without necessarily wiring them up in the same turn. They assume that they wrote a method, but in reality they wrote a procedure instead. Then they run it and keep wondering why they don't get any values back. Incredibly frustrating. For some, their Scala journey ends right there.

 
P.S. If your IDE can color it for you, it can rewrite f { } into f: Unit = { } for you.

Agree. I'll look into the refactoring code, so that the IDE can get rid of the special syntax without requiring user interaction.

Roland Kuhn

unread,
May 28, 2013, 3:00:07 AM5/28/13
to scala-i...@googlegroups.com
28 maj 2013 kl. 02:04 skrev Rex Kerr:

I suppose we could name Unit

ImSoSorryButIJustWantThisToWorkIKnowItsSideEffectingImNotABadPersonOkay

Please stop spreading this FUD, especially while relating it to “bad persons”: side-effecting is not universally bad. Note how my statement differs from “side-effecting is universally good”. It is a tool which every program must eventually use.

Regards,

Rex Kerr

unread,
May 28, 2013, 4:55:00 AM5/28/13
to scala-i...@googlegroups.com
Goodness, sorry--I just thought it was amusing!

I use side-effecting code all the time, and functional code all the time, and recognize that most people see the value in both even at the level of hardware abstraction offered by Scala.  I was just (apparently unsuccessfully) making fun of the holier-than-thou attitude that occasionally crops up with functional programming.  (I did not intend that aspect of it to be a criticism of Simon's position either, which I take to be favoring explicitness and simplicity--the latter of which I support, but the former of which I only sometimes do.)

  --Rex




Roland Kuhn

unread,
May 28, 2013, 5:22:55 AM5/28/13
to scala-i...@googlegroups.com
Okay, thanks for the clarification, maybe I read your mail too quickly and missed the “making fun” part. We are in agreement about the intentions, then.

Regards,

Roland

nafg

unread,
May 28, 2013, 6:35:48 AM5/28/13
to scala-i...@googlegroups.com


On Monday, May 27, 2013 2:43:49 PM UTC-4, som-snytt wrote:
Also, how did the wrong wrong wrong scaladoc style leak over to:

http://docs.scala-lang.org/style/scaladoc.html

I say "wrong" because the correct style is a way for the closing slash not to impinge typographically on the comment text.

Possibly, before the doc sprint, the code didn't include enough doc to set a precedent.

(As a total noob/nuli, I adopted the first style as advocated by the style doc, which is mathematically (alignment on multiples of two columns) and rectilinearly cleaner.  Neither style solves the problem of switching to non-scaladoc without a formatter. But the second style now looks to me like a flag planted atop the code. Happy Memorial Day.)

/** Foo is something useful.
  * Too bad the PR is rejected because the
  * Scaladoc comment is wrong wrong wrong.
  */
class Foo {
}

/** Bar is a refinement of Foo.
 *  In the Scala type system, refinement = improvement.
 */
class Bar extends Foo {
}

/***** .........
 ***** .........
 ***** .........
 ...............
 ...............
 *
 *
 */



I thought the "important" question was which line the text starts on.
 

nafg

unread,
May 28, 2013, 6:37:26 AM5/28/13
to scala-i...@googlegroups.com
By the way, shouldn't this be on scala-debate or something?

Lukas Rytz

unread,
May 28, 2013, 7:13:31 AM5/28/13
to scala-i...@googlegroups.com
On Tue, May 28, 2013 at 12:37 PM, nafg <nafto...@gmail.com> wrote:
By the way, shouldn't this be on scala-debate or something?

+1
 
--

Simon Ochsenreither

unread,
May 28, 2013, 8:36:00 AM5/28/13
to scala-i...@googlegroups.com

Rex Kerr

unread,
May 28, 2013, 11:03:04 AM5/28/13
to scala-i...@googlegroups.com
On Mon, May 27, 2013 at 8:56 PM, Simon Ochsenreither <simon.och...@gmail.com> wrote:

 
P.S. If your IDE can color it for you, it can rewrite f { } into f: Unit = { } for you.

Agree. I'll look into the refactoring code, so that the IDE can get rid of the special syntax without requiring user interaction.

Is there already a "insert explicitly the inferred return type" option?  If so, this should be easy.  If not, that would be a really valuable feature as well.

  --Rex

P.S. Regarding frustration, f(i: Int) { i + 1 } could be a gotcha also; maybe it would make sense to warn about that also (i.e. if the statement is an expression not returning unit).
 

Kevin Wright

unread,
May 28, 2013, 11:10:13 AM5/28/13
to scala-i...@googlegroups.com
+2 (one for each point)

I know I've already seen the warning before about the value of an expression being discarded, can't recall if it was from intellij or a compiler option though.


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

Johannes Rudolph

unread,
May 28, 2013, 11:12:53 AM5/28/13
to scala-i...@googlegroups.com
On Tue, May 28, 2013 at 5:03 PM, Rex Kerr <ich...@gmail.com> wrote:
P.S. Regarding frustration, f(i: Int) { i + 1 } could be a gotcha also; maybe it would make sense to warn about that also (i.e. if the statement is an expression not returning unit).

There's already `-Ywarn-value-discard` which seems to work:

λ scala -Ywarn-value-discard
Welcome to Scala version 2.10.1 (OpenJDK 64-Bit Server VM, Java 1.7.0_21).
Type in expressions to have them evaluated.
Type :help for more information.

scala> def f(i: Int) { i + 1 } 
<console>:7: warning: discarded non-Unit value
       def f(i: Int) { i + 1 } 
                         ^
f: (i: Int)Unit


--
Johannes

-----------------------------------------------
Johannes Rudolph
http://virtual-void.net

Simon Ochsenreither

unread,
May 28, 2013, 12:13:41 PM5/28/13
to scala-i...@googlegroups.com, johannes...@googlemail.com
Agree.

Is there consensus on the trait Foo { def foo } bit? If yes, I can create a pull request for it now.

Paul Phillips

unread,
May 28, 2013, 12:14:28 PM5/28/13
to scala-i...@googlegroups.com
And I'm not sure offhand why this one doesn't trigger.

scala> { 7 ; 8 }
<console>:8: warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses
              { 7 ; 8 }
                ^
res3: Int = 8

Jeff Olson

unread,
May 28, 2013, 1:30:01 PM5/28/13
to scala-i...@googlegroups.com, johannes...@googlemail.com


On Tuesday, May 28, 2013 11:13:41 AM UTC-5, Simon Ochsenreither wrote:
Agree.

Is there consensus on the trait Foo { def foo } bit? If yes, I can create a pull request for it now.

I agree that trait Foo { def foo } is bad, but I think trait Foo { def foo: Unit } is equally bad. It should always be trait Foo { def foo() }. Then intentions are clear--foo has side-effects and doesn't return anything. I think that trait Foo { def foo(): Unit } adds nothing but clutter.

-Jeff

Simon Ochsenreither

unread,
May 28, 2013, 1:37:33 PM5/28/13
to scala-i...@googlegroups.com, johannes...@googlemail.com

Simon Ochsenreither

unread,
May 28, 2013, 1:39:16 PM5/28/13
to scala-i...@googlegroups.com, johannes...@googlemail.com

I agree that trait Foo { def foo } is bad, but I think trait Foo { def foo: Unit } is equally bad. It should always be trait Foo { def foo() }. Then intentions are clear--foo has side-effects and doesn't return anything. I think that trait Foo { def foo(): Unit } adds nothing but clutter.

The huge issue I have is with consistency, not with conciseness. I think it would be great to have ONE, consistent rule like "a method needs either a body to infer the result type or an explicit result type annotation".

Jeff Olson

unread,
May 28, 2013, 2:03:55 PM5/28/13
to scala-i...@googlegroups.com, johannes...@googlemail.com


On Tuesday, May 28, 2013 12:39:16 PM UTC-5, Simon Ochsenreither wrote:

I agree that trait Foo { def foo } is bad, but I think trait Foo { def foo: Unit } is equally bad. It should always be trait Foo { def foo() }. Then intentions are clear--foo has side-effects and doesn't return anything. I think that trait Foo { def foo(): Unit } adds nothing but clutter.

The huge issue I have is with consistency, not with conciseness. I think it would be great to have ONE, consistent rule like "a method needs either a body to infer the result type or an explicit result type annotation".

It would be even more consistent to require explicit type annotations everywhere. Clearly there are trade-offs between consistency and conciseness, and you would draw the line somewhere differently than I would. But I think if we change the rules now we are going to aggravate quite a number of people, myself among them.

For the record I also prefer def foo() { ... } for side-effecting methods over def foo(): Unit = { ... } for much the same reasons as Rex. It's clear, concise, and syntactically obvious that foo doesn't return anything.

-Jeff

Simon Ochsenreither

unread,
May 28, 2013, 3:33:36 PM5/28/13
to scala-i...@googlegroups.com, johannes...@googlemail.com

It would be even more consistent to require explicit type annotations everywhere.

Exactly. That's what already happens! All abstract methods require a type annotation – EXCEPT Unit. This is exactly the inconsistency I want to fix.

 
Clearly there are trade-offs between consistency and conciseness, and you would draw the line somewhere differently than I would. But I think if we change the rules now we are going to aggravate quite a number of people, myself among them.

Sure, there are trade-offs, but I strongly oppose the idea that it is somehow defensible that we let _every_ beginner suffer through the method-vs.-procedure madness so that a few people save 5 chars for accomplishing something which isn't even idiomatic Scala.

 
For the record I also prefer def foo() { ... } for side-effecting methods over def foo(): Unit = { ... } for much the same reasons as Rex. It's clear, concise, and syntactically obvious that foo doesn't return anything.

As probably mentioned the umpteenth time, it's not syntactically obvious for most people as clearly demonstrated by the "why doesn't my method return anything"-confusion when people forget the =.

Simon Ochsenreither

unread,
May 29, 2013, 4:29:31 AM5/29/13
to scala-i...@googlegroups.com, johannes...@googlemail.com
I implemented the mentioned bit about missing result type for abstract methods: https://github.com/scala/scala/pull/2604/files
Killing this special case will allow the removal of the complete chapter 4.6.3, which amounts to 70% of a page.

Som Snytt

unread,
May 29, 2013, 12:41:29 PM5/29/13
to scala-internals
Has no one suggested import scala.language.procedures?

The compiler could special-case the definition of main so that the first day of Scala class goes without a hitch.


> I strongly oppose the idea that it is somehow defensible that we let _every_ beginner suffer through the method-vs.-procedure madness

I honestly love this sort of language, and I only I wish it were on scala-debate so you wouldn't have to hold back.

I picture the opposing counsel jumping to his/her feet and barking, "I object!"  The courtroom erupts!  Pandemonium ensues!

It does take me the umpteenth time to think of something to contribute: It's possible procedure syntax forces beginners to cope with the conceptual hump of everything evaluating to something, which is why they forget the equals sign.  I remember that ": Unit" seemed strange to me because of that hump, and by conceptual hump I mean hurdle and not brain-f--k.

Here is the fascinating moment in PiS when unit value is introduced, the context is loops and not procedures:

http://www.artima.com/pins1ed/builtin-control-structures.html#7.2





--

Simon Ochsenreither

unread,
May 29, 2013, 5:14:34 PM5/29/13
to scala-i...@googlegroups.com
Hey,


Has no one suggested import scala.language.procedures?
 
indeed, that sounds like a good compromise!


The compiler could special-case the definition of main so that the first day of Scala class goes without a hitch.

I think one can go a long time with just sticking to App.


> I strongly oppose the idea that it is somehow defensible that we let _every_ beginner suffer through the method-vs.-procedure madness

I honestly love this sort of language, and I only I wish it were on scala-debate so you wouldn't have to hold back.

I picture the opposing counsel jumping to his/her feet and barking, "I object!"  The courtroom erupts!  Pandemonium ensues!

No native speaker, don't understand whether what you said is positive/negative/ironic/...
But hey, I _did_ create a thread on scala-debate! :-D (And even there all the rules apply, right? Afaik, scala-functional is the only free-speech zone when it comes to Scala-related mailing lists, right?)


It does take me the umpteenth time to think of something to contribute: It's possible procedure syntax forces beginners to cope with the conceptual hump of everything evaluating to something, which is why they forget the equals sign.  I remember that ": Unit" seemed strange to me because of that hump, and by conceptual hump I mean hurdle and not brain-f--k.

I think forgetting the equals sign is not caused by overthinking it, it's just that: forgetting.

Thanks and bye,

Simon

Simon Ochsenreither

unread,
Jun 24, 2013, 6:18:45 PM6/24/13
to scala-i...@googlegroups.com
I have created a new issue¹ for the procedure syntax part, listing the requirements mentioned in this thread.

A remaining issue is what (if anything) should be done with secondary constructors?
I'm slightly leaning towards allowing it without the = for now, because the return type will always be the same.²
Opinions?

¹ https://issues.scala-lang.org/browse/SI-7605
² Although the question whether a constructor should return Unit or the actual type in question is a larger topic for itself.

Simon Ochsenreither

unread,
Oct 23, 2013, 7:11:13 PM10/23/13
to scala-i...@googlegroups.com
Hi!

The style guide has been updated a while ago. Here is the pull request which adds deprecation warnings, hidden behind -Xfuture. This PR is a requirement for IDE support (the editor needs to receive some kind of warning to be able to offer a quick fix as far as I understand). Meanwhile I'll look into IntelliJ's syntax checking tool.

Thanks,

Simon

Rich Oliver

unread,
Oct 25, 2013, 2:12:24 PM10/25/13
to scala-i...@googlegroups.com
Is it really OK that the following only gives 1 warning and no errors?

object MyApp extends App {  
   val x = new MyC1
   val y = x.g
}

abstract class MyC {
   def g
}
 
 class MyC1 extends MyC {
   def g = 5
 }

James Iry

unread,
Oct 25, 2013, 2:24:13 PM10/25/13
to scala-i...@googlegroups.com
Without Simon's PR on "def g = 5" you get "warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses" which I'm sure is pretty confusing. With Simon's PR it moves to the line "def g" where you get "Procdure syntax is deprecated." Already that's a great improvement because the real source of the problem is highlighted. Presumably the deprecation will morph into an error eventually.

Rich Oliver

unread,
Oct 25, 2013, 2:58:36 PM10/25/13
to scala-i...@googlegroups.com
Being of the TypeSafer faction, I think Unit, Any and AnyRef should all require explicit type annotation.

Naftoli Gugenheim

unread,
Oct 28, 2013, 8:04:03 PM10/28/13
to scala-i...@googlegroups.com
On Fri, Oct 25, 2013 at 2:24 PM, James Iry <jame...@typesafe.com> wrote:
Without Simon's PR on "def g = 5" you get "warning: a pure expression does nothing in statement position; you may be omitting necessary parentheses" which I'm sure is pretty confusing. With Simon's PR it moves to the line "def g" where you get "Procdure syntax is deprecated." Already that's a great improvement because the real source of the problem is highlighted.

Shouldn't it still have the second warning? What about this?

//lib.scala
trait C {
  def doSomething(): Unit
}
//app.scala
object C extends C {
  def doSomething() = 5
}

 
Presumably the deprecation will morph into an error eventually.

On Oct 25, 2013, at 11:12 AM, Rich Oliver <rzi...@gmail.com> wrote:

Is it really OK that the following only gives 1 warning and no errors?

object MyApp extends App {  
   val x = new MyC1
   val y = x.g
}

abstract class MyC {
   def g
}
 
 class MyC1 extends MyC {
   def g = 5
 }

--
You received this message because you are subscribed to the Google Groups "scala-internals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to scala-interna...@googlegroups.com.

For more options, visit https://groups.google.com/groups/opt_out.

--
You received this message because you are subscribed to a topic in the Google Groups "scala-internals" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/scala-internals/q1YX7NC1geM/unsubscribe.
To unsubscribe from this group and all its topics, send an email to scala-interna...@googlegroups.com.

Simon Ochsenreither

unread,
Nov 15, 2013, 12:11:16 PM11/15/13
to scala-i...@googlegroups.com
Hi!

One remaining question: What to do with constructors?

Keeping the procedure syntax only for constructors seems to be a bit of an ugly corner case, but applying the same rules like for all the other Unit-returning methods won't work, because def this(...): Unit = ... is no valid Scala.

Imho, what makes the most sense is to suggest/migrate people to def this(...) = ... and mention/explain it in the Scala Style Guide (e. g. "the return type of a constructor is obvious, that's why one doesn't need Unit").

What do you think, Martin?

Thanks and bye,

Simon

Naftoli Gugenheim

unread,
Nov 29, 2013, 3:37:52 AM11/29/13
to scala-i...@googlegroups.com
Well, are auxiliary constructors a kind of method?
If not, I wouldn't consider the syntax a corner case... it's special syntax for special semantics.



--
Reply all
Reply to author
Forward
0 new messages