Live data from Hacker News

The Dynamic Def – abusing Ruby's def statement

weblog.jamisbuck.org

21–30 of 87 posts

Re: The Dynamic Def – abusing Ruby's def statement

#21
post #16
post #12

Earlier quoted context omitted.

Anytime you have some value type. Say a `Money` class for instance. The default `==` from Object compare identity, so unless you define it `Money.new(20, 'USD') != Money.new(20, 'USD')`.

Right, this seems like exactly why we shouldn't be allowed to redefine it. As a reader of your code that redefines ==, I think == means we are talking identity until I find your function that redefines ==. It has made it so I need to understand more things in order to be able to reason about your code. That seems like a negative to me.

But even in core Ruby, == is not always identity; hashes, arrays, ranges, all of them are compared by value and not by identity. The assumption that == is comparing identity is broken, not the code that implements it differently.

Re: The Dynamic Def – abusing Ruby's def statement

#22
post #18
post #16

Earlier quoted context omitted.

Right, this seems like exactly why we shouldn't be allowed to redefine it. As a reader of your code that redefines ==, I think == means we are talking identity until I find your function that redefines ==. It has made it so I need to understand more things in order to be able to reason about your code. That seems like a negative to me.

That's because you are among the people who don't like abstractions. I disagree with that opinion, but that's fine, Ruby is just definitely not for you. Don't try to change or complain about Ruby, you are likely more happy with languages like go.

> That's because you are among the people who don't like abstractions.

That's not the issue at all. Abstractions are great. Redefining operators is not abstraction, it's practically obfuscation.

Re: The Dynamic Def – abusing Ruby's def statement

#23
post #9

Earlier quoted context omitted.

Can you give me an example of where redefining equality makes sense?

Without 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.

I think Python make the difference clear, with == vs "is".

Re: The Dynamic Def – abusing Ruby's def statement

#24
post #16

Earlier quoted context omitted.

Right, this seems like exactly why we shouldn't be allowed to redefine it. As a reader of your code that redefines ==, I think == means we are talking identity until I find your function that redefines ==. It has made it so I need to understand more things in order to be able to reason about your code. That seems like a negative to me.

But even in core Ruby, == is not always identity; hashes, arrays, ranges, all of them are compared by value and not by identity. The assumption that == is comparing identity is broken, not the code that implements it differently.

For "primitives" yes, for objects no. What would be primitives in Ruby extend Object, because everything in ruby does, but (sigh) they redefine == so they act more like primitives in other languages. At least there is a clear cut rule, but it's pretty much turtles all the way down.

Re: The Dynamic Def – abusing Ruby's def statement

#25
post #10

Earlier quoted context omitted.

It's a complaint about the ability to redefine many things that shouldn't be redefine-able, operators included.

Very 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. used as 'int x = v1 v2;' If you're going to do something with operators, at least let me make descriptive ones.

I 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.

Re: The Dynamic Def – abusing Ruby's def statement

#26

Earlier quoted context omitted.

Very 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. used as 'int x = v1 v2;' If you're going to do something with operators, at least let me make descriptive ones.

I 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.

Its 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.

Re: The Dynamic Def – abusing Ruby's def statement

#27
post #24

Earlier quoted context omitted.

But even in core Ruby, == is not always identity; hashes, arrays, ranges, all of them are compared by value and not by identity. The assumption that == is comparing identity is broken, not the code that implements it differently.

For "primitives" yes, for objects no. What would be primitives in Ruby extend Object, because everything in ruby does, but (sigh) they redefine == so they act more like primitives in other languages. At least there is a clear cut rule, but it's pretty much turtles all the way down.

But there are no primitives in Ruby, that's the point. Everything is an object, and some objects extend ==, others don't, even in the core language.

Re: The Dynamic Def – abusing Ruby's def statement

#29

Earlier quoted context omitted.

I 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.

Its 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.

Sure, for some cases, == is not immediately clear. Don't use it in those cases.

Re: The Dynamic Def – abusing Ruby's def statement

#30

Earlier quoted context omitted.

I 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.

Its 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.

> 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.

Post reply on HN