Skip to content

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fewerBraces: allow partial function arguments without : #17731

Closed
sjrd opened this issue May 2, 2022 · 5 comments
Closed

fewerBraces: allow partial function arguments without : #17731

sjrd opened this issue May 2, 2022 · 5 comments

Comments

@sjrd
Copy link
Member

sjrd commented May 2, 2022

It is quite common to pass anonymous partial function to higher-order functions (whether they take a PartialFunction or a regular Function1). In that case, there is no explicit parameter to the lambda, which requires the use of : for the fewerBraces mechanism to kick in:

object Test {
  def main(args: Array[String]): Unit =
    val xs = List((1, "hello"), (true, "bar"), (false, "foo"))
    val ys = xs.collect:
      case (b: Boolean, s) if b => s
    println(ys)
}

I suggest that we infer the : in that situation, so that we could write instead:

object Test {
  def main(args: Array[String]): Unit =
    val xs = List((1, "hello"), (true, "bar"), (false, "foo"))
    val ys = xs.collect // note: no ':' here
      case (b: Boolean, s) if b => s
    println(ys)
}

Currently, the above fails to parse:

-- [E040] Syntax Error: tests/run/hello.scala:5:6 ------------------------------
5 |      case (b: Boolean, s) if b => s
  |      ^^^^
  |      unindent expected, but 'case' found
-- [E040] Syntax Error: tests/run/hello.scala:7:0 ------------------------------
7 |}
  |^
  |'}' expected, but unindent found
-- [E006] Not Found Error: tests/run/hello.scala:6:12 --------------------------
6 |    println(ys)
  |            ^^
  |            Not found: ys
  |
  | longer explanation available when compiling with `-explain`
3 errors found
@odersky
Copy link
Contributor

odersky commented Jul 21, 2022

I's a difficult tradeoff between conciseness and consistency. I would leave it out of the first version of fewerBraces. We can always add it later.

@alexandru
Copy link

If you care for a random personal anecdote … I'm teaching my son and my nephew Python, both teens, and the syntax has been a big roadblock. I also don't have teaching experience, so it caught me off guard, especially since I thought Python was easy to understand for beginners. A point of confusion, besides the perennial misunderstanding of the evaluation model, is the syntax for code blocks. They have been confused about where blocks of code should be.

And having a consistent rule like “a block of code must follow a : char, always” helps a lot because they can rote learn such rules. Skipping over the fact that teens have no appreciation for whitespace or its proper use, this is where Python is more consistent than curly braced languages, since an if, while, for, and other statements always end with a : char. Whereas in C-family languages, the curly braces are optional if the block of code is made of a single expression.

I think that consistency helps when learning languages, I think that's because it helps us to recognize patterns that we can later reuse in other instances, which is why exceptions to rules are bad for the learning process. And the ideal would be to see how students struggle to learn a syntax before adopting it. YMMV.

@odersky
Copy link
Contributor

odersky commented May 26, 2023

@alexandru It's not that this has not been studied. See for instance http://okasaki.blogspot.com/2008/02/in-praise-of-mandatory-indentation-for.html. But yes, YMMV, I don't think it's possible to get consensus on this.

@alexandru
Copy link

alexandru commented May 27, 2023

@alexandru It's not that this has not been studied. See for instance http://okasaki.blogspot.com/2008/02/in-praise-of-mandatory-indentation-for.html. But yes, YMMV, I don't think it's possible to get consensus on this.

Thanks for the link by Chris Okasaki.

Here I was thinking about the issue at hand: having cases in which : can be avoided in place of a {} block, and having it as optional. I was saying that I appreciate Python's consistency in this regard. Avoiding the overloading of syntax or the complexity of remembering when indentation is significant, were AFAIK among the reasons for why multi-line anonymous functions did not make it in Python (a relevant link).

Similar cases already exist. For example, in a for {} yield {}, it's just for\n, and not for:\n. A case can be made that for is special and that the curly braces don't introduce a lexical block of code (as the for introduces a lexical scope on each <-). I also noticed that adding : after for doesn't work, so it's not optional. Which is good.

Based on this example, one could also make the case that the syntax for anonymous partial function is similar. Each of the cases introduces a scope, and this is different from a block of code passed as a parameter to a normal function. However, one can also make the case that partial functions are confusing as a concept, and that missing the : may lead to more confusion, and has to be carefully considered. Especially because we can't get rid of the :, due to how code can change:

// (1)
list.map: x =>
  x match:
    case Odd => 1
    case Even => 0

// (2) can be refactored to
list.map:
  case Odd => 1
  case Even => 0

// (3) versus
list.map
  case Odd => 1
  case Even => 0

Requiring sample no. 3 and banning sample 2 would be confusing. So, this issue talks about having : as optional. I don't think having : as an optional char helps, with teaching or otherwise. Just an opinion from limited experience.

@odersky
Copy link
Contributor

odersky commented May 27, 2023

Yes, that's a good point. I also think we should avoid making : optional.

@ckipp01 ckipp01 transferred this issue from lampepfl/dotty-feature-requests May 31, 2023
@scala scala locked and limited conversation to collaborators May 31, 2023
@ckipp01 ckipp01 converted this issue into discussion #17732 May 31, 2023

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants