wren-lang / wren

The Wren Programming Language. Wren is a small, fast, class-based concurrent scripting language.
http://wren.io
MIT License
6.93k stars 554 forks source link

Support equality operators with lists #606

Open MageJohn opened 6 years ago

MageJohn commented 6 years ago

Currently the code [1,2] == [1,2] returns false. I can't find anything in the documentation as to why this would be. Equality on lists should really be supported.

mhermier commented 6 years ago

Because as this, it does object instance comparison. Code is missing for the support.

minirop commented 6 years ago

I'll add that the culprit is wrenValuesEqual in wren_value.c: https://github.com/munificent/wren/blob/master/src/vm/wren_value.c#L1275-L1313

MageJohn commented 6 years ago

Maybe if it can't test for equality it should raise an exception. It could lead to some difficult to find bugs if people assume that they can test the equality of two lists, but find that their code doesn't do what they expect; things shouldn't fail silently, unless we make it explicit.

avivbeeri commented 6 years ago

I suppose it depends on the intended semantics, but the current behaviour doesn't bother me. Each list is a different object in the heap so I wouldn't consider them to be the same object, even if their contents is "equal".

I would expect the following to print true though.

var a = [1 ,2]
System.print(a == a)

To do as this issue suggests, equality operations would have to do deep inspection of the whole list contents (adding to the operational complexity). Would the same semantics extend to maps? What about deeply-nested lists?

mhermier commented 6 years ago

Well to me == is the good place. There is some same object function (i would prefer === but that is another subject) that has the same object sementic.

I have a whole new branch, that need still a lot love, but I added <=> aka starts his operator, that is an even better solution to the list equality question.

ruby0x1 commented 6 years ago

I'm also not a fan of deep/expensive operations on syntax level. As mentioned above, you also have to account for recursion, you can make a cycle trivially with lists and now == has undefined behaviour, or behaviour that is difficult to define with reasonable expectations.

There are functions though! We don't need to overload syntax for operations on values when functions are a unit of work.

List (or maybe even Sequence) can offer a function like equivalent or equals that does this, and allows more nuance and error handling. i.e list.equals(other).

MageJohn commented 6 years ago

Isn't == an overloadable operator? The equality of two lists could be added as a method to the List class.

mhermier commented 6 years ago

All methods can be overloaded, even the critical ones (if there is any). There is no real check in the compiler for that.

bjorn commented 6 years ago

Currently the code [1,2] == [1,2] returns false. I can't find anything in the documentation as to why this would be. Equality on lists should really be supported.

Are there any other scripting languages where a simple equality test of lists does a deep comparison? I think it's really uncommon at best, due to problems mentioned by @underscorediscovery.

Of course we know it from C++, but values are not pointers there unless written so explicitly, so it's clear when you do a pointer comparison or a deep comparison.

mhermier commented 6 years ago

I think most language does collection equality using the real equality operator. The nuance is that here == is the real equality, while same(_) is the simple test.

avivbeeri commented 6 years ago

Quick aside: It looks like the terms for what we are discussing are "physical" and "structural" equality. Wren's current == operator checks physical equality, as does the Object.same(_,_) static method.

An operator for testing structural equality might be useful, but it shouldn't replace the existing semantics of ==.

mhermier commented 6 years ago

I disagree with that, for me as == is a structural equality, it is expected to be expensive and slow, and defaults to physical equality which is dumb simple and fast.

bjorn commented 6 years ago

I think most language does collection equality using the real equality operator.

It doesn't do this in Java, C#, Lua and JavaScript. Neither does it work like that in C++ or C if you're dealing with pointers (which is essentially what Wren object handles are).

I just found Python and Ruby do a deep comparison, but Python provides "is" for identify comparison and Ruby provides "equal?" for that. I think especially Ruby is pretty confusing here with their naming.

In any case I think it's not easy to say what "most languages" do, and by extension it's not easy to say what == is expected to do, since this would mostly depend on what the coder is familiar with.

mhermier commented 6 years ago

It all depends on what you consider to be the source of equality. For me in java, .equals() seems to be for me a better source of equality than == since it can be overloaded.

If all is a question of having a physical and structural equality, for me === and == are the ideal candidates it is only a question to have them as operators. This relate to the fact that I'm a big fan of the <=> operator. That would make 3 operators of 3 symbols (===, !==, <=>).

buckle2000 commented 4 years ago

I feel like there is already is operator for reference equality.