bug icon indicating copy to clipboard operation
bug copied to clipboard

please allow value definitions before the first generator in a for comprehension

Open scabug opened this issue 17 years ago • 15 comments

I would like to be able to write this:

for{x = foo(bar); y <- x} ...

the language spec (6.19) says "An enumerator sequence always starts with a generator", but why? From time to time I would find it convenient to put a value definition first. I realize that in the above code I only use x once, but I've hit this in real code where I want to use x more than once.

(Perhaps "if" should be allowed too?)

scabug avatar May 14 '08 11:05 scabug

Imported From: https://issues.scala-lang.org/browse/SI-907?orig=1 Reporter: @SethTisue

scabug avatar May 14 '08 11:05 scabug

@paulp said: While I agree with the sentiment on an aesthetic level, the overhead of such a change (in implementation and testing as well as updating the language spec, documentation, and etc.) has been deemed too high to justify it, as the known use cases are marginal. So I'm closing this as wontfix, but please update the ticket if you come across a compelling motivation.

scabug avatar Feb 19 '09 13:02 scabug

@som-snytt said: It's pretty compelling that Seth is now in a position to do whatever he likes with a three-digit issue.

scabug avatar Dec 11 '16 23:12 scabug

Samuel Halliday (fommil) said: Is there any reason this couldn't be implemented as a parser rewrite to move the value definition out of the for?

e.g. rewrite Seth's original example as

val x = foo(bar)
for {y <- x}

scabug avatar Apr 02 '17 16:04 scabug

I'd really like to see this ticket reopened.

fommil avatar Apr 25 '17 12:04 fommil

I'm not sure this workaround:

val x = foo(bar)
for {y <- x}

is worth it. I think we have already enough desugarings in parser. Putting more would force all the Scala tooling to catch up and I don't think it's a neat solution overall, but rather a hack.

jvican avatar Apr 25 '17 12:04 jvican

for FP code this is definitely worth it. This comes up all the time when for is your main language structure for sequential code.

fommil avatar Apr 25 '17 12:04 fommil

btw, apparently we should be discussing at https://contributors.scala-lang.org/t/ressurrect-assignment-as-first-line-of-for/808

fommil avatar Apr 25 '17 12:04 fommil

it appears this was closed because the core team at the time didn't intend to tackle it, not because it would necessarily be rejected if it came in as a community contribution (including the necessary spec work and so forth)

SethTisue avatar May 09 '17 22:05 SethTisue

an example usage with Future via @viktorklang: https://twitter.com/viktorklang/status/861982357800308737

SethTisue avatar May 09 '17 22:05 SethTisue

further food for thought in this area at https://contributors.scala-lang.org/t/pre-sip-let-expressions-in-scala/1391/1

SethTisue avatar Dec 12 '17 23:12 SethTisue

came up again at https://contributors.scala-lang.org/t/allow-simple-vals-to-appear-first-in-for-expression/5428

SethTisue avatar Nov 12 '21 16:11 SethTisue

I would like to go even further and allow for comprehensions with only value definitions and no generators. It would be like defining a bunch of vals without having to write val each time.

One of the really nice things about Scala is that changing code in a limited way often involves few edits. For instance to change a binding from immediately-evaluate-once to deferred-evaluate-every-time you just change val to def while in say Java you'd have to change a whole bunch of syntax (add parentheses, curly braces, and return). To make a function's scope persist (a.k.a. change a method to a class) is a bit more work but not nearly as much as in say Java, because it's still basically just keyword-name-arguments-body. And so on.

Additionally, most constructs don't have a very strict, conservative set of ways to apply it. Constructs are usually limited only for very good reasons. For instance you can nest methods inside classes inside pattern matches etc. Vals can have block statements on their right-hand side. And there isn't different syntax for class members vs. local bindings.

Together this means that you can take a more "agile" approach to writing code, not worrying up front what form things will take because you can easily evolve code over time with little effort.

By the same token, to me it makes sense that since for comprehension already supports value definitions, there's no good reason to prohibit them as the first item. And once you accept that, there's no good reason to require it to be followed by a generator.

Because suppose you're editing a for comprehension and you end up deleting the first generator, which has value definitions after it. As it is, now you may have to suddenly create curly braces around it and move the definitions there and add the val keyword. There's no reason to force that busy work when the meaning is clear.

And if you do that, then by the same token if later you delete the subsequent generator, leaving only value definitions, there's no reason the compiler has to force the busy work of converting all the value definitions to explicit vals.

As an added bonus, there are contexts where using for to define a bunch of bindings without val would make a lot of sense and make the code more readable.

nafg avatar Aug 28 '22 21:08 nafg

Naftoli touches a zombie thread

fommil avatar Sep 06 '22 21:09 fommil

came up again at https://contributors.scala-lang.org/t/pre-sip-comprehensive-function-applications/5902/12

where initial args are precomputed.

som-snytt avatar Sep 07 '22 00:09 som-snytt

closing since this would need to happen in Scala 3 first before we could do it here

SethTisue avatar Oct 17 '23 21:10 SethTisue

Closing because the ticket has 22 thumbs-up, which is the limit for Scala 2.

Since it is an enhancement, not a bug, feature proposals with implementations and backports are always welcome.

som-snytt avatar Oct 18 '23 00:10 som-snytt

https://github.com/scala/improvement-proposals/pull/79 proposes to fix this in Scala 3

SethTisue avatar Feb 20 '24 00:02 SethTisue