Standard Library: Now open for improvements and suggestions!

I agree it’s better, but as I said, it still feels like too much friction, too much to remember, too much to explain

Maybe I’m exaggerating, but really being able to do the basics with just stdlib in python just feels so smooth

And the standard library is also one of the things that made me love Scala

1 Like

Can we merge mutable.ArrayDeque into mutable.Buffer?

As far as I know, ArrayDeque introduced in Scala 2.13 is basically a superset of Buffer’s functionality, and there is no reason that anyone should use Buffer anymore. ArrayDeque supports all the same APIs efficiently, and more due to allowing efficient operations on the other side.

It should be straightforward to implement all the mutable.Buffer operations using ArrayDeque, and add in the other ArrayDeque operations as well. Since the name mutable.Buffer is the “default” mutable buffer semantically, we should make it do what most people would want, rather than forcing them to reach for the more verbose ArrayDeque sometimes but not other times.

This would streamline usage of mutable.Buffer/mutable.ArrayDeque, and remove a stumbling block of having to choose which one to use when there really is one right answer and the obvious answer is wrong

6 Likes

My wishlist for a stdlib addition is two-fold.

Firstly, having a ++ for Vector that isn’t O(n) would be amazing (I believe it’s still not the case?)

Secondly, I’d love to see scala.collection.mutable.TrieMap/Set and scala.collection.immutable.TrieMap/Set as a specialisation of Map[String, _] or Set[String] perhaps acting as SortedMap if appropriate, and with suffixes, as these structures are also classically suffix-trees. I often find myself longing for a good Trie, and while there is a concurrent one, that seems totally overkill for non-concurrent workloads.

I think there is still a missing Factory for IArray too, iirc, which would be nice to have for consistency.

The last improvement merged was https://github.com/scala/scala/pull/10159 from 2023 (for Scala 2.13.11)

That PR says “the time needed [is now] O(min(m,n))”.

But I see that the PR author wrote: “There is still the possibility to introduce some form of heterogeneous structure that allows O(log(n)) concatenation also for misaligned Vectors. I’m currently experimenting with this, and it looks promising, but it’s definitely not possible without some tradeoffs in (random) access times, at least for large Vectors that were obtained by concatenating many misaligned medium-sized Vectors.”

So it looks like that’s where things stand.

1 Like

in a typical situation where you are using ++ alot on sequences, do you also need random access?

What are the tradeoffs of making a sequence that is very fast concat (i.e. a tree structure of arrays) - ok iteration is still pretty fast, but then do people want fast views/slices/random access.

how can we make a good survey of typical patterns for collections usage

One thing that I was discussing now at work. Would there be any interest in a comment macro?

extension (inline x: Any) inline def comment: Unit = ()

I believe this is similar to Clojure’s comment macro. While I wrote this as an extension, it works well as a non-extension method as well.

It might seem kind of useless in a language with block comments, but it does have some advantages:

  1. The code inside the comment block is still type checked, which can be quite nice for examples that shouldn’t run
  2. In the same way, scalafmt will keep the code formatted
  3. It let’s one quickly comment/uncomment blocks of code, while also allowing the comment block to be edited.
4 Likes

it would be quite easy for nullable types also, e.g.

(it may have drawbacks, but works for me)

given [T: ToExpr as toExpr] => ToExpr[T | Null]:
  def apply(x: T | Null)(using Quotes): Expr[T | Null] = x match
    case null => '{ null }
    case value => toExpr.apply(value.asInstanceOf[T])

given [T: FromExpr as fromExpr] => FromExpr[T | Null]:
  def unapply(x: Expr[T | Null])(using Quotes): Option[T | Null] = x match
    case '{ $_ : Null } => Some(null)
    case value => fromExpr.unapply(value.asInstanceOf[Expr[T]])

Not sure if people are misunderstanding or I’m just misreading comments here butmutable.ArrayDeque is not an alternative to mutable.Buffer. Buffer is the abstract data structure (ADS), similar to how Map,Set,Seq are ADSs, and ArrayDeque is an implementation of that ADS. There are also other implementations of Buffer such as m.ListBuffer, m.Queue, etc.

And in fact ArrayDeque is already the default implementation of Buffer, so the factory method Buffer(1,2,3) et al just return ArrayDeque’s at runtime.

2 Likes

they return ArrayBuffer actually

3 Likes

Sorry yes you’re right.

1 Like

I’d like to have very simple but semantically useful classes like pekko/actor/src/main/scala/org/apache/pekko/Done.scala at main · apache/pekko · GitHub and pekko/actor/src/main/scala/org/apache/pekko/NotUsed.scala at main · apache/pekko · GitHub in the stdlib. They are way more descriptive than just using Unit for multitude of unrelated purposes. Overloading the meaning of Unit is in some ways analogous to overloading the meaning of _ or implicit in Scala 2.

5 Likes

Meta: maybe start to collect tickets with patches somewhere.

few thins which come to mind at first:

  • BigInt has no unapply.
  • Somethings for App and Monad will be helpfull
  • ~Exists scala.concurrent.Channel, which is not a channel, and disallows wildcard import of scala.concurrent.* with nearly every user-level library for concurrent primitives.
2 Likes

It’s not obvious whether a given stdlib change should have a ticket (that references the contributors thread).

I would favor having a github issue as the canonical locus where it is agreed what is to be done, perhaps merely summarizing the forum. A PR is subject to ancillary discussions such as, “That test is flaky.”

In particular, a ticket can have a disposition such as “won’t fix”, whereas a forum thread is only a discussion. Issues are also easier to search.

Also, IMHO the use case for ArrayBuffer is that the user intended ArrayBuilder to build an array or ArrayDeque otherwise. OTOH, I’m not sure I signed up to bloat Buffer, which is defined as “a growable and shrinkable Seq ”. Where does that get discussed?

1 Like

For convenience, I would like a version of PPrint to exist in the standard library.

This is one of these cases which is super useful for quick debugging, but it’s annoying to add a dependency just for that, and in libraries and such one might not want to have it as a dependency permanently.

8 Likes

How about JSON parser, similar to scala-xml?

2 Likes

Without having put too much thought on the issue, I think I’m against a JSON library in the stdlib… I think that’s the kind of stuff that’s better handled at the toolkit level.

There are already a bunch of good Scala JSON libraries, and they’ve evolved quite quickly over the years (at least compared to a more static library, like the stdlib).

So I think it doesn’t make much sense to have one in the stdlib that’s just going to be a slightly worse JSON library that everyone uses because it’s the default.

(I don’t have strong feelings against it being only in toolkit or there being an official module like scala-xml).

6 Likes

I would like to see |> added to the stdlib - no imports required, using infix symbolic, and inlined for no performance cost.

I already personally add it to every project I start on, and I’m sure I’m not the only one. It’s one of the things I miss coming from other fp languages.

2 Likes

There’s a lot of value already captured in those existing repos. Please make sure they are thoroughly reviewed, as many ideas are queued there awaiting an initiative like this.

4 Likes

do you also mostly use top-level functions (i.e not infix)

I often use top-level functions over methods, especially when I’m working with built-in types other than classes and I’m describing transformations. Idiomatic Scala overall might tend towards a more oop style, but I still think this operator is a staple in the traditional functional programming world and should be available for when you want to use it, even if that’s not all the time.

2 Likes