Live data from Hacker News

My Objection to Array#sum

github.com

11–20 of 65 posts

Re: My Objection to Array#sum

#11
Why is [1,"two"].sum any different from 1 + "two"? That is, 1.respond_to?(:+) is always going to be true, and yet sometimes sending the + message to a number will give a type error.

I don't buy into this idea of interface as binary - that if you respond_to? the message, it's always appropriate, and if you don't, it's not. Interfaces are something you look at when you're writing the program, and so they are interpreted by humans and can be necessarily fuzzy: "#sum will give you the total of the elements in the array, unless they aren't homogenous, in which case you'll likely get an error". Fine. If you don't know enough about the array in question, don't send #sum.

Similarly, if you don't know that this is a chequing account, it would be odd to ask it to write a cheque.

But at runtime, you send the message, and you maybe get an error. Whether this is TypeError or NoMethodError seems entirely irrelevant.

Incidentally, my objection to Array#sum is that you don't know what to use as the "0" element (what if the elements implement +, but aren't numbers), though I'd be fine with it being called #numeric_sum or the like.

Re: My Objection to Array#sum

#12
Not all arrays can be summed, but they all claim to respond to #sum. This is extremely broken.

This is how I felt when I first saw Array#sum. But then I took a few hi-

But then I tried it a few times. And now I can quit anytime I want.

I think String#titlecase is correct though. Not all arrays can be summed, but all strings can be titlecased, including part codes.

Re: My Objection to Array#sum

#13
post #6

Python does this - sum/any/all are standalone functions, and join() is a member of the string class instead of the array class. Python also gets a lot of flack for it, as it seems like every month you can see someone complaining about why you use `"\n".join(lines)` to join an array instead of `lines.join("\n")`. People can't seem to wrap their head around it. Personally, I think the big mistake is to think objects sh…

Count me as one of those people that don't get it. If I'm joining the elements of an array together, I'm operating on the array. Therefore I _expect_ the join() method to be on the array. To me, Python can't seem to make up its mind with these weird (IMHO) stand-alone methods like join(), sum(), any(), etc. That's the kind of thing I'd expect in a functional language, not in an OO language.

I agree with you if you mean that an array should be able to abstractly reduce its elements, but I'd argue that the specifics of how the array gets reduced are generally outside of the responsibility of the array class.

In Ruby, this is accomplished through Array#inject, which allows you to specify the procedure that gets applied as you're joining. This makes it easy to do summing, string concatenation, etc, etc.

Re: My Objection to Array#sum

#14

Not all arrays can be summed, but they all claim to respond to #sum. This is extremely broken. This is how I felt when I first saw Array#sum. But then I took a few hi- But then I tried it a few times. And now I can quit anytime I want. I think String#titlecase is correct though. Not all arrays can be summed, but all strings can be titlecased, including part codes.

But does String#titlecase do the right thing for ß? :)

Re: My Objection to Array#sum

#15
post #4

Calling [1,2,3].inject(0) {|sum, ii| sum + ii } has a cleaner smell, but it's a lot more typing. I wonder if the solution might be to have all arrays support sum (in the responds_to() sense) only if they can can actually perform the operation. Thus [1, 2, 3].respond_to?(:sum) => true [1, [2, 3]].respond_to?(:sum) => false I can come up with an O(1) way to do this where we assume that an array does respond to sum, and…

[1, [2, 3]].respond_to?(:sum) => false I elided a discussion about this case from the post. For some arrays, a recursive sum is semantically valid. For other arrays a recursive sum is not semantically valid, and it is not a simple case of knowing whether all of the leaf elements respond to :+. So again, trying to implement this in the Array class doesn't work because containers are implementation rather than interfac…

[deleted]

Re: My Objection to Array#sum

#17
I agree with you.

That being said, I suspect that this turns out to be a cultural debate more than anything else. Remember, Ruby is a freedom language. Ruby could eliminate many of the issues you raise by being strictly typed, but of course that'd defeat the purpose.

The whole thing is a question of trust. Do you trust clients enough to give them the syntactic sugar of Array#sum even if their arrays may not all be strictly summable?

The answer to that question if you're writing Java is probably no. If you're a Rubyist, however, the answer is a resounding maybe. For something like ActiveSupport, it's probably OK. For other more hostile environments, maybe not.

As to whether it's idiomatic Ruby to provide Array#sum, I'd argue no, even though it's culturally acceptable.

Re: My Objection to Array#sum

#18
post #15

Earlier quoted context omitted.

[1, [2, 3]].respond_to?(:sum) => false I elided a discussion about this case from the post. For some arrays, a recursive sum is semantically valid. For other arrays a recursive sum is not semantically valid, and it is not a simple case of knowing whether all of the leaf elements respond to :+. So again, trying to implement this in the Array class doesn't work because containers are implementation rather than interfac…

[deleted]

[deleted]

Re: My Objection to Array#sum

#19
post #17

I agree with you. That being said, I suspect that this turns out to be a cultural debate more than anything else. Remember, Ruby is a freedom language. Ruby could eliminate many of the issues you raise by being strictly typed, but of course that'd defeat the purpose. The whole thing is a question of trust. Do you trust clients enough to give them the syntactic sugar of Array#sum even if their arrays may not all be st…

> The whole thing is a question of trust. Do you trust clients enough to give them the syntactic sugar of Array#sum even if their arrays may not all be strictly summable?

I agree that Ruby should embrace Freedom, but that does not mean that all choices programers make freely are good ones. This is not about whether programmers accidentally call #sum on arrays that cannot be summed. It is about whether, when I look at the methods implemented by Array, it describes what arrays do or what arrays sometimes do or may do once in a while.

I actually think that Array#sum is the least objectionable in a single project where summing the elements may be common, maybe objectionable in ActiveSupport where every Rails project gets it whether they sum arrays or not, and absolutely wrong in Ruby's core libraries where every Ruby programmer will get it.

Free choices should be scrutinized most carefully when they has the broadest impact.

Re: My Objection to Array#sum

#20
post #10
post #6

Earlier quoted context omitted.

Count me as one of those people that don't get it. If I'm joining the elements of an array together, I'm operating on the array. Therefore I _expect_ the join() method to be on the array. To me, Python can't seem to make up its mind with these weird (IMHO) stand-alone methods like join(), sum(), any(), etc. That's the kind of thing I'd expect in a functional language, not in an OO language.

The thing is, they aren't methods. They really aren't. They don't operate on an object using the object's local data. They are generic functions that use certain defined interfaces that many objects define. "list.join(str)" and "str.join(list)" are not the same . The list.join syntax only works for lists, but str.join takes any sequence , which is anything that implements the sequence protocol, including lists, dicts…

Well join should be on sequence instead of list then.

To me it seems unnatural to see join on string because string feels more 'basic' than a sequence, so I would expect the sequence to know about strings rather than the opposite. But the argument against join on string is not as strong as the argument against sum on array.

Post reply on HN