Skip to content
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

[WIP] Immutable ordered finite maps and sets #561

Draft
wants to merge 15 commits into
base: master
Choose a base branch
from

Conversation

jiribenes
Copy link
Contributor

@jiribenes jiribenes commented Aug 30, 2024

I've been sitting on this code for almost 9 months now, it's about time we finalise it.
This PR adds immutable ordered maps and sets based on BB[α]-trees into the standard library.

Important caveat: These structures work only on the JS backend because it's the only one with a generic comparison primitive (#394).

Note that it might take a while before I'm happy with this code, I just want to put it out here in case someone wants to help out / to prevent somebody else from spending too much time on reimplementing this.

TODO:

  • add unit tests for the map
  • add unit tests for the set
  • add unit tests for the shift operators
  • add a few more complex functional tests
  • fix TODOs in code
  • improve the docs
  • use /// for doc strings
  • improve the function names (insert in Set vs put/add in Map?)
  • add intersection!
  • check that the via combinators in Set actually inline

@jiribenes jiribenes changed the title Immutable ordered maps and sets Immutable ordered finite maps and sets Aug 30, 2024
// Check if set `s` is empty.
//
// O(1)
def isEmpty[A](s: Set[A]): Bool = {
Copy link
Member

Choose a reason for hiding this comment

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

maybe we could use empty? here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks!
In general, feel free to suggest better names everywhere, I really just took the first idea I had every time :)

Copy link
Collaborator

Choose a reason for hiding this comment

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

We should do this change consistently across the stdlib, if we decide for it

@@ -0,0 +1,714 @@
module map
Copy link
Contributor Author

Choose a reason for hiding this comment

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

In #488, we agreed to use constructors like $collection_name for array, ref, and bytes. For example:

// Creates a new Array of size `size` filled with the value `init`
extern global def array[T](size: Int, init: T): Array[T]
 
// Allocates new bytes with the given `capacity`, setting its values to `0`.
extern io def bytes(capacity: Int): Bytes

// Creates a new reference with the initial value `init`.
extern global def ref[T](init: T): Ref[T]

There are two main ways to make a map / set:

  • empty map/set
  • map/set created from a (possibly unordered) list

Does the convention mention above apply anywhere here? Personally, I'd always use these namespaced: map::empty() and map::fromList([...]), but I'm interested in what y'all think.

Comment on lines 5 to 6
// Ordered finite set, backed by a `Map`.
record Set[A](internal: Map[A, Unit])
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Here's a place where newtypes would be nice: I never want to leak the type Map[A, Unit] outside, otherwise type Set[A] = Map[A, Unit] would do. But packing it into a record might have some unpleasant consequences when benchmarking. Any ideas?

Copy link
Collaborator

Choose a reason for hiding this comment

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

You can use extern type Set[A] with identity coercions, but that might get into the way of optimizations.

@jiribenes jiribenes changed the title Immutable ordered finite maps and sets [WIP] Immutable ordered finite maps and sets Aug 30, 2024
@jiribenes jiribenes force-pushed the master branch 3 times, most recently from ee9d209 to 58c8510 Compare October 1, 2024 18:11
@jiribenes jiribenes force-pushed the feature/stdlib/treemap-treeset branch from 3890ddd to 889c0f8 Compare October 2, 2024 16:05
@jiribenes
Copy link
Contributor Author

Rebased on current master.

@jiribenes
Copy link
Contributor Author

Blocked on #629, I'll fix it there and then rebase. :)

jiribenes added a commit that referenced this pull request Oct 2, 2024
Cherry-picked from #561: adds arithmetic right shifts and a comprehensive test suite.
@jiribenes jiribenes force-pushed the feature/stdlib/treemap-treeset branch from ef7d4a2 to 498b95f Compare October 4, 2024 09:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants