Forum: Ruby What exactly does "rubyish" or "ruby way" mean?

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
R. K. (Guest)
on 2008-10-22 17:38
Over the last month I have been reading a lot of blogs, searching, going
through source code of some apps and my pickaxe. I am still unable to
clearly understand what all "the ruby way" means.

I will be perfectly happy if you can tell me:

1. phrases to google on, or check in pickaxe
2. pointers to specific libraries or classes i can study
3. link to any article I may have missed, or blog

The only thing I can put down, that i have gleaned, is the usage of
procs/blocks, i.e. allowing the user to pass in blocks/yielding a value
or self. I liked the chapter on Ruby Tk in pickaxe (since I am hoping to
write a rubyish wrapper to ncurses).

Surely there is more to the ruby way than blocks/procs/lambda. Would
really appreciate pointers.

thanks.
Todd B. (Guest)
on 2008-10-22 18:05
(Received via mailing list)
On Wed, Oct 22, 2008 at 8:37 AM, Nit K. <removed_email_address@domain.invalid>
wrote:
> The only thing I can put down, that i have gleaned, is the usage of
> procs/blocks, i.e. allowing the user to pass in blocks/yielding a value
> or self. I liked the chapter on Ruby Tk in pickaxe (since I am hoping to
> write a rubyish wrapper to ncurses).
>
> Surely there is more to the ruby way than blocks/procs/lambda. Would
> really appreciate pointers.

I avoid phrases like "ruby way" or words like "rubyish" simply because
the language is flexible enough to allow you to do your own thing.

With that said... my style gravitates towards conceptual, whereas some
are concerned about performance, and others about something else.

On this list, it seems people like to talk about elegance, which, to
me, means that very once in a while, someone comes up with a piece of
terse code that, at first glance, makes perfect sense; almost like a
eureka moment.

I think, very humbly, that Ruby tries its best to provide those
eureka/click moments.

So, I believe that your best answer is to read a good portion of Ruby
code (which you said you have done) and pay attention to ruby-talk.
Being rubyish is by no means a standard.  Just look at Ruby Q. to
see the variety.

Todd
Hugh S. (Guest)
on 2008-10-22 18:09
(Received via mailing list)
On Wed, 22 Oct 2008, Nit K. wrote:

> Over the last month I have been reading a lot of blogs, searching, going
> through source code of some apps and my pickaxe. I am still unable to
> clearly understand what all "the ruby way" means.

Ruby is a [programming] language.  To do things in the ruby way means
to write it as those who regularly (and skillfully) use the language
write it.  Some say "It is possible to write FORTRAN in any language".
That is the opposite idea.  Idiomatic usage, is another way to consider
it.

>
> I will be perfectly happy if you can tell me:
>
> 1. phrases to google on, or check in pickaxe
> 2. pointers to specific libraries or classes i can study
> 3. link to any article I may have missed, or blog
>
> The only thing I can put down, that i have gleaned, is the usage of
> procs/blocks, i.e. allowing the user to pass in blocks/yielding a value

Rubyists don't always do that.  It depends on whether it makes sense
to do so.  It is really about knowing the language and it's libraries
to be able to use them clearly and with some degree of elegance.

Well, that's my take on it, anyway.

> or self. I liked the chapter on Ruby Tk in pickaxe (since I am hoping to
> write a rubyish wrapper to ncurses).
>
> Surely there is more to the ruby way than blocks/procs/lambda. Would
> really appreciate pointers.
>
> thanks.

        Hugh
Lloyd L. (Guest)
on 2008-10-22 18:15
Nit K. wrote:
> Over the last month I have been reading a lot of blogs, searching, going
> through source code of some apps and my pickaxe. I am still unable to
> clearly understand what all "the ruby way" means.
>
> I will be perfectly happy if you can tell me:
>
> 1. phrases to google on, or check in pickaxe
> 2. pointers to specific libraries or classes i can study
> 3. link to any article I may have missed, or blog
>
> The only thing I can put down, that i have gleaned, is the usage of
> procs/blocks, i.e. allowing the user to pass in blocks/yielding a value
> or self. I liked the chapter on Ruby Tk in pickaxe (since I am hoping to
> write a rubyish wrapper to ncurses).
>
> Surely there is more to the ruby way than blocks/procs/lambda. Would
> really appreciate pointers.
>
> thanks.

In short, I believe that a program is "rubyish" when it is the language
solving the problem rather than the writing of an algorithm to do it, as
in Java et. al.

Here are possible examples from recent threads here.  Consider how this
would be written in java, then compare it to these.

First example:

1.     You are given a big (odd) string with words separated by a space:

"eggs lovely spam spam bar bar bar bar bar baz baz baz baz baz baz eggs
bar baz baz baz baz baz eggs spam spam"


2.     You want to make a list of all the different words and how many
times each one occurs, then display the alphabetized list.

Just think how you would do that in an algorithm based language like
java.  That is a LOT of work.  Now look at a ruby way:

s = "eggs lovely spam spam bar bar bar bar bar baz baz baz baz baz baz
eggs bar baz baz baz baz baz eggs spam spam".split(/[ ]/)

p s.inject(Hash.new(0)) {|h, e| h[e] += 1; h}.sort

Second example:

You are given an array of numbers as strings:  ["10.1", "7.4", "10.9",
"10.11", "10.10"]

If you do a standard sort, it turns into: ["10.1", "10.10", "10.11",
"10.9", "7.4"]

What you want is a numeric sort:  ["7.4", "10.1", "10.9",
"10.10","10.11"]

Extra credit if the sort allows for the addition of numeric bits.  E.g.
["10.1.5", "7.4.4", "10.9.3", "10.11.2", "10.10.3", "10.10.1"]

Ruby solution:

arr = ["10.1.5", "7.4.4", "10.9.3", "10.11.2", "10.10.3", "10.10.1"]
p arr.sort_by { |str| str.split('.').map { |x| x.to_i } }

=> ["7.4.4", "10.1.5", "10.9.3", "10.10.1", "10.10.3", "10.11.2"]
Robert K. (Guest)
on 2008-10-22 18:41
(Received via mailing list)
2008/10/22 Nit K. <removed_email_address@domain.invalid>:
> The only thing I can put down, that i have gleaned, is the usage of
> procs/blocks, i.e. allowing the user to pass in blocks/yielding a value
> or self. I liked the chapter on Ruby Tk in pickaxe (since I am hoping to
> write a rubyish wrapper to ncurses).
>
> Surely there is more to the ruby way than blocks/procs/lambda. Would
> really appreciate pointers.

I cannot come up with a clear cut definition, but simplicity is
certainly a part of it. Here's another example. If you want to group
multiple values and use them as Hash key you can do

MyKey = Struct.new :name, :age, :gender

or you can do

class MyKey
  attr_accessor :name, :age, :gender

  def eql? other
    name.eql? other.name and
    age.eql? other.age and
    gender.eql? other.gender
  end

  alias == eql?

  def hash
    name.hash ^ age.hash ^ gender.hash
  end
end

or even

class MyKey
  def name; @name end
  def name=(x) @name = x end
  def age; @age end
  def age=(x) @age = x end
  def gender; @gender end
  def gender=(x) @gender = x end

  def initialize(name, age, gender)
    self.name = name
    self.age = age
    self.gender = gender
  end

  def eql? other
    name.eql? other.name and
    age.eql? other.age and
    gender.eql? other.gender
  end

  alias == eql?

  def hash
    name.hash ^ age.hash ^ gender.hash
  end
end

Kind regards

robert
R. K. (Guest)
on 2008-10-22 19:07
Thanks a lot for all the tips.

Let's say I am writing base classes or a library to be used by others. I
am wondering that there must be things ruby provides that give a simpler
or more elegant interface to the users. Blocks was an example i gave
earlier. Yielding values in a loop was an example. I am beginning to
understand yielding self or just yield, too.

Perhaps one could give an example of Modules as in the Enumerable
module. If your class defines an "each" (iirc) then you automatically
get many methods for free.

Maybe the correct approach for me is to compare how a library is
implemented in another language (or non ruby way) versus a good ruby
implementation. e,g,
1. compare getoptlong to optparse
2. compare sqlite wrapper in java vs ruby ?
Thomas S. (Guest)
on 2008-10-22 23:18
(Received via mailing list)
On Oct 22, 9:37 am, Nit K. <removed_email_address@domain.invalid> wrote:
> Over the last month I have been reading a lot of blogs, searching, going
> through source code of some apps and my pickaxe. I am still unable to
> clearly understand what all "the ruby way" means.

  1. However something is done in Ruby.
  2. Whatever Matz says it is.

For #1 that usually translates it into concise code. For #2 that
usually translates into concise words.
R. K. (Guest)
on 2008-10-23 07:20
Thomas S. wrote:
> On Oct 22, 9:37�am, Nit K. <removed_email_address@domain.invalid> wrote:
>> Over the last month I have been reading a lot of blogs, searching, going
>> through source code of some apps and my pickaxe. I am still unable to
>> clearly understand what all "the ruby way" means.
>
>   1. However something is done in Ruby.
>   2. Whatever Matz says it is.
>
> For #1 that usually translates it into concise code. For #2 that
> usually translates into concise words.

So my code and the user of the library should have the least code to
write, and of course it has to be simple and clear, while at the same
time the simplicity should not rob the user of power/customizability
etc.
Shall keep the above in mind. (sorry for not being as concise as you ;-)
)
Robert K. (Guest)
on 2008-10-23 11:23
(Received via mailing list)
2008/10/23 Nit K. <removed_email_address@domain.invalid>:

> So my code and the user of the library should have the least code to
> write, and of course it has to be simple and clear, while at the same
> time the simplicity should not rob the user of power/customizability
> etc.
> Shall keep the above in mind. (sorry for not being as concise as you ;-)
> )

I'd add that simplicity for the user of the lib is more important than
simplicity for the implementer of the lib.

Cheers

robert
Robert D. (Guest)
on 2008-10-23 13:35
(Received via mailing list)
On Thu, Oct 23, 2008 at 9:20 AM, Robert K.
<removed_email_address@domain.invalid> wrote:
> simplicity for the implementer of the lib.
And it might be one of the rare occasion where performance counts.

As an example I once submitted an *ugly* patch using each_with_index
instead of inject to Factes which made a
method which was just elegant ugly, but it gained 10% of performance.
The maintainer judged that my code was still readable enough to accept
my patch because the method might be heavily used.No one would ever
consider changing
this method in an application unless performance was not good enough.

This just to underline how important Robert's point is.
Robert
--
C'est véritablement utile puisque c'est joli.

Antoine de Saint Exupéry
Brian C. (Guest)
on 2008-10-23 13:35
Nit K. wrote:
> Maybe the correct approach for me is to compare how a library is
> implemented in another language (or non ruby way) versus a good ruby
> implementation. e,g,
> 1. compare getoptlong to optparse

Ruby has both :-) That is, you will find both getoptlong.rb and
optparse.rb in the standard library. The first tries to follow the C
API, while the second tries to be more native-rubyish.

However even optparse.rb is rather verbose to use, and there are other
competitors in this space (e.g. commandline, trollop). You choose the
one which suits you best.

It just goes to show that even the ruby core language designers don't
always have the deepest insights into "the best" API at the time when
they first write one. More succinct and powerful APIs often develop
through new insights from users of the older ones.

I'd say you'll develop a sense for this over time. But don't worry about
it too much. Even within the core library things aren't consistent. For
example, some objects use capitalised symbols as option hash keys:

    WEBrick::HTTPServer.new(:BindAddress => "127.0.0.1", :Port => 1234)

some use lower-case symbols with underscores:

    DRb.start_service("drb://127.0.0.1:1234", nil, :load_limit =>
1_000_000)

and some use strings:

   Net::Telnet.new("Host" => "1.2.3.4")

You just have to learn the conventions for each library you use.
R. K. (Guest)
on 2008-10-23 15:37
Brian C. wrote:

>> 1. compare getoptlong to optparse
>
> Ruby has both :-) That is, you will find both getoptlong.rb and
> optparse.rb in the standard library.

I *did* mean ruby's getoptlong.

> However even optparse.rb is rather verbose to use, and there are other
> competitors in this space (e.g. commandline, trollop). You choose the
> one which suits you best.
>

That's a great example. I am aware of various command-line parsers, each
making some aspect of the problem easier.

> It just goes to show that even the ruby core language designers don't
> always have the deepest insights into "the best" API at the time when
> they first write one. More succinct and powerful APIs often develop
> through new insights from users of the older ones.
>
Today I was glancing at some of the ORM's: sequel, datamapper and seeing
the same thing you mention.

> I'd say you'll develop a sense for this over time. But don't worry about
> it too much.

I worked on Java for several years (my first OOPL), and became pretty
decent in OOAD with Java. But read many many books for that, and
eyeballed a lot of code, too. I am hoping to shorten that process with
ruby. Thanks for the pointers. Thanks also to all the bloggers who are
sharing their experiences and insights.
This topic is locked and can not be replied to.