Stream: ideas

Topic: List/Str/Box.isUnique


view this post on Zulip Brendan Hansknecht (Jul 13 2022 at 01:13):

Now that we have expect, it could be nice to expose a function that checks whether or not a refcounted value is unique. These function would simply check if the refcount is 1.

The main use case would be to help in avoiding copies in a call stack. If each function is able to ensure that it's inputs are unique and is coded in a way as to not duplicate the inputs, the inputs would always get updated inplace. It would help to defend from accidentally keeping a reference to a value and then getting a copy. This is a very common optimization that I manualy perform when trying to improve benchmarks of roc code.

This would not perfectly defend from accidental copies, but it would be a cheap way to easily debug where a copy is happening and when a value is duplicated. What are people's thoughts on adding a isUnique functions?

As an aside, a makeUnique function should probably also be pair with this addition. That way if you have a list that is not unique, you can still pass it into a call stack that expects a unique list. Otherwise, a call stack could always wait until after the first update of a list to start expecting isUnique. That would make it so that the first update would make the list unique and then it would stay unique as long as the programmer didn't mess up.

view this post on Zulip Richard Feldman (Jul 13 2022 at 01:15):

the first update would make the list unique and then it would stay unique as long as the programmer didn't mess up.

I believe this already happens automatically

view this post on Zulip Richard Feldman (Jul 13 2022 at 01:16):

like all the functions that can mutate in-place will clone (into a clone that's necessarily unique because we just cloned it!) and then perform their operation

view this post on Zulip Brendan Hansknecht (Jul 13 2022 at 01:20):

Yes. I am talking about the case where you want to enable your top level function to accept a non-unique list, but want to make sure you only duplicate it once.

view this post on Zulip Brendan Hansknecht (Jul 13 2022 at 01:21):

So after the first update it will be guarenteed unique due to how Roc works. Then all other uses of the list and functions you call can use expect List.isUnique. They will only crash if you made a bug that duplicated the list by accident. This is more thinking from a library author perspective.

view this post on Zulip Brendan Hansknecht (Jul 13 2022 at 01:23):

As an auther, you probably want to accept a non-unique list, but you may want to ensure that once you have it, you only ever copy it once across all of your functions. So interspersing expect List.isUnique is kinda a defensive measure/a useful debugging tool.

view this post on Zulip Richard Feldman (Jul 13 2022 at 01:54):

yeah I can definitely see it being useful as like a "this is true right now, and I want a test to fail if it ever stops being true" measure

view this post on Zulip Richard Feldman (Jul 13 2022 at 01:55):

and expect is kinda perfect for that because it gets compiled away at runtime, so if there's some code pathway that violates it, but your tests don't catch it, you won't blow up your users' production apps with it; they'll just get more clones than is ideal

view this post on Zulip Brendan Hansknecht (Jul 13 2022 at 02:01):

Exactly!

view this post on Zulip Giovanni Zanandrea (Jul 14 2022 at 15:30):

I don't know what expect does, but I'm assuming it's the equivalent of the assertmacro in C. Please correct me if I'm wrong.

Would the use of isUnique be restricted so that it would only be possible to use it in conjunction with expect? Otherwise it would be possible to use it to write code that is not referentially transparent. I know it's just an academic concern, but the purist in me is a little bit bothered by that...

view this post on Zulip Giovanni Zanandrea (Jul 14 2022 at 15:32):

Is full referential transparency a design goal for ROC, by the way? Or are minor deviations from it considered acceptable?

view this post on Zulip Giovanni Zanandrea (Jul 14 2022 at 15:36):

I'm totally on board with the idea of adding of a makeUnique function. I definitely see why it would be useful, and it wouldn't affect referential transparency in any way

view this post on Zulip Brendan Hansknecht (Jul 14 2022 at 15:45):

Expect is just a debug assert. It is removed in release builds

view this post on Zulip Brendan Hansknecht (Jul 14 2022 at 15:50):

As for referential transparency. That's a good point.

someFunc = \x ->
    if List.isUnique x then
        7
    else
        12

x = [ ...]
a = someFunc x
b = someFunc x

Yep, definitely broken. Dang.....

view this post on Zulip Brendan Hansknecht (Jul 14 2022 at 15:52):

I would be fine with limiting this to being only allowed in an expect. Which still technically breaks referential transparency. First call would panic second would run fine. But it breaks it in an expected way that I would not expect to cause issues.

view this post on Zulip Richard Feldman (Jul 14 2022 at 15:53):

we could make a separate expect-unique keyword

view this post on Zulip Richard Feldman (Jul 14 2022 at 15:54):

full referential transparency is definitely a design invariant for Roc! Has been from day one, and I plan for that to never change. :big_smile:

view this post on Zulip Brendan Hansknecht (Jul 14 2022 at 15:54):

Also, makeUnique should only be added if we also add isUnique or equivalent. It is strictly a pesimization. In fact in release build it could be argued that we should ignore makeUnique like we would with isUnique.


Last updated: Jun 16 2026 at 16:19 UTC