What makes a "good" Ruby extension?

So I’m reading the “Comparing Gui Toolkits” wiki page
(http://www.rubygarden.org/ruby?ComparingGuiToolkits) and I notice that
the author characterizes one of the Ruby interfaces as “Perl-like” and
another as “immature.” As someone who’s been busy beavering away at his
own Ruby interface to an existing C library for some months now, I’m wondering,
just what makes a “good” Ruby interface? (After all, I don’t want to
embarrass myself by offering a bad one to the Ruby community :slight_smile:

Going by my own standards for software, I’m assuming that a good Ruby
interface should be

  1. usable, that is, not buggy, reasonably efficient, and predictable
  2. complete, that is, provides a complete interface to whatever it’s
    interfacing with
  3. documented, (no point having an interface that you can’t figure out) and
  4. supported, so you have some hope of getting bugs fixed, etc.

Does this sound right? What else is important? I’m especially intrigued
by the notion of a “Perl-like” binding vs. a
"Ruby-like" binding. What makes an interface “Ruby-like?”

basic answer: use of OO and code blocks. also shy away from special
globals, i.e. ${puncuation mark}.

by the way what are you interfacing too if you don’t mind me asking?

···

On Tue, 2002-08-20 at 16:31, Tim Hunter wrote:

Does this sound right? What else is important? I’m especially intrigued
by the notion of a “Perl-like” binding vs. a
“Ruby-like” binding. What makes an interface “Ruby-like?”


~transami

I don’t really know but I guess it could be being truly OO, allowing the
usage of blocks…

···

On Wed, Aug 21, 2002 at 07:31:05AM +0900, Tim Hunter wrote:

Does this sound right? What else is important? I’m especially intrigued
by the notion of a “Perl-like” binding vs. a
“Ruby-like” binding. What makes an interface “Ruby-like?”


_ _

__ __ | | ___ _ __ ___ __ _ _ __
'_ \ / | __/ __| '_ _ \ / ` | ’ \
) | (| | |
__ \ | | | | | (| | | | |
.__/ _,
|_|/| || ||_,|| |_|
Running Debian GNU/Linux Sid (unstable)
batsman dot geo at yahoo dot com

Computers are like air conditioners. Both stop working, if you open windows.
– Adam Heath

So I’m reading the “Comparing Gui Toolkits” wiki page
(http://www.rubygarden.org/ruby?ComparingGuiToolkits) and I notice that
the author characterizes one of the Ruby interfaces as “Perl-like” and
another as “immature.” As someone who’s been busy beavering away at his
own Ruby interface to an existing C library for some months now, I’m
wondering,
just what makes a “good” Ruby interface? (After all, I don’t want to
embarrass myself by offering a bad one to the Ruby community :slight_smile:

Well, if it’s on the Internet, it must be true. :slight_smile:

Going by my own standards for software, I’m assuming that a good Ruby
interface should be

  1. usable, that is, not buggy, reasonably efficient, and predictable
  2. complete, that is, provides a complete interface to whatever it’s
    interfacing with
  3. documented, (no point having an interface that you can’t figure out)
    and
  4. supported, so you have some hope of getting bugs fixed, etc.

Does this sound right? What else is important? I’m especially intrigued
by the notion of a “Perl-like” binding vs. a
“Ruby-like” binding. What makes an interface “Ruby-like?”

An interesting question. I’ll offer an opinion or two.

An API should take advantage of the things Ruby does
well – the things that make it Ruby – WHEN this is
appropriate.

Most of my examples here will deal with only the API
that is exposed to the user… if we got into coding
style, I could probably come up with even more.

Examples:

  1. Use class variables and methods in the API as needed.
  2. If you have a collection or list, consider giving it
    an iterator. Consider more than one kind, e.g. with_index.
  3. If you do an open/close or start/stop, consider using
    an “non-iterating” iterator for this. Examples are
    File.open, Mutex#synchronize, and Dir.chdir (the new one).
  4. If a method takes an object, consider whether it might
    be meaningful for it to take a block instead or in addition.
  5. Make use of nil where appropriate.
  6. Make use of the existing modules, especially Enumerable
    and Comparable, where appropriate.
  7. Use symbols if/when appropriate. Sometimes they make a
    good substitute for string constants or arbitrary integer
    values.
  8. Create meaningful exception classes as needed.
  9. Provide objects with to_a, to_s, to_i, etc., as needed.
  10. Give objects good ‘inspect’ methods.
  11. Remember that often it matters less what class a thing
    is than what methods it responds to. One of my favorite
    examples: Suppose your method appends each thing in a collection
    onto an object supplied by the caller (obj << item). This
    will work whether the ‘obj’ passed in is a string, array, or
    file (since you can meaningfully append onto any of them
    with a << operation).
  12. As regards #9, we also have to_ary, to_str, and (I think?)
    to_int.
  13. If you define some kind of numeric class, make sure it can
    be coerced as needed.
  14. Subclass as needed. This is just good OO besides good Ruby.
    Subclass your own classes and/or the predefined ones.
  15. Use hashes when convenient/appropriate. They’re powerful.
  16. As regards #11 above, remember to hide implementation
    details to de-couple with the caller. If a hash has numeric
    keys, it resembles an array (if you only use and =). Or
    it could even be your own special data structure.
  17. Use readers/writers/accessors when appropriate.
  18. Don’t be afraid to add to existing classes/modules when
    it makes sense to do so. That’s why they’re open.
  19. An occasional alias can help an API. (Some people don’t
    like this, but I do.) In the core, indexes and indices are the
    same for Arrays. For Strings, size and length are the same. Etc.
  20. When an object needs to act “almost” like another object,
    minus some functionality, consider delegation (delegate.rb).
  21. When appropriate, make use of the ? and ! suffixes in the
    standard way.
  22. When appropriate, use default values for parameters.
  23. Use Struct when it will help you. This will often prevent
    indexing into arrays with arbitrary indices.
  24. Be platform independent when you can. There are things like
    File::SEPARATOR (?) that help with this.
  25. Consider whether it makes sense to marshal an object. If so,
    try to write the class so that it remains marshallable.
  26. Overload operators as needed. That’s why we have the capability.
  27. In your API, try to use terminology consistent with the rest
    of the Ruby world. (Sigh. I don’t always do this either.)
  28. It’s a good idea (though I don’t practice what I preach) to
    try to support non-US and/or non-ASCII users to the extent you can.
  29. Use singleton methods for objects where it makes sense. For
    example: In a GUI, you might allow the user to attach a method
    directly to a Button object.
  30. Worry about performance last, and only when needed. (Some may
    flame me for this.) If you really need great performance, write
    a C extension. Otherwise stay in Ruby. Conceivably you might even
    offer options for some pieces.
  31. Allow users to represent their data in creative ways. If your
    “foo” method takes an array, see if it makes sense for it to take
    a hash also (or any object that knows and =). If it takes a
    string, see if a regex makes sense. Et cetera…
  32. Make use of method_missing where appropriate. At the very
    least, catch undefined methods that may be generated/called at
    runtime. Hmm, unneeded? Ruby does it for you…
  33. If you add to a class or module, go to the highest meaningful
    level of generality. Don’t add to File if it belongs in IO. Don’t
    add to a dozen classes if it belongs in Enumerable.
  34. Consider making objects thread-safe when appropriate, since
    Ruby has thread capabilities.
  35. Consider a “hybrid iterator” (if I may call it that) which
    returns a list when called without a block.
  36. Don’t forget that Ruby is dynamic. I’m not sure what I mean
    by saying this, but don’t forget it. :slight_smile:
  37. Avoid camelCase in your API. Some like it, some use it, but
    it isn’t done in the core, I think. Likewise avoid using capitalized
    method names (unless perhaps they perform data conversion, like
    Integer). Underscores are generally accepted (i.e., used in the core).
  38. Don’t force users to use global variables or the Perl-like
    “swearing” variables ($!, $_, etc.).
  39. Don’t forget there is such a thing as a Range class. Allow
    users to pass in ranges where it makes sense.
  40. Allow arbitrary numbers of parameters where it makes sense.
  41. Make error messages and exceptions as meaningful as possible.
    You can include data in them when it helps.
  42. Use Rubylike ways of dealing with data. For example, don’t
    represent a time as an array of numbers or a string, but as a
    Time object. If you need to convert to/from the other representations,
    provide a way to do so.

Oh, yeah. And wear sunscreen.

Hal Fulton

···

----- Original Message -----
From: “Tim Hunter” cyclists@nc.rr.com
Newsgroups: comp.lang.ruby
To: “ruby-talk ML” ruby-talk@ruby-lang.org
Sent: Tuesday, August 20, 2002 5:31 PM
Subject: What makes a “good” Ruby extension?

Tim Hunter wrote:

So I’m reading the “Comparing Gui Toolkits” wiki page
(http://www.rubygarden.org/ruby?ComparingGuiToolkits) and I notice that
the author characterizes one of the Ruby interfaces as “Perl-like” and
another as “immature.” As someone who’s been busy beavering away at his
own Ruby interface to an existing C library for some months now, I’m wondering,
just what makes a “good” Ruby interface? (After all, I don’t want to
embarrass myself by offering a bad one to the Ruby community :slight_smile:

I think this is a question that a lot of Ruby programmers struggle with,
especially if they’ve come to Ruby after a long history with some other
programming language. Despite efforts like this:

http://www.rubygarden.org/ruby?RubyStyleGuide

there’s not really a “checklist” out there to compare your work to (and
I don’t think anyone wants that anyways).

Perhaps your best bet, then, is to study Ruby code that others have
pointed to as exemplary of “The Ruby Way”. That certainly includes
looking at the sources from Ruby’s standard library, but a lot of code
from the Ruby community falls into this category as well. For example,
many people have pointed to Sean Russell’s REXML library:

http://www.germane-software.com/software/rexml

as a very intuitive (read: “Ruby-like”) interface. I hope others reading
this thread might throw in their $0.02 about other good examples (for my
benefit :wink:

Going by my own standards for software, I’m assuming that a good Ruby interface should be:

  1. usable, that is, not buggy, reasonably efficient, and predictable
  2. complete, that is, provides a complete interface to whatever it’s interfacing with
  3. documented, (no point having an interface that you can’t figure out) and
  4. supported, so you have some hope of getting bugs fixed, etc.

Well, yes. I guess those things are important too :wink:

Tim Hunter wrote:

So I’m reading the “Comparing Gui Toolkits” wiki page
(http://www.rubygarden.org/ruby?ComparingGuiToolkits) and I notice that
the author characterizes one of the Ruby interfaces as “Perl-like” and
another as “immature.” As someone who’s been busy beavering away at his
own Ruby interface to an existing C library for some months now, I’m
wondering,
just what makes a “good” Ruby interface? (After all, I don’t want to
embarrass myself by offering a bad one to the Ruby community :slight_smile:

I think this is a question that a lot of Ruby programmers struggle with,
especially if they’ve come to Ruby after a long history with some other
programming language. Despite efforts like this:

http://www.rubygarden.org/ruby?RubyStyleGuide

there’s not really a “checklist” out there to compare your work to (and
I don’t think anyone wants that anyways).

Tim - what Lyle says is true. There’s no one right way to do things.

And while I claim my list has some good ideas, it’s not definitive
and it shouldn’t be viewed as a checklist.

And as for being embarrassed over a “bad” interface… don’t worry
about it! Nothing is perfect the first time. That’s why we have
version numbers. Any contribution is welcome, and a bad interface
is better than no interface at all. Usually. :slight_smile:

Perhaps your best bet, then, is to study Ruby code that others have
pointed to as exemplary of “The Ruby Way”. That certainly includes
looking at the sources from Ruby’s standard library, but a lot of code
from the Ruby community falls into this category as well. For example,
many people have pointed to Sean Russell’s REXML library:

http://www.germane-software.com/software/rexml

as a very intuitive (read: “Ruby-like”) interface. I hope others reading
this thread might throw in their $0.02 about other good examples (for my
benefit :wink:

Yes, from the little I’ve seen of REXML, I like it. Hard to compare, since
I don’t use XML much.

Some other good coders (IMO): Dave Thomas, Guy Decoux, obviously Matz,
David Alan Black, Michael Neumann. There are others.

Study the Ruby core classes and methods (and net stuff) and the libraries.
The API I mean, not the code. Although the code is good too. :slight_smile:

I guess NOW that is my $0.02 worth.

Hal

···

----- Original Message -----
From: “Lyle Johnson” lyle@users.sourceforge.net
Newsgroups: comp.lang.ruby
To: “ruby-talk ML” ruby-talk@ruby-lang.org
Sent: Tuesday, August 20, 2002 6:51 PM
Subject: Re: What makes a “good” Ruby extension?

I think this is a question that a lot of Ruby programmers struggle
with,
especially if they’ve come to Ruby after a long history with some
other
programming language. Despite efforts like this:

http://www.rubygarden.org/ruby?RubyStyleGuide

there’s not really a “checklist” out there to compare your work to
(and
I don’t think anyone wants that anyways).

Maybe I’m old and set in my ways, but I just read that page and while
good, I’m having a little trouble with some aspects of it.

In the “use iterators” section, it says …

Even Better

Use iterators and higher order functions. These were invented in
LISP, which was around before Algol introduced while and for loops.
Therefore these are very old ways, and have worked fine for the last
50 years!

PROMPTS = [“First Name”, “Last Name”, “Phone”]
first_name,last_name,phone = PROMPTS.map { |prompt | prompt_and_read(
prompt ) }

I’m sorry, I’m perfectly capable of grokkin that, but there is no way
(to me) that that example reads better than the initial:

first_name = prompt_and_read “First name”
last_name = prompt_and_read “Last name”
phone = prompt_and_read “Phone”

The iterator example reads like perl to me, which in and of itself
isn’t bad, but it just seems like using a ruby construct for the sake
of using a ruby construct.

Thoughts?

···

Perhaps your best bet, then, is to study Ruby code that others
have
pointed to as exemplary of “The Ruby Way”. That certainly includes
looking at the sources from Ruby’s standard library, but a lot of
code
from the Ruby community falls into this category as well. For
example,
many people have pointed to Sean Russell’s REXML library:

http://www.germane-software.com/software/rexml

as a very intuitive (read: “Ruby-like”) interface. I hope others
reading
this thread might throw in their $0.02 about other good examples
(for my
benefit :wink:

Going by my own standards for software, I’m assuming that a good
Ruby interface should be:

  1. usable, that is, not buggy, reasonably efficient, and
    predictable
  2. complete, that is, provides a complete interface to whatever
    it’s interfacing with
  3. documented, (no point having an interface that you can’t
    figure out) and
  4. supported, so you have some hope of getting bugs fixed, etc.

Well, yes. I guess those things are important too :wink:

=====

Use your computer to help find a cure for cancer: http://members.ud.com/projects/cancer/

Yahoo IM: michael_s_campbell


Do You Yahoo!?
HotJobs - Search Thousands of New Jobs
http://www.hotjobs.com

So I’m reading Hal’s 42-item list and in my head it sounds like
this: “Uh-huh. Did that. Okay. Oops. Got it covered. Oops. Oops. Okay.
Oops…”

With all this good advice I’ll be able to polish my extension to a high
gloss! Thanks, everybody!

P.S. In the “real” (a.k.a. corporate) world, this kind of advice would cost
$2,000/day, take two days to present, and come bound in a leather folder
with my name embossed in gold on the cover.

···

On Tue, 20 Aug 2002 22:26:34 -0400, Hal E. Fulton wrote:

----- Original Message -----
From: “Tim Hunter” cyclists@nc.rr.com Newsgroups: comp.lang.ruby To:
“ruby-talk ML” ruby-talk@ruby-lang.org Sent: Tuesday, August 20, 2002
5:31 PM Subject: What makes a “good” Ruby extension?

An interesting question. I’ll offer an opinion or two.

An API should take advantage of the things Ruby does well – the things
that make it Ruby – WHEN this is appropriate.

Most of my examples here will deal with only the API that is exposed to
the user… if we got into coding style, I could probably come up with
even more.

Examples:

  1. Use class variables and methods in the API as needed. 2. If you have
    a collection or list, consider giving it an iterator. Consider more than
    one kind, e.g. with_index. 3. If you do an open/close or start/stop,
    consider using an “non-iterating” iterator for this. Examples are
    File.open, Mutex#synchronize, and Dir.chdir (the new one). 4. If a
    method takes an object, consider whether it might be meaningful for it
    to take a block instead or in addition. 5. Make use of nil where
    appropriate. 6. Make use of the existing modules, especially Enumerable
    and Comparable, where appropriate.
  2. Use symbols if/when appropriate. Sometimes they make a good
    substitute for string constants or arbitrary integer values. 8. Create
    meaningful exception classes as needed. 9. Provide objects with to_a,
    to_s, to_i, etc., as needed. 10. Give objects good ‘inspect’ methods.
  3. Remember that often it matters less what class a thing is than what
    methods it responds to. One of my favorite examples: Suppose your method
    appends each thing in a collection onto an object supplied by the caller
    (obj << item). This will work whether the ‘obj’ passed in is a string,
    array, or file (since you can meaningfully append onto any of them with
    a << operation).
  4. As regards #9, we also have to_ary, to_str, and (I think?) to_int.
  5. If you define some kind of numeric class, make sure it can be
    coerced as needed.
  6. Subclass as needed. This is just good OO besides good Ruby. Subclass
    your own classes and/or the predefined ones. 15. Use hashes when
    convenient/appropriate. They’re powerful. 16. As regards #11 above,
    remember to hide implementation details to de-couple with the caller. If
    a hash has numeric keys, it resembles an array (if you only use and
    =). Or it could even be your own special data structure. 17. Use
    readers/writers/accessors when appropriate. 18. Don’t be afraid to add
    to existing classes/modules when it makes sense to do so. That’s why
    they’re open. 19. An occasional alias can help an API. (Some people
    don’t like this, but I do.) In the core, indexes and indices are the
    same for Arrays. For Strings, size and length are the same. Etc. 20.
    When an object needs to act “almost” like another object, minus some
    functionality, consider delegation (delegate.rb). 21. When appropriate,
    make use of the ? and ! suffixes in the standard way. 22. When
    appropriate, use default values for parameters. 23. Use Struct when it
    will help you. This will often prevent indexing into arrays with
    arbitrary indices. 24. Be platform independent when you can. There are
    things like File::SEPARATOR (?) that help with this. 25. Consider
    whether it makes sense to marshal an object. If so, try to write the
    class so that it remains marshallable. 26. Overload operators as needed.
    That’s why we have the capability. 27. In your API, try to use
    terminology consistent with the rest of the Ruby world. (Sigh. I don’t
    always do this either.) 28. It’s a good idea (though I don’t practice
    what I preach) to try to support non-US and/or non-ASCII users to the
    extent you can. 29. Use singleton methods for objects where it makes
    sense. For example: In a GUI, you might allow the user to attach a
    method directly to a Button object.
  7. Worry about performance last, and only when needed. (Some may flame
    me for this.) If you really need great performance, write a C extension.
    Otherwise stay in Ruby. Conceivably you might even offer options for
    some pieces.
  8. Allow users to represent their data in creative ways. If your “foo”
    method takes an array, see if it makes sense for it to take a hash also
    (or any object that knows and =). If it takes a string, see if a
    regex makes sense. Et cetera… 32. Make use of method_missing where
    appropriate. At the very least, catch undefined methods that may be
    generated/called at runtime. Hmm, unneeded? Ruby does it for you… 33.
    If you add to a class or module, go to the highest meaningful level of
    generality. Don’t add to File if it belongs in IO. Don’t add to a dozen
    classes if it belongs in Enumerable. 34. Consider making objects
    thread-safe when appropriate, since Ruby has thread capabilities. 35.
    Consider a “hybrid iterator” (if I may call it that) which returns a
    list when called without a block. 36. Don’t forget that Ruby is dynamic.
    I’m not sure what I mean by saying this, but don’t forget it. :slight_smile: 37.
    Avoid camelCase in your API. Some like it, some use it, but it isn’t
    done in the core, I think. Likewise avoid using capitalized method names
    (unless perhaps they perform data conversion, like Integer). Underscores
    are generally accepted (i.e., used in the core). 38. Don’t force users
    to use global variables or the Perl-like “swearing” variables ($!, $_,
    etc.).
  9. Don’t forget there is such a thing as a Range class. Allow users to
    pass in ranges where it makes sense. 40. Allow arbitrary numbers of
    parameters where it makes sense. 41. Make error messages and exceptions
    as meaningful as possible. You can include data in them when it helps.
  10. Use Rubylike ways of dealing with data. For example, don’t represent
    a time as an array of numbers or a string, but as a Time object. If you
    need to convert to/from the other representations, provide a way to do
    so.

Oh, yeah. And wear sunscreen.

Hal Fulton

Maybe this is a feature, but on my ruby -v ruby 1.7.2 (2002-06-29)
[i386-mswin32], running from cmd.exe on a w2k system:

D:\Fuji>ruby -e “print File::SEPARATOR”
/

Looks a bit odd to me.

···

On Wed, Aug 21, 2002, Hal E. Fulton wrote:

[snip]
24. Be platform independent when you can. There are things like
File::SEPARATOR (?) that help with this.


Pierre Baillet
Support the Debian GNU/Linux Project (http://www.debian.org)

http://www.rubygarden.org/ruby?RubyStyleGuide

Maybe I’m old and set in my ways, but I just read that page and while
good, I’m having a little trouble with some aspects of it.

In the “use iterators” section, it says …

Even Better

Use iterators and higher order functions. These were invented in
LISP, which was around before Algol introduced while and for loops.
Therefore these are very old ways, and have worked fine for the last 50
years!

PROMPTS = [“First Name”, “Last Name”, “Phone”]
first_name,last_name,phone = PROMPTS.map { |prompt | prompt_and_read(
prompt ) }

I’m sorry, I’m perfectly capable of grokkin that, but there is no way
(to me) that that example reads better than the initial:

first_name = prompt_and_read “First name”
last_name = prompt_and_read “Last name”
phone = prompt_and_read “Phone”

The iterator example reads like perl to me, which in and of itself isn’t
bad, but it just seems like using a ruby construct for the sake of using
a ruby construct.

Thoughts?

I quite agree. The original expresses the intention much more clearly. I
love parallel assignment and map, but this is not a good use of them.

Gavin

PROMPTS = [“First Name”, “Last Name”, “Phone”]
first_name,last_name,phone = PROMPTS.map { |prompt | prompt_and_read(
prompt ) }

I’m sorry, I’m perfectly capable of grokkin that, but there is no way
(to me) that that example reads better than the initial:

first_name = prompt_and_read “First name”
last_name = prompt_and_read “Last name”
phone = prompt_and_read “Phone”

The iterator example reads like perl to me, which in and of itself
isn’t bad, but it just seems like using a ruby construct for the sake
of using a ruby construct.

I’m new to Ruby (so apologies for sounding ignorant) but doesn’t the
Ruby example, also show how you might go about doing Internationalization.

Yes it makes it less clear, but it means that it becomes a simple case
of swapping that array PROMPTS for another with say French words and
leaving the rest of the code intact.

Where as the other example would leave you having to track down each of
the quoted strings and changing them.

my 2p

Rob

So I’m reading Hal’s 42-item list and in my head it sounds like
this: “Uh-huh. Did that. Okay. Oops. Got it covered. Oops. Oops. Okay.
Oops…”

Heh… it was something I’d been thinking about awhile.
Don’t take my advice too seriously. One person’s opinion.

With all this good advice I’ll be able to polish my extension to a high
gloss! Thanks, everybody!

What’s the extension, anyway?

P.S. In the “real” (a.k.a. corporate) world, this kind of advice would
cost
$2,000/day, take two days to present, and come bound in a leather folder
with my name embossed in gold on the cover.

Watch your mailbox for the leather folder… and the bill. :wink:

Cheers,
Hal

···

----- Original Message -----
From: “Tim Hunter” cyclists@nc.rr.com
Newsgroups: comp.lang.ruby
To: “ruby-talk ML” ruby-talk@ruby-lang.org
Sent: Wednesday, August 21, 2002 3:53 PM
Subject: Re: What makes a “good” Ruby extension?

[someone else (apologies to now anonymous author) wrote:]

PROMPTS = [“First Name”, “Last Name”, “Phone”]
first_name,last_name,phone = PROMPTS.map { |prompt | prompt_and_read(
prompt ) }
[snip]
first_name = prompt_and_read “First name”
last_name = prompt_and_read “Last name”
phone = prompt_and_read “Phone”
[snip[
The iterator example reads like perl to me, which in and of itself
isn’t bad, but it just seems like using a ruby construct for the sake
of using a ruby construct.

That the iterator example reads like Perl is not necessarily a Bad
Thing™. That the example shown doesn’t really demonstrate how this
makes your life better is. To me the problem is not the iterator so much
as the parallel assignment-- if the input was a list, let’s keep the
output as a list (or a hash)

I’m new to Ruby (so apologies for sounding ignorant) but doesn’t the
Ruby example, also show how you might go about doing
Internationalization.

To truly do internationalization you would probably want to build a class
that stored your various phrases and allowed you to set a global or class
variable to the language to be used, then whenever you need a string you
call a method of that class, which responds appropriately.

This way you can set up things like handling plurals or other grammatical
constructs. This is the function of the GNU gettext library, and the RAA
appears to have some similar stuff. Disclaimer: I’ve never used any of
gettext or the RAA modules-- I have only read about them. But thank you
for reminding me that it’s time to include this in an incipient
application I’m writing-- looks like I’ll do more than just reading soon.
:slight_smile:

Yes it makes it less clear, but it means that it becomes a simple case
of swapping that array PROMPTS for another with say French words and
leaving the rest of the code intact.

Where as the other example would leave you having to track down each of
the quoted strings and changing them.

Except that for the contrived example shown, neither of the above seem that
efficient (in terms of programmer brain and finger usage) to me.

Why not create a list of parameters and use it to build a hash, rather than
an enumerated set of locals?

PROMPTS = [“First Name”, “Last Name”, “Phone”]
hv = {}
PROMPTS.each{|p| hv[p] = prompt_and_read(p)}

Now I have a data structure that is still easy to use, but also
self-contained. What if I want to pass all the results here to another
routine for validation or processing? Whether in the first example or the
second I still have to now script:

validate_and_process(“First Name”, first_name)
validate_and_process(“Last Name”, last_name)
validate_and_process(“Phone”, phone)

That’s a lot of work compared to:

hv.each_key{|k| validate(k, hv[k])}

Or, if we write our validate_and_process method so it can accept a hash:

validate_and_process(hv)

This way if I need to add in elements, doing so requires that I add those
elements in one place only (although my example validate_and_process
method might need to add code to handle new additions, that’s actual new
program logic, not just more code that all does the same thing).

-michael

···

On Wednesday 21 August 2002 05:52, Rob McG wrote:

++++++++++++++++++++++++++++++++++++++++++
Michael C. Libby x@ichimunki.com
public key: http://www.ichimunki.com/public_key.txt
web site: http://www.ichimunki.com
++++++++++++++++++++++++++++++++++++++++++

PROMPTS = [“First Name”, “Last Name”, “Phone”]
first_name,last_name,phone = PROMPTS.map { |prompt | prompt_and_read(
prompt ) }

I’m sorry, I’m perfectly capable of grokkin that, but there is no way
(to me) that that example reads better than the initial:

first_name = prompt_and_read “First name”
last_name = prompt_and_read “Last name”
phone = prompt_and_read “Phone”

The iterator example reads like perl to me, which in and of itself
isn’t bad, but it just seems like using a ruby construct for the sake
of using a ruby construct.

I’m new to Ruby (so apologies for sounding ignorant) but doesn’t the
Ruby example, also show how you might go about doing Internationalization.

Yes it makes it less clear, but it means that it becomes a simple case
of swapping that array PROMPTS for another with say French words and
leaving the rest of the code intact.

Where as the other example would leave you having to track down each of
the quoted strings and changing them.

my 2p

I see your point here and of course, you can contrive any number of situations
where “x” is better than “y”. I18N wasn’t however the context of the example
in this case.