8 ms·
Cool article about the craziness of Ruby. Ruby is a frustrating language. The oauth gem, for instance, redefines '==(val)' on the AccessToken to 'Base64.encod
by wdewind 11y ago
Cool article about the craziness of Ruby. Ruby is a frustrating language. The oauth gem, for instance, redefines '==(val)' on the AccessToken to 'Base64.encode(self.signature) == Base64.encode(val).'
This stuff feels really dangerous and unnecessary. I spend a lot of time on code reviews pointing out bad features of Ruby (and Rails) that we shouldn't be using because they break application flow and make it significantly harder to reason about the code for the small benefit of decreasing a few lines. But it's certainly fun to talk about :)
- rylee 11y ago> The oauth gem, for instance, redefines '==(val)' on the AccessToken to 'Base64.encode(self.signature) == Base64.encode(val).' Is this just a complaint about the ability to overload operators in general?
- wdewind 11y agoIt's a complaint about the ability to redefine many things that shouldn't be redefine-able, operators included.
- JoeAltmaier 11y agoVery right. Operator overloading is a self-indulgent trick. The only one to benefit is the author. Subsequent readers are mostly confused. Instead of overloading, I've always wanted to define new operators e.g. <DotProduct> used as 'int x = v1 <DotProduct> v2;' If you're going to do something with operators, at least let me make descriptive ones.
- wdewind 11y ago> Operator overloading is a self-indulgent trick. The only one to benefit is the author. That's a great way to put it.
- icebraining 11y agoI disagree, operator overloading often makes the code much more readable. I don't see the problem unless you're trying to write C in Ruby. As long as the overloaded implementation keeps the expected semantics as described in the language documentation, it's fine.
- JoeAltmaier 11y agoIts not ever 'fine'. Its confusing at best. Imagine a component with 5 attributes. Does '==' match them all? Some of them? Loosely or tightly? I'm afraid just seeing '==' in the code is never going to be informative. Instead, maybe a method MatchAttr1And2(v1, v2) would certainly tell a subsequent reader a little more about what's going on.
- icebraining 11y agoSure, for some cases, == is not immediately clear. Don't use it in those cases.
- msbarnett 11y ago> Imagine a component with 5 attributes. Does '==' match them all? Some of them? Loosely or tightly? I'm afraid just seeing '==' in the code is never going to be informative. This is, fundamentally, a disagreement about the value of encapsulation. With an opaque, encapsulated type, '==' should mean whatever makes the most sense in the context of that type. For a pointer that might be "equality" means "same memory address", whereas for a vector that might mean "equal components". As a user, "equality" should match an intuitive understanding of what it means for two things of this type to "be the same". It's an art form. Like many things in programming, doing it well requires good taste. Operator overloading is a powerful technique for preserving encapsulation. It's the polar opposite of: > Instead, maybe a method MatchAttr1And2(v1, v2) would certainly tell a subsequent reader a little more about what's going on. This leaks implementation details like a sieve. It's a great recipe for encouraging dependency on a particular implementation detail across module boundaries, and rolling yourself a great heaping ball of mud.
- 11y ago
- blt 11y agoEhh, there are good and bad uses. Yes, dot product should not be overloaded asterisk operator because elementwise multiplication of vectors is a thing, and also if you overload multiplication for matrices then dot product should be u-transpose-times-v for consistency. But what about vector addition? There's no ambiguity. Try writing any 3d graphics code without overloaded vector addition. It sucks. I generally disagree with people who dislike a language feature only because of its abuse potential. Good programmers should not have to suffer for the sake of damage controlling bad programmers. Edit: I do think it's stupid to make the identity-equals operator overloadable. Identity-equals and value-equals are separate concepts. In C++ this isn't an issue because == is the value-equals operator.
- msbarnett 11y ago> Edit: I do think it's stupid to make the identity-equals operator overloadable. Identity-equals and value-equals are separate concepts. In C++ this isn't an issue because == is the value-equals operator. In Ruby, == is value-equals at well (identity-equality being such a rarely needed concept in Ruby that it wouldn't make sense to privilege it with its own operator). Identity equality in Ruby is provided by: a.object_id == b.object_id
- anamexis 11y agoFor identity equality, there's also `Object#equal?`. http://ruby-doc.org/core-2.2.3/Object.html#method-i-eql-3F http://ruby-doc.org/core-2.2.3/Object.html#method-i-eql-3F
- regularfry 11y agoIn its place, being able to redefine equality on value types really helps clarify code. Misused, it creates confusion. The problem is that it's easy to think you've got a case where it helps, when actually it's not well-defined. Usually that revolves around there being state you care about which is missed from the equality comparison. Another trap is redefining #== without also looking at #eql?, which means Hash doesn't behave like you expect. It's just another bit of mental trivia you've got to Just Know...
- wdewind 11y agoCan you give me an example of where redefining equality makes sense?
- JoeAltmaier 11y agoWithout explicit comments/documentation it is hard to imagine a good example. Its a longstanding issue. Even Lisp has 'equals' and 'equals?' which is an abomination. One looks for identity of object; the other for identity of value (if I understand it right). These kind of things are bug factories.
- icebraining 11y agoI think Python make the difference clear, with == vs "is".
- msbarnett 11y agoRuby provides object_id for the same purpose. Comparing those for equality provides the "is_" semantics.
- deckard1 11y agoKent Pitman has always been a good read, for the problems of equality in dynamic languages. The typical Ruby or JS programmer stumbles through the day just "getting by", where it comes to comparing objects. http://www.nhplace.com/kent/PS/EQUAL.html http://www.nhplace.com/kent/PS/EQUAL.html
- pdkl95 11y agoRuby is a wonderful (and wonderfully powerful) language. Unfortunately, some of the popular ruby libraries (gems) are... problematic. To put it nicely. The web/rails gems in particular can be nasty minefields. However, the language itself is great. The trick is to remember the usual advice that just because you can doesn't mean you should. Too many gems add "clever" metaprogramming (such as the def tricks in this article), when it isn't actually making the program simpler. The beauty of ruby is that while it can act almost like a LISP for the times when you want powerful metaprogramming features, while also allowing simple shell or C style imperative code when that is more appropriate. (Of course, some people fear that type of freedom... https://vimeo.com/17420638 https://vimeo.com/17420638 )