Hi, lets say I have list1 := Str["a", "b", "c"] and list2 := Obj["a", "b", "c"].
If in my system, I want to treat those as equals (comparing the inner items instead of the List type), what is the best way to do this?
list1 == list2, list1 === list2, and list1.equals(list2) will of course return false. How do I do this without iterating all the items?
SlimerDudeThu 26 Jul 2012
I'm not sure why you'd ever have the same list declared as different types but...
The two lists are different because they are declared with a different type (see sys::List#of) which is read only. So the only way I can think of is creating new lists with a common type and comparing those...
list1.map |o->Obj| { o } == list2.map |o->Obj| { o }
How do I do this without iterating all the items?
Well someone, somewhere would have to iterate over the items! :)
heliumThu 26 Jul 2012
You can't do that without iterating over the items.
brianThu 26 Jul 2012
There is no built-in method to compare list items without taking type into account. Although I believe it has been discussed before with varying levels of support and dissent
ikhwanhayatThu 26 Jul 2012
I'm not sure why you'd ever have the same list declared as different types but...
It's not actually declared like that, I'm making it simple for the sake of asking. What I have is a method accepting a generic Obj?[] and the comparison is done in there.
Because the lack of method overloading, I found myself always using Obj? as the argument and then do type checking in the method body to do different things. Is this the right way to do stuff in Fantom?
Well someone, somewhere would have to iterate over the items! :)
I sure hope it's not me :D
Thanks for replies guys...
SlimerDudeThu 26 Jul 2012
using Obj? as the argument and then do type checking in the method body to do different things
Err, that sounds orrible!
As they do different things, can you not break it out into different methods with different names?
And I'd avoid the null type (Obj?) as much as possible unless you really have to. One of the things I like about Fantom is that my objs are usually guaranteed not to be null.
ikhwanhayatThu 26 Jul 2012
As they do different things, can you not break it out into different methods with different names?
API looks cleaner with method overloading. Let say I have a method that accepts a type, and then I want another one that do the same thing but accepts the type name instead. So basically in Fantom I accepts an Obj then check whether its a Type or an Str.
I'm thinking that maybe Fantom is pushing us to achieve polymorphism via classes instead of methods.
SlimerDudeThu 26 Jul 2012
See Method Overloading for a quick explanation of why Fantom doesn't allow it.
My favourite comment is: (!)
I personally think that no methods/fields overloading is one of the best feature of Fan :)
SlimerDudeFri 27 Jul 2012
When I first moved to Fantom I felt the lack of method overloading a little restrictive, but since I started using Fantom properly, I've barely noticed.
Convention (or an easy way out) is to add the type sig to the method name. e.g. from sys::Int don't have:
I've read those posts in this forum and agree that no method overloading makes it simpler, like when working with reflections (which I also seem to use a lot in Fantom). Also, when you have default/named parameters you don't really need method overloading. I guess the pro is more than the cons.
I think it would be really good if there's a guide for this kind of things, like how you do it in Fantom when usually you do it with method overloading in other languages. Also for generics, null checking, etc. Some kind of recipes or cookbook.
brianFri 27 Jul 2012
To get back to the original issue, would everybody like to see something like a a new method on List for:
Bool valsEqual(List that)
Yeah or nay or other ideas?
AkcelistoFri 27 Jul 2012
No matter. I never compare lists.
SlimerDudeFri 27 Jul 2012
How about a method that returns a new List backed by a new type? That would allow you to up or downcast every item in the list then you could do l1 == l2 as usuall.
ikhwanhayatFri 27 Jul 2012
Yes, obviously :)
ikhwanhayatFri 27 Jul 2012
How about a method that returns a new List backed by a new type? That would allow you to up or downcast every item in the list then you could do l1 == l2 as usuall.
Wouldn't that take much more from performance compared to comparing items 1 by 1?
SlimerDudeSat 28 Jul 2012
I was thinking of a method such as
List.toTypeOf(Type typeOf) throws CastErr
which returns a new list of a different type which in your example would allow you to do:
list1.toTypeOf(Str#) == list2.toTypeOf(Str#)
Not that I think I'd ever have use for it.
Though, to be honest, I'd be happy with the List.equals only checking the contents of the List so we don't have to think / bother with this List.typeOf stuff. I can't remember a time when I've been concerned about the List impl. I see a list as a transparent wrapper caring only about what it contains.
Although I believe it has been discussed before with varying levels of support and dissent
Hmm, I'd be interested to find out what the objections were.
brianSat 28 Jul 2012
which returns a new list of a different type which in your example would allow you to do:
That is already pretty trivial like this (and probably maybe even a little more readable to show intent):
foo := Str[,].addAll(oldList)
Though, to be honest, I'd be happy with the List.equals only checking the contents of the List
I think most people would consider type to be an inherit quality to identity and equality. For example Str[,] really is not the same thing as Int[,] and they will behave quite differently when you go to add stuff.
Hmm, I'd be interested to find out what the objections were.
I don't think this has even bothered me in normal code. Where it gets a bit annoying is testing code. But the basic idea was that if you are actually writing a test case, you should be checking the list type to make sure you aren't returning a Obj[] when you should have been returning a Foo[].
SlimerDudeSat 28 Jul 2012
foo := Str[,].addAll(oldList)
Nice one.
most people would consider type to be an inherit quality to identity and equality
I did quibble with this myself, but then realised I've never cared about the List type, namely because...
example Str[,] is not the same as Int[,] and will behave quite differently
...it's all picked up by the compiler.
Meanwhile, I (myslef) am non-plussed about a Bool valsEqual(List that) for I can't see me using it. And a :
Str[,].addAll(list1) == Str[,].addAll(list2)
would suffice should I ever need to.
ikhwanhayatSat 28 Jul 2012
I just noticed something.
fansh> a := Obj["1","2"]
[1, 2]
fansh> b := Str["1","2"]
[1, 2]
fansh> a == b
false
fansh> a.hash == b.hash
true
So in List's case, equality doesn't means the hashes are equal.
Also if valsEqual(List other) is to be implemented, it can just be a wrapper around this.hash == other.hash right?
SlimerDudeSat 28 Jul 2012
Err no. Because you're comparing hashes, not Obj contents. Although very unlikely, hashes (by their very nature) are not guaranteed to be unique. They only exist to help hashtables.
From Java's Object#hashcode JavaDoc:
It is not required that if two objects are unequal according to the java.lang.Object#equals(java.lang.Object) method, then calling the hashCode method on each of the two objects must produce distinct integer results. However, the programmer should be aware that producing distinct integer results for unequal objects may improve the performance of hashtables.
At most a hash is just a checksum - it doesn't guarantee uniqueness.
ikhwanhayat Wed 25 Jul 2012
Hi, lets say I have
list1 := Str["a", "b", "c"]
andlist2 := Obj["a", "b", "c"]
.If in my system, I want to treat those as equals (comparing the inner items instead of the List type), what is the best way to do this?
list1 == list2
,list1 === list2
, andlist1.equals(list2)
will of course return false. How do I do this without iterating all the items?SlimerDude Thu 26 Jul 2012
I'm not sure why you'd ever have the same list declared as different types but...
The two lists are different because they are declared with a different type (see sys::List#of) which is read only. So the only way I can think of is creating new lists with a common type and comparing those...
Well someone, somewhere would have to iterate over the items! :)
helium Thu 26 Jul 2012
You can't do that without iterating over the items.
brian Thu 26 Jul 2012
There is no built-in method to compare list items without taking type into account. Although I believe it has been discussed before with varying levels of support and dissent
ikhwanhayat Thu 26 Jul 2012
It's not actually declared like that, I'm making it simple for the sake of asking. What I have is a method accepting a generic
Obj?[]
and the comparison is done in there.Because the lack of method overloading, I found myself always using Obj? as the argument and then do type checking in the method body to do different things. Is this the right way to do stuff in Fantom?
I sure hope it's not me :D
Thanks for replies guys...
SlimerDude Thu 26 Jul 2012
Err, that sounds orrible!
As they do different things, can you not break it out into different methods with different names?
And I'd avoid the
null
type (Obj?) as much as possible unless you really have to. One of the things I like about Fantom is that my objs are usually guaranteed not to be null.ikhwanhayat Thu 26 Jul 2012
API looks cleaner with method overloading. Let say I have a method that accepts a type, and then I want another one that do the same thing but accepts the type name instead. So basically in Fantom I accepts an
Obj
then check whether its aType
or anStr
.I'm thinking that maybe Fantom is pushing us to achieve polymorphism via classes instead of methods.
SlimerDude Thu 26 Jul 2012
See Method Overloading for a quick explanation of why Fantom doesn't allow it.
My favourite comment is: (!)
SlimerDude Fri 27 Jul 2012
When I first moved to Fantom I felt the lack of method overloading a little restrictive, but since I started using Fantom properly, I've barely noticed.
Convention (or an easy way out) is to add the type sig to the method name. e.g. from
sys::Int
don't have:but rather
which turns out to be a lot more explicit, hence I would say better.
And I'd briefly refer you to StackOverflows Is method overloading a form of polymorphism or something else?
ikhwanhayat Fri 27 Jul 2012
I've read those posts in this forum and agree that no method overloading makes it simpler, like when working with reflections (which I also seem to use a lot in Fantom). Also, when you have default/named parameters you don't really need method overloading. I guess the pro is more than the cons.
I think it would be really good if there's a guide for this kind of things, like how you do it in Fantom when usually you do it with method overloading in other languages. Also for generics, null checking, etc. Some kind of recipes or cookbook.
brian Fri 27 Jul 2012
To get back to the original issue, would everybody like to see something like a a new method on List for:
Yeah or nay or other ideas?
Akcelisto Fri 27 Jul 2012
No matter. I never compare lists.
SlimerDude Fri 27 Jul 2012
How about a method that returns a new List backed by a new type? That would allow you to up or downcast every item in the list then you could do
l1 == l2
as usuall.ikhwanhayat Fri 27 Jul 2012
Yes, obviously :)
ikhwanhayat Fri 27 Jul 2012
Wouldn't that take much more from performance compared to comparing items 1 by 1?
SlimerDude Sat 28 Jul 2012
I was thinking of a method such as
which returns a new list of a different type which in your example would allow you to do:
Not that I think I'd ever have use for it.
Though, to be honest, I'd be happy with the
List.equals
only checking the contents of the List so we don't have to think / bother with this List.typeOf stuff. I can't remember a time when I've been concerned about the List impl. I see a list as a transparent wrapper caring only about what it contains.Hmm, I'd be interested to find out what the objections were.
brian Sat 28 Jul 2012
That is already pretty trivial like this (and probably maybe even a little more readable to show intent):
I think most people would consider type to be an inherit quality to identity and equality. For example
Str[,]
really is not the same thing asInt[,]
and they will behave quite differently when you go to add stuff.I don't think this has even bothered me in normal code. Where it gets a bit annoying is testing code. But the basic idea was that if you are actually writing a test case, you should be checking the list type to make sure you aren't returning a
Obj[]
when you should have been returning aFoo[]
.SlimerDude Sat 28 Jul 2012
Nice one.
I did quibble with this myself, but then realised I've never cared about the List type, namely because...
...it's all picked up by the compiler.
Meanwhile, I (myslef) am non-plussed about a
Bool valsEqual(List that)
for I can't see me using it. And a :would suffice should I ever need to.
ikhwanhayat Sat 28 Jul 2012
I just noticed something.
So in List's case, equality doesn't means the hashes are equal.
Also if
valsEqual(List other)
is to be implemented, it can just be a wrapper aroundthis.hash == other.hash
right?SlimerDude Sat 28 Jul 2012
Err no. Because you're comparing hashes, not Obj contents. Although very unlikely, hashes (by their very nature) are not guaranteed to be unique. They only exist to help hashtables.
From Java's
Object#hashcode
JavaDoc:At most a hash is just a checksum - it doesn't guarantee uniqueness.