Live data from Hacker News

The Dynamic Def – abusing Ruby's def statement

weblog.jamisbuck.org

31–40 of 87 posts

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

#31

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.

If the code you're dealing with makes you care what the equality operator is doing internally, it's not well enough abstracted.

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

#32
post #9

Earlier quoted context omitted.

In 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 does…

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

Any value type.

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

#33
post #22
post #18

Earlier quoted context omitted.

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.

It is. By redefining the equality method (operators are just regular methods really), you abstract away how this kind of object need to be compared with it's peers.

The fact that it's an operator or a method doesn't change a thing. For example in Java many classes redefine the `equals` method. It's default behavior is just like Ruby, comparing identity. It's not an operator but the effect is exactly the same. And IMO it's worse because now you have a leaky abstraction with types you need to compare with `==` and others with `.equals`.

It's just you who have this expectation of operators being not redefinable. When I read Ruby code, for me `==`, or `+` are just regular methods like any others with just a bit of syntactic sugar.

It also allows for greater polymorphism. Like the Money object from before. If I couldn't redefine `+`, then `[Money.new(20), Money.new(22)].sum` wouldn't work.

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

#34

Earlier quoted context omitted.

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 add…

Only if you do it that way. Make it MatchForParticularPurpose(v1, v2) instead, and voila no leak.

Operators are unique in the language. They hold a special place. They deliberately are written to imply something we already understand. No fair lumping them in with every other attribute or method of an encapsulated type.

Intuition is a very, very poor thing to depend upon in a programming language. I disagree heartily that it should be the solution to disambiguating any operation.

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

#35

Just because you CAN do something doesn't mean you SHOULD. Metaprogramming has a place in Ruby but for the examples in the article there are far more readable ways to implement it. Readability > cleverness every single time.

> Readability > cleverness every single time.

Readability is in the eye of the beholder. For those unfamiliar with higher-order programming, maps are just a 'too clever' form of a for loop.

A clean and understandable solution is one matching the problem being solved in a precise way. In search for simplicity one can't forget that programming is a trade, and one should be expected to actually learn some shit.

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

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

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

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

#37

Just because you CAN do something doesn't mean you SHOULD. Metaprogramming has a place in Ruby but for the examples in the article there are far more readable ways to implement it. Readability > cleverness every single time.

> Readability > cleverness every single time. Readability is in the eye of the beholder. For those unfamiliar with higher-order programming, maps are just a 'too clever' form of a for loop. A clean and understandable solution is one matching the problem being solved in a precise way. In search for simplicity one can't forget that programming is a trade , and one should be expected to actually learn some shit.

To that point, Jef Raskin famouly said that “intuitive == familiar,” and all-too-often, that’s exactly what people mean when they talk about “intuitive" code and/or user interfaces.

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

#38
post #12
post #9

Earlier quoted context omitted.

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

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')`.

Should Money.new(20, 'USD') == Money.new(2000, 'US Cents')?

Or Money.new(20, 'USD') == Money.new(125, 'CNY') when ExchangeRateManager.getExchangeRate('CNY', 'USD') == 0.16?

My point is that when performing these comparisons, it may be useful to use a more descriptive function like:

boolean currenciesHaveSameWorth(Money m1, Money m2)

And then a reader of the calling code might not have to look into the implementation to understand what the function is doing, whereas you definitely would when using == because == now means "whatever it's overridden to mean"

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

#39

Just because you CAN do something doesn't mean you SHOULD. Metaprogramming has a place in Ruby but for the examples in the article there are far more readable ways to implement it. Readability > cleverness every single time.

> Just because you CAN do something doesn't mean you SHOULD

This is hacker news, not "production code" news. Abusing things in unexpected ways is pretty much the definition of hacking.

Many people seem to be jumping on this article as if the author was suggestion a new programming pattern we should start using, rather than an interesting look at some of the lesser-known quirks of ruby. I'm pretty sure even the author would agree that triple nested method definitions are not something we should use for production code.

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

#40

Just because you CAN do something doesn't mean you SHOULD. Metaprogramming has a place in Ruby but for the examples in the article there are far more readable ways to implement it. Readability > cleverness every single time.

This is a fundamental part of the language, the idea that objects and classes are dynamic, not static.

What I would say is that although we should have an extremely good reason to employ these techniques in production, I believe that every professional Ruby programmer should be able to understand them and/or figure them out in a few minutes.

It’s not like we’re talking about obfuscated C.

Post reply on HN