4

Feel free to delete this topic if it's discussed or quite obvious. I hail from C# background and I'm planning to learn Ruby. Everything I read about it seems quite intriguing. But I'm confused over this basic philosophy of Ruby that "there's more than one way to do one thing". Can someone provide 2 or 3 simple arithmetic or string examples to make this point clear, like if its about the syntaxes or logics etc.

Thanks

Andrew Grimm
  • 78,473
  • 57
  • 200
  • 338
nawfal
  • 70,104
  • 56
  • 326
  • 368
  • I think it's all about syntactic sugar. – Emiliano Poggi Jun 19 '11 at 08:33
  • 1
    As you say yourself, it's more a philosophy than a literal truth. In virtually all languages it's *possible* to do many things in different ways (but maybe not equally easy). The point about Ruby is that it's *considered okay* by the community to actually do things in different ways. The earlier language python had exactly the opposite attitude: there should be *exactly one* way of doing most things. (And this, in turn, was a reaction to Perl's motto "There's more than one way to do it".) – Kilian Foth Jun 19 '11 at 10:40
  • Question is ambiguous and vague? A person has even replied me showing me an example how ruby has a different approach, exactly what I asked. I don't know what went wrong with this question. Embarrassing – nawfal Jun 19 '11 at 12:07
  • @AndrewGrimm: That's a really marginal tag. Quite worthy of generating a meta discussion all by itself. – Robert Harvey Nov 05 '12 at 06:49
  • @RobertHarvey I didn't create the tag. I suspect Sklivvz, who is a diamond mod on Skeptics.SE, created it. – Andrew Grimm Nov 05 '12 at 06:58
  • In any language, there are many ways of doing things, so the statement is not meaningful if taken literally. What it really means is that Ruby has tons of syntactic sugar. do/end blocks versus curly blocks. Stabby lambda literals `->(x) { ...}` versus writing out "lambda" `lambda { |x| ... }` etc etc. In my experience teaching intro to CS courses, it makes it much harder for beginners, adds confusion and inconsistency to the syntax, requires them to memorize all the different orders of precedence etc. – Marcel Besixdouze Aug 04 '22 at 13:15
  • 1
    It's worth noting that TIMTOWTDI philosophy originates in Perl. Ruby has a very strong Perl legacy (the name of the language itself being a gemstone is an homage to Perl). – Marcel Besixdouze Aug 04 '22 at 13:27
  • @KilianFoth That isn't quite the Python motto. The python motto is: "There should be one-- and preferably only one --obvious way to do it. Although that way may not be obvious at first unless you're Dutch." There will always be many ways to do it, but there should be at least one way that is obvious, and it's preferable if there is only one way that's obvious. The obvious way might not even be the best way, there's no statement like that going on. – Marcel Besixdouze Aug 04 '22 at 13:33

3 Answers3

7

"More than one way of doing something" means having the choice of doing something the way you want it. That way you can use various programming styles, no matter what background you're coming from.


Iteration using for vs. blocks

You can iterate over an array of things like so. This is pretty basic, and if you're from a Java background, this feels kind of natural.

for something in an_array
   print something
end

A more Ruby-like way would be the following:

an_array.each do |something|
    print something
end

The first is a rather well known way of doing things. The second one is using blocks, a very powerful concept that you'll find in many Ruby idioms. Basically, the array knows how to iterate over its contents, so you can modify this and add something like:

an_array.each_with_index do |something, index|
    print "At #{index}, there is #{something}"
end

You could have done it like this too, but now you see that the above one looks easier:

index = 0
for something in an_array
    print "At #{index}, there is #{something}"
    index += 1
end

Passing arguments as usual or using Hashes

Normally, you would pass arguments like so:

def foo(arg1, arg2, arg3)
    print "I have three arguments, which are #{arg1}, #{arg2} and #{arg3}"
end

foo("very", "easy", "classic")

=> "I have three arguments, which are very easy and classic"

However, you may also use a Hash to do that:

def foo(args)
    print "I have multiple arguments, they are #{args[:arg1]}, #{args[:arg2]} and #{args[:arg3]}"
end

foo :arg1 => "in a", :arg2 => "hash", :arg3 => "cool"

=> "I have three arguments, which are in a hash and cool"

The second form is one used excessively by Ruby on Rails. The nice thing is that you now have named parameters. When you are passing them, you will more easily remember what they are used for.

slhck
  • 36,575
  • 28
  • 148
  • 201
  • 1
    Feel free to expand (this is a CW post) – slhck Jun 19 '11 at 08:39
  • I don't consider these good examples. Iterators are available in many languages that also have loops, but which very much do not have Ruby's philosophy with regards to excessive syntactic sugar and inconsistency. And your second example is just a hash literal; again I don't think the fact that literal expressions are available for certain data types in a language captures whether or not that language follows a TIMTOWTDI philosophy. – Marcel Besixdouze Aug 04 '22 at 13:25
5

It means a lot of confusion, style wars, and bugs due to subtle differences, all in the name of freedom of choice.

Cees Timmerman
  • 17,623
  • 11
  • 91
  • 124
1

A somewhat trivial example is the use of alias/alias_method (also note that there are two similar ways for almost the same thing, e. g. alias versus alias_method).

Consider that you are working in a project and you forgot which API to use.

What was the name of the method again?

Well, you can just remain within the domain logic of your program at hand, and continue to work with it the way you want to; then you are going to simply add an alias in the main entry point of your other program.

People can use by default .collect or they can use .map, it makes little difference what you personally would use (I use .map since it is shorter).

The use of aliases helped me because after some months, I often can not remember how to use something. Yes, I could look it up, but why would I have to bother anyway? I can just use an alias instead. (Note that I do try to remain as simple as possible with aliases and APIs.)

shevy
  • 920
  • 1
  • 12
  • 18