Skip to content
This repository has been archived by the owner on Dec 22, 2021. It is now read-only.

[WIP] Add immutable array vc #16

Closed
wants to merge 3 commits into from

Conversation

odersky
Copy link
Contributor

@odersky odersky commented Jan 16, 2017

This is an attempt to add immutable arrays as value classes over normal arrays. So far, this compiles only in dotty under PR #1906, but there is an ongoing discussion about its validity.

It should also be noted that the arrays defined here don't have an immutability guarantee. It's just that they don't offer mutation operations themselves. So, maybe they should rather be a collection.Array instead of a collection.immutable.Array.

 - Split GrowableSeq from Seq
 - Make everything compilable with -Yno-imports under both dotc and scalac.
This is an attempt to make immutable array a value class which has the
same representation as the underlying mutable array.

This is currently a WIP. It compiles only under dotty with PR #1906 added.
To get it to compile under scalac, we need to fix SI-10150.
@dwijnand
Copy link
Member

I would call this is an "unmodifiable array" rather than an "immutable array", and definitely not put it in the immutable package.

Copy link
Contributor

@julienrf julienrf left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After discussing with @densh, I think it might be interesting to bring efficient head/tail decomposition to immutable.Array by additionally storing the actual start and end indices to use of the underlying array. This way, tail could be implemented like this: def tail = if (isEmpty) throw Unsupported else new immutable.Array(underlying, start + 1, end). But that would be incompatible with a value class… What do you think of this idea, though?

Also, I think we could have more efficient implementations of map and some other methods of Array because we often know in advance the size of the resulting collection (so, we don’t need to go through a growing buffer). But, I definitely have to push a benchmark to check that…

implicit def arrayToArrayOps[A](as: Array[A]): ArrayOps[A] = new ArrayOps[A](as)

implicit def immutableArrayToArrayOps[A](as: immutable.Array[A]): immutable.ArrayOps[A] = new immutable.ArrayOps[A](as)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need to go through an implicit conversion here rather than making immutable.Array extend immutable.ArrayOps?

@sjrd
Copy link
Member

sjrd commented Jan 16, 2017

The efficient head/tail decomposition is only possible if it is truly an immutable array (not a read-only view of an array).

IMO we need both truly immutable array (in collection.immutable) and an efficient read-only view of an array (in collection). The former is not that inefficient either. Only the first "wrapping" from an array needs copying. Subsequent operations do not need more copying than the read-only view version.

@odersky
Copy link
Contributor Author

odersky commented Jan 16, 2017

The discussion in scala/scala3#1905 shows that things are not so simple. We would have to await major implementation changes for value classes to make this approach work.

If we do not insist that immutable arrays have the same representation as mutable ones, then
I believe the existing ArrayView is already pretty good, and has the advantage of simplicity. Like the current PR there's no guarantee of immutability, but the view itself is readonly.

@odersky odersky closed this Jan 16, 2017
@odersky
Copy link
Contributor Author

odersky commented Jan 16, 2017

After discussing with @densh, I think it might be interesting to bring efficient head/tail decomposition to immutable.Array by additionally storing the actual start and end indices to use of the underlying array. This way, tail could be implemented like this: def tail = if (isEmpty) throw Unsupported else new immutable.Array(underlying, start + 1, end). But that would be incompatible with a value class… What do you think of this idea, though?

I think this a great idea, but I would look at ArrayView as the right basis to do this.

@odersky
Copy link
Contributor Author

odersky commented Jan 17, 2017

In fact ArrayView already supports efficient head and tail since it is an IndexedView.

@szeiger
Copy link
Contributor

szeiger commented Jan 17, 2017

ArrayView in master doesn't have efficient tail. It only wraps an array without an extra start index and length. ArrayBufferView has those. I see no reason why we would want to keep a separate ArrayView. In #2 I unified them.

@odersky odersky mentioned this pull request Jan 22, 2017
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants