Hacker News new | ask | show | jobs
by ploxiln 3972 days ago
To me that appears to be the strangest way to express a loop in any language I've used (and I've used a lot of them).

It also really bothers me that in ruby you can invoke a function on a null value to see if its null (myvar.nil?). That's really messed up...

5 comments

> To me that appears to be the strangest way to express a loop in any language I've used (and I've used a lot of them).

Well, given that repeating some piece of code N times involves only two "entities", the code to be repeated and the number of repetitions, i see it as a very natural OO design decision to put that looping logic on a method on one of those two entities. The other possibility would be to make the "code" object respond to a method that tells it how many times to execute:

  { puts "Hello, alternate Ruby" }.do_times(10)
It might be more intuitive to do so if the first object you have is the code you want to repeat, but it doesn't read as nicely :P

> It also really bothers me that in ruby you can invoke a function on a null value to see if its null (myvar.nil?). That's really messed up...

Can you elaborate in this please? I personally think that making nil something else than an object on OO language wouldn't make much sense. It would be an unnecessary complexity to stipulate "the way we interact with objects is through message-passing, except with nil, on which you cannot pass any message, but instead you have to compare it by identity to a global value named nil". Nil being a regular object that responds to things like .to_s or .nil? is pretty handy.

If you don't know the type which a name references (or whether it is nil), you have to figure that out before you call any methods on it, in an "external" way. So you have to do " == nil" or "typeof(mything) ==" or "isinstance(mything, type)". This is true for almost every method (except "nil?" in ruby.)

Ruby has a lot of these special cases where there's a gimmicky way to do something which is not the general purpose way and is not the right way to think about that kind of logic. "== nil" is just as short as ".nil?" and isn't as wacky as intentionally calling methods of nil (and every other object needing to have this nil-specific interface).

This isn't a gimmick or a special case. "nil" is an object of type NilClass, which is a subclass of Object: http://ruby-doc.org/core-2.2.0/NilClass.html

In fact, everything in Ruby is an object. Languages that treat "nil" or "44" as not being instances of a class are the ones making special cases.

The absence of an object is not a special case.

To indicate that with a "nill" object is a special case?

> That's really messed up...

No, it's a brilliant use of polymorphism. "null" in Ruby is not a value, it's like everything else an object. So it have methods.

Just because you are not used to it doesn't make it messed up.

It's the wrong way to think about organization of logic.

It's not a number's place to know how to do looping, it's not an object's place to know whether it's nil or not. Why would every single object have a "nil?" method?

You can make it work, but it's just not good style (and it doesn't serve the purpose of implementation efficiency or machine-sympathy, which I would give exception for).

(also, special characters in method names?! my complaints about ruby really don't end with these comments, these are just the most succinct ones)

> It's the wrong way to think about organization of logic.

This is not an objective statement, it is one of subjective preference, about which people (demonstrably, by the very existence of Ruby) disagree. The right way to think about organization of logic is not an objective fact, and...

> You can make it work, but it's just not good style

...neither is "style".

> It's not a number's place to know how to do looping

If we consider a number as "zero or 1 plus a number", then the "Number" class could very well be the one that knows how to execute a piece of code a number times given that representation. It's actually pretty similar to the Church encoding of numbers in the lambda calculus[1].

[1]: https://en.wikipedia.org/wiki/Church_encoding

The number doesn't know how to loop. `100.times` returns an enumerator that can then be iterated upon. In real code, that particular method doesn't get used all that much, but its existence tells you nothing about Ruby's design.

Why shouldn't every single object have a 'nil?' method? It can be very useful. Think about operating on a collection of objects with `map` or `collect` or whatever your favorite language calls it. No need to write code, just send the `:nil?` message to every object, which you can do with one line.

You're right that "everything is an object" is not the most performant way to build a runtime, but it suits the purposes for which Ruby was designed very well. Just because you don't value those priorities doesn't mean others do not.

> To me that appears to be the strangest way to express a loop in any language I've used (and I've used a lot of them).

How is it strange? Feels rather intuitive to me: "Do this 100 times".

> It also really bothers me that in ruby you can invoke a function on a null value to see if its null (myvar.nil?). That's really messed up...

Again: how so? `nil` is just another object, so why shouldn't it have a method telling us if it's nil?

Of course, if you don't like it, you could check to see if it equals `nil`, or you can check if its class is equal to or is a subclass of `NilClass`. Like Perl, There's More Than One Way To Do It (TM).

It only seems messed up because you know about pointers, which are an implementation detail. In an object-oriented language it makes perfect sense. I assume Smalltalk did something similar.
If you knew nothing about programming that would not look strange to you. On the contrary, it might look as the most intuitive way to do it. And since this book is for kids who know nothing about coding... well, you can see where I am going.