Dotty Language Survey Results

This fall we ran our functional programming course with 250 students using Dotty / Scala 3 as the teaching language. Students were typically in the 2nd year of the Bachelor after having seen Java in the 1st year. In the final lecture we did a survey where we got student’s responses to some questions about the language. We presented question slides and observed the responses which were by show-of-hands. We also collected individual comments on each question.

Here are the survey questions with the feedback we got.

13 Likes

None of the results feel at all surprising to me, but it is much better to have data than hunches!

Do you have results from other courses where implicits were taught that may shed light on given vs. implicit? It could be that givens are an inherently complex topic, and thus hard to grok (but worth it when you get it). Or it could be that some aspects of the change have made it superficially hard to grok and those could be fixed (at least back to the level of implicits).

6 Likes

Can we have a survey from more general public, preferably experienced Scala programmers? Or is dotty just targetting new learners?

5 Likes

I agree the more data the better, but let’s not forget that in software, the only way to know for sure is once the target audience is actually using it. This is a lesson that the software industry has learned countless times. I would imagine Microsoft had tons of data that suggested to them that Window 8’s design was a good one. The problem is they didn’t have the other data…

Just to be extra clear: I’m not trying to predict doom. I’m saying we can’t know the future, period. Managing software releases is all about risk management.

I think the recent blog post is wonderful news. It means we can expose much greater numbers of people to Dotty in a gradual, organic way, even before we cut a final, leaving the potential for continuing to iterate as necessary until it’s ready to be cemented.

(It’s wonderful news for other reasons too, but that’s the one that pertains to this.)

5 Likes

So glad you took the time to collect that data Martin. I plan to start updating my textbooks to Scala 3 this year. It is good to have information on areas that might need to be emphasized. Since we use Scala in CS1 there won’t be as many issues of students wanting something from a previous language. The aspect covered in these questions that I think will have the biggest impact on my teaching is not requiring the use of new to create an instance. Knowing when they do and don’t need new is tricky for students who aren’t ready to dig into the API to see if the companion object has an apply method or not.

4 Likes

I also was surprised that a significant minority of students found it hard to drop new. I would have expected that to be less of a problem. Coming from Java does make a difference here.

That seems very likely. I suspect the dislike of indentation-blocks stems from the same reason; if they had spent the last semester doing Python, I’d expect both dropping-new and indentation-blocks would be second nature.

2 Likes

You are almost certain right about this. I personally have a bias against significant white space, but I know that so much of what we like and don’t like is based on our previous experience. I remember when I first learned Scala I bristled at things like switching <> to [] and indexing arrays with () instead of []. That was because at first it just felt like they had picked those things for no reason other than being different. As soon as I realized that collections are functions, including arrays, the move to indexing with () immediately made sense. Indeed, now I can’t see what other languages chose to use [] and make arrays somehow different from other functions.

3 Likes

Well, the reason why most languages treat arrays special is because they are special. Consider:


Welcome to Scala 2.13.1 (OpenJDK 64-Bit Server VM, Java 1.8.0_232).
Type in expressions for evaluation. Or try :help.

> classOf[Array[String]] == classOf[Array[Int]]
res0: Boolean = false

> classOf[List[String]] == classOf[List[Int]]
res1: Boolean = true

For proponents of significant whitespace, I have this challenge, which I posted before, but got no answer. How would this look like with significant whitespace:


def combine3(s1: String)(s2: String)(s3: String): String = s"$s1\n$s2\n$3"
 
  val combined = combine3 {
    "Hello, World"
  }{
    "How are you doing?"
  }{
    "Nice weather!"
  }
2 Likes

For higher-level languages, yes, the divergence seems odd. For lower level languages, in which the boundary between array and pointer is fuzzy, the distinction does make sense as it’s a fundamentally different operation.

This wouldn’t surprise me one bit. If you’ve never been free of the tedium of manually managing your indentation, going from having to mentally keep track of types and manually fiddle with indentation in Python, to Dotty where the compiler helps keep track of types and you have to manually fiddle with indentation is an unqualified improvement.

On the other hand, if you are coming from Scala and are already used to the compiler helping you keep track of types and a formatter managing your indentation, switching to Dotty just means something that wasn’t a problem is now something you need to keep track of (because, honestly, the tooling around significant whitespace is severely lacking).

The answer is: exactly like that. Significant whitespace doesn’t currently handle method invocations, and I’ve found that it’s occasionally needed to make pattern matching compile, so it’s unpleasantly inconsistent.

Unfortunately, for all that its pretty to look at, I’ve found it extremely tedious to work with and the tooling insufficient to the task. While that may change, given Python’s popularity hasn’t produced reasonable tooling yet, I doubt Scala 3 adopting it will suddenly spur innovation in this area.

1 Like

Significant indentation doesn’t currently handle multi-line method invocation. Thought so. Will it ever? Don’t think so.

To make this as clear as possible:

No one has presented a proposal for replacing all the brackets with significant indentation. Instead, the only existing proposal is to replace the brackets with a complex mix of brackets and significant indentation. Nothing like Python.

3 Likes

I’ve got to say that I find the ability to omit braces quite nice. It just feels very natural, given that braces are already optional in many places (after def ... =, after if/else, etc.) under some special circumstances. I like the idea of making this bracket-elision possibility more general.

For instance, I was looking at this code and found it nice to read:

private object StringRewriter extends util.ExprMap {

  def transform[T](e: Expr[T])(given QuoteContext, Type[T]): Expr[T] = e match
    case '{ ($x: Foo).x } =>
      '{ new Foo(4).x } match case '{ $e: T } => e
    case _ =>
      transformChildren(e)

}
2 Likes

Being able to omit brackets around a single expression is something completely different from being able to replace brackets by significant indentation.

6 Likes

Though the mechanism is very different, I would say it has the result of looking like a natural generalization most of the time. Since most code is already well-indented anyways.

2 Likes

Here’s one proposal I have made before:

combine3
    "Hello, World"
do
    "How are you doing?"
do
    "Nice weather!"

Essentially, do can be our generic “start an indentation-based block” keyword

At least in my experience, code is already well-indented anyway because of git hooks and scalafmt, not because people enjoy the tedious process of managing their indentation manually.

3 Likes

The biggest weakness of this approach is that it’s adapted from statement-oriented languages, and it shows. In particular, as someone who works in shell scripts on a regular basis, this looks like 3 statements, rather than a single expression.

For what it’s worth, Ruby has very similar block syntax, and has decided that chained blocks are always ugly

3 Likes

I agree that dropping new is a pain mostly only if you come from Java, but I don’t think it’s the same with indentation-blocks. I know of many experienced Python programmers who dislike it. I think it really is a matter of opinion, regardless of which language you’re used to.

4 Likes

Significant White Space has already caused problems in Scala 2. Is there yet a clear specification of what terminates a statement and what doesn’t? We were sold the delusion that dropping the requirement for semi colon terminators would be cost free. Of course it wasn’t. Maybe some people had a coding style that meant they never had to mess about with the ugly fix of hanging operators.

I’m extremely sceptical of any claims that these further significant White space innovations will not prove to have a significant cost down the road as well. Some things I happy to take on trust. I’m happy to take the DOT calculus on trust. If the DOT calculus says that certain Types are unsound, I’m happy to trust those that have spent the time studying these matters. However as far as I’m aware the DOT calculus says nothing about syntactic soundness.

1 Like

If your pitch is “semicolon inference was bad and this is worse”, you may find you’ve already lost most of your audience before you’ve even reached the second clause. I don’t share your dim view of semicolon inference in Scala. I think it’s awesome, and my impression is that most Scala programmers feel the same way.

And yes, I’m well aware that semicolon inference ended up needing a couple of adjustments. It didn’t mix well with language.postfixOps, so we got rid of that. And re: hanging operators, it never bothered me that much, but also, it’s already fixed in Dotty. Consider the following program:

  val x = 2
    + 3
  println(x)

in Scala 2, this warns (“warning: a pure expression does nothing in statement position; multiline expressions may require enclosing parentheses”) and prints 2. But in Dotty, it prints 5, as expected.

8 Likes