[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Any solutions to Ruby's inconsistencies?

C. Dagnon

3/4/2009 4:03:00 PM

Ruby has definite positives over Java and even other scripting
languages, but many negatives too. One negative is the inconsistency of
how rules seem to be applied in the language and accompanying toolsets.
Here are a few that have bitten me:


1. I almost immediately got started with Ruby on Rails and loved the
idea of partials, but then I found that the ||= idiom doesn't work on
partials' parameters.

<% my_param_a ||= 1 # Errors out
my_param_a = my_param_a ? my_param_a : 1 # works
-%>

That seemed odd as I thought both were equivalent, and it broke some of
the trust I had for Ruby. Not as much as early Rails' use of 2 separate
variables for RAILS_ENV, but...


2. Then when using blocks to process an array I tried to use another
Ruby control structure:

arr=[1,2,3,4]
arr2 = arr.collect{|ii| return 0 if ii == 3; ii+1}
# result: LocalJumpError: unexpected return

That also caught me off guard - I need the block to return a value, to
evaluate to a value - but suddenly I'm told that 'return' doesn't mean
what I think it means? At least not inside a block (or Proc.new)...


3. Originally I was taught that symbols were the salvation of memory and
key problems - and they certainly sounded like it. Up until the point a
few days later when one (Rails?) map used Symbols and another used
Strings. Ouch.
Without any explicit typing abilities in the language (optional or
otherwise?) it seems like the only solution is to return to basic string
matches:
regex = Regexp.compile("^#{matcher.to_s}$", Regexp::IGNORECASE)
key = map.keys.find{ |key| key.to_s =~ regex }
Yuck.


4. And what's up with Ruby incorrectly naming their Map 'Hash'? Or is
my C.S. idea of a Hash too limited? Granted in Java they have HashMap,
but if you enter one value and get a second one out it is a Map,
regardless of how the keys are stored. A 'Hash' would instead be a type
of set.


Please let me know how I can supplement my possibly deficient Ruby
education :) Relevant discussions or sections of "The Ruby Way"
appreciated!

-Chris
--
Posted via http://www.ruby-....

28 Answers

WilliamJames

3/4/2009 4:39:00 PM

0

C. Dagnon wrote:

> Ruby has definite positives over Java and even other scripting
> languages, but many negatives too. One negative is the inconsistency
> of how rules seem to be applied in the language and accompanying
> toolsets. Here are a few that have bitten me:
>
>
> 1. I almost immediately got started with Ruby on Rails and loved the
> idea of partials, but then I found that the ||= idiom doesn't work on
> partials' parameters.
>
> <% my_param_a ||= 1 # Errors out
> my_param_a = my_param_a ? my_param_a : 1 # works
> -%>
>
> That seemed odd as I thought both were equivalent, and it broke some
> of the trust I had for Ruby.


Rails isn't Ruby. If I wrote a program in Ruby that erased every file
on your hard-drive, would you blame Ruby or me?


> Not as much as early Rails' use of 2
> separate variables for RAILS_ENV, but...
>
>
> 2. Then when using blocks to process an array I tried to use another
> Ruby control structure:
>
> arr=[1,2,3,4]
> arr2 = arr.collect{|ii| return 0 if ii == 3; ii+1}

This makes no sense. Correct:

[1,2,3,4].map{|n| if 3==n; 0 else n+1 end}
==>[2, 3, 0, 5]
[1,2,3,4].map{|n| 3==n ? 0 : n+1 }
==>[2, 3, 0, 5]


> # result: LocalJumpError: unexpected return
>
> That also caught me off guard - I need the block to return a value, to
> evaluate to a value - but suddenly I'm told that 'return' doesn't mean
> what I think it means? At least not inside a block (or Proc.new)...
>
>
> 3. Originally I was taught that symbols were the salvation of memory
> and key problems - and they certainly sounded like it. Up until the
> point a few days later when one (Rails?)

Rails is not Ruby. Rails could be be the worst piece of crap in the
universe and it still wouldn't be Ruby's fault.


> map used Symbols and another
> used Strings. Ouch.
> Without any explicit typing abilities in the language (optional or
> otherwise?) it seems like the only solution is to return to basic
> string matches:
> regex = Regexp.compile("^#{matcher.to_s}$", Regexp::IGNORECASE)

Horrible.

sym = :foo
==>:foo
"can FOO be found?"[ / #{ sym } /i ]
==>" FOO "



> key = map.keys.find{ |key| key.to_s =~ regex }
> Yuck.
>
>
> 4. And what's up with Ruby incorrectly naming their Map 'Hash'?

You beg the question. You must be very ignorant of "scripting"
languages. Hash is short for Hash Table, what is called in Awk
an associative array.

> Or is
> my C.S. idea of a Hash too limited? Granted in Java they have
> HashMap, but if you enter one value and get a second one out it is a
> Map, regardless of how the keys are stored. A 'Hash' would instead
> be a type of set.

A hash is a number returned by a hash function. An item's hash is
used to determine in which bucket of the hash-table it is put.

>
>
> Please let me know how I can supplement my possibly deficient Ruby
> education :) Relevant discussions or sections of "The Ruby Way"
> appreciated!
>


Yossef Mendelssohn

3/4/2009 4:45:00 PM

0

On Mar 4, 10:02=A0am, "C. Dagnon" <c-soc-rubyfo...@dagnon.net> wrote:
> 3. Originally I was taught that symbols were the salvation of memory and
> key problems - and they certainly sounded like it. =A0Up until the point =
a
> few days later when one (Rails?) map used Symbols and another used
> Strings. =A0Ouch.
> =A0 =A0 Without any explicit typing abilities in the language (optional o=
r
> otherwise?) it seems like the only solution is to return to basic string
> matches:
> =A0 =A0 regex =3D Regexp.compile("^#{matcher.to_s}$", Regexp::IGNORECASE)
> =A0 =A0 key =3D map.keys.find{ |key| key.to_s =3D~ regex }
> Yuck.

There's been endless discussion and confusion about Symbols, Strings,
what they mean, what they should be used for, and their relation to
each other. Rails did not help with HashWithIndifferentAccess, though
I imagine they thought they would. But I don't want to start anything
like that up. I just want to point out that a lot of that code is
unnecessary and could just be:

key =3D map.keys.detect { |k| k.to_s.downcase =3D=3D
matcher.to_s.downcase }

Specifically, "#{something.to_s}" is not required because string
interpolation calls to_s on the object. And anyway, this example seems
confused with Symbol vs. String as well as case-insensitive matching.
If you want something like that, you write your own Hash (or Map)
subclass or find something someone else wrote. Maybe there's
HashWithReallyIndifferentAccess or HashThatJustKnowsWhatYouMean or
HashThatWillGiveYouTheValueOfSomeTangentionallyRelatedKey.

> 4. And what's up with Ruby incorrectly naming their Map 'Hash'?

This isn't only a Ruby thing. I'm used to it, but then again I came to
Ruby from Perl.

At least they're not called "dictionaries", right? Am I right?

>=A0Or is my C.S. idea of a Hash too limited? =A0Granted in Java they
> have HashMap, but if you enter one value and get a second one
> out it is a Map, regardless of how the keys are stored.

Hey, why aren't Arrays called Maps instead?

--
-yossef

James Coglan

3/4/2009 5:01:00 PM

0

[Note: parts of this message were removed to make it a legal post.]

>
>
> > Or is my C.S. idea of a Hash too limited? Granted in Java they
> > have HashMap, but if you enter one value and get a second one
> > out it is a Map, regardless of how the keys are stored.
>
> Hey, why aren't Arrays called Maps instead?



I've always found Java's naming of collections to be contrary to its idea of
OO in that it exposes implementation details, e.g. HashSet, LinkedHashSet
and TreeSet really ought to be called Set, OrderedSet and SortedSet to
reflect their intended use rather than their internal structure.

'Map' is unfortunately too vague a term and could be used to refer to
anything that maps a set of inputs to another set of outputs. You arguably
call arrays, lambdas, methods and even objects 'maps'. HashMap actually
isn't a bad name for this since it differentiates the data structure from
other mapping objects. I don't mind 'table' or 'hashtable'. 'Dictionary' is
a little restrictive in that it seems to imply string-only keys and seems to
relate to JavaScript-style objects rather than real hashtables. All said,
Hash isn't bad: it's an object that maps input to output by hashing the
input, which is all you need to know really.

Florian Gilcher

3/4/2009 5:02:00 PM

0


On Mar 4, 2009, at 5:02 PM, C. Dagnon wrote:

> Ruby has definite positives over Java and even other scripting
> languages, but many negatives too. One negative is the
> inconsistency of
> how rules seem to be applied in the language and accompanying
> toolsets.
> Here are a few that have bitten me:
>
>
> 1. I almost immediately got started with Ruby on Rails and loved the
> idea of partials, but then I found that the ||= idiom doesn't work on
> partials' parameters.
>
> <% my_param_a ||= 1 # Errors out
> my_param_a = my_param_a ? my_param_a : 1 # works
> -%>
>
> That seemed odd as I thought both were equivalent, and it broke some
> of
> the trust I had for Ruby. Not as much as early Rails' use of 2
> separate
> variables for RAILS_ENV, but...

What was the exact error? I don't know how ERB in Rails work, but
sometimes those constructs are method calls and not variables.

> 2. Then when using blocks to process an array I tried to use another
> Ruby control structure:
>
> arr=[1,2,3,4]
> arr2 = arr.collect{|ii| return 0 if ii == 3; ii+1}
> # result: LocalJumpError: unexpected return
>
> That also caught me off guard - I need the block to return a value, to
> evaluate to a value - but suddenly I'm told that 'return' doesn't mean
> what I think it means? At least not inside a block (or Proc.new)...

"return" in Ruby has a lexical meaning and can jump to the end of a
scope (the end of the method). In some contexts, that is not allowed.
Especially in the case of collect, that has to return an array that is
as large as the first one.

It is not inconsistent: it is just not Javas return. So the language
is right to tell you that it is not what you think it means: because
it ain't.
Don't use it unless you really want to jump.

I for my part find Ruby a rather consistent language. It's just that
the ruleset is not simple.

Regards,
Florian

--
Florian Gilcher

smtp: flo@andersground.net
jabber: Skade@jabber.ccc.de
gpg: 533148E2


Ken Bloom

3/4/2009 5:28:00 PM

0

On Wed, 04 Mar 2009 11:02:36 -0500, C. Dagnon wrote:

> Ruby has definite positives over Java and even other scripting
> languages, but many negatives too. One negative is the inconsistency of
> how rules seem to be applied in the language and accompanying toolsets.
> Here are a few that have bitten me:
>
>
> 1. I almost immediately got started with Ruby on Rails and loved the
> idea of partials, but then I found that the ||= idiom doesn't work on
> partials' parameters.
>
> <% my_param_a ||= 1 # Errors out
> my_param_a = my_param_a ? my_param_a : 1 # works
> -%>
>
> That seemed odd as I thought both were equivalent, and it broke some of
> the trust I had for Ruby. Not as much as early Rails' use of 2 separate
> variables for RAILS_ENV, but...

I don't use rails, and I don't know what a partial is, so I can't answer.
You probably better ask on a Rails list.

> 2. Then when using blocks to process an array I tried to use another
> Ruby control structure:
>
> arr=[1,2,3,4]
> arr2 = arr.collect{|ii| return 0 if ii == 3; ii+1} # result:
> LocalJumpError: unexpected return
>
> That also caught me off guard - I need the block to return a value, to
> evaluate to a value - but suddenly I'm told that 'return' doesn't mean
> what I think it means? At least not inside a block (or Proc.new)...

A block (except when it's a lambda) is meant to be looked at as though
it's a control structure in the function, the same as if it were an
ordinary loop. So the idea of `return` is to return from the function.
Use `next` to return a value early from the block.

arr2 = arr.collect{|ii| next 0 if ii == 3; ii+1}


> 4. And what's up with Ruby incorrectly naming their Map 'Hash'? Or is
> my C.S. idea of a Hash too limited? Granted in Java they have HashMap,
> but if you enter one value and get a second one out it is a Map,
> regardless of how the keys are stored. A 'Hash' would instead be a type
> of set.

Perhaps they should, but it would be a pain to change it now.

--Ken


--
Chanoch (Ken) Bloom. PhD candidate. Linguistic Cognition Laboratory.
Department of Computer Science. Illinois Institute of Technology.
http://www.iit.edu...

Ken Bloom

3/4/2009 5:33:00 PM

0

On Wed, 04 Mar 2009 12:01:27 -0500, James Coglan wrote:

> [Note: parts of this message were removed to make it a legal post.]
>
>
>>
>> > Or is my C.S. idea of a Hash too limited? Granted in Java they have
>> > HashMap, but if you enter one value and get a second one out it is a
>> > Map, regardless of how the keys are stored.
>>
>> Hey, why aren't Arrays called Maps instead?
>
>
>
> I've always found Java's naming of collections to be contrary to its
> idea of OO in that it exposes implementation details, e.g. HashSet,
> LinkedHashSet and TreeSet really ought to be called Set, OrderedSet and
> SortedSet to reflect their intended use rather than their internal
> structure.

No, no, no. In Java, you have the interfaces Set, and SortedSet (no
OrderedSet, I suppose it would have exactly the same operations as a
Set), which don't define any operations, and AbstractSet which is a
helper class for people implementing sets.

Then you create instantiations HashSet, LinkedHashSet, TreeSet, which you
instantiate *knowing* what data you intend to use it for, and which
behind-the-scenes implementation has the best performance characteristics
for that data. (You *should* be allowed that choice, in general.) Then
you pass those around using the aforementioned implementation-agnostic
interfaces.

--
Chanoch (Ken) Bloom. PhD candidate. Linguistic Cognition Laboratory.
Department of Computer Science. Illinois Institute of Technology.
http://www.iit.edu...

David A. Black

3/4/2009 9:20:00 PM

0

Hi --

C. Dagnon wrote:
> Ruby has definite positives over Java and even other scripting
> languages, but many negatives too. One negative is the inconsistency of
> how rules seem to be applied in the language and accompanying toolsets.
> Here are a few that have bitten me:
>
>
> 1. I almost immediately got started with Ruby on Rails and loved the
> idea of partials, but then I found that the ||= idiom doesn't work on
> partials' parameters.
>
> <% my_param_a ||= 1 # Errors out
> my_param_a = my_param_a ? my_param_a : 1 # works
> -%>
>
> That seemed odd as I thought both were equivalent, and it broke some of
> the trust I had for Ruby. Not as much as early Rails' use of 2 separate
> variables for RAILS_ENV, but...

I can't duplicate that problem. What error message are you getting?

> 3. Originally I was taught that symbols were the salvation of memory and
> key problems - and they certainly sounded like it. Up until the point a
> few days later when one (Rails?) map used Symbols and another used
> Strings. Ouch.
> Without any explicit typing abilities in the language (optional or
> otherwise?) it seems like the only solution is to return to basic string
> matches:
> regex = Regexp.compile("^#{matcher.to_s}$", Regexp::IGNORECASE)

You can use some shortcuts there:

/^#{matcher}$/i

> key = map.keys.find{ |key| key.to_s =~ regex }
> Yuck.

In 1.9, symbols can be matched against regular expressions. So you can do:

[:a,:b,:c,:cat].grep(/a/)

I have mixed emotions about the string-like behavior of symbols in 1.9
(they have methods like #upcase and #succ), but it has the practical
advantage of making it unnecessary to worry about which you've got if
you're matching patterns.

> Please let me know how I can supplement my possibly deficient Ruby
> education :) Relevant discussions or sections of "The Ruby Way"
> appreciated!

There's a book or two due out soon... see below :-)


David

--
David A. Black / Ruby Power and Light, LLC
Ruby/Rails consulting & training: http://www.r...
Coming in 2009: The Well-Grounded Rubyist (http://manning....)

Ruby Training Atlanta! April 1-3, http://www.entp.com/training...

C. Dagnon

3/4/2009 9:33:00 PM

0

Yossef Mendelssohn wrote:
> There's been endless discussion and confusion about Symbols, Strings,
> what they mean, what they should be used for, and their relation to
> each other. Rails did not help with HashWithIndifferentAccess, though
> I imagine they thought they would. But I don't want to start anything

I'm happy I didn't miss anything and sad to hear I'm not alone in that
confusion.

> like that up. I just want to point out that a lot of that code is
> unnecessary and could just be:
>
> key = map.keys.detect { |k| k.to_s.downcase ==
> matcher.to_s.downcase }

Hmmm, what is 'detect'?

I had been doing that, but then I thought that compiling a single regex
would be less expensive than downcasing everything every time they got
compared. Not that the example I included appears in any of my code,
but I've been doing it for similar situations to allow for things like
case-indifferent parameters.


>> 4. And what's up with Ruby incorrectly naming their Map 'Hash'?
> ...
> At least they're not called "dictionaries", right? Am I right?

Yes, definitely right on that one.
Okay, so that was a Perl influence. Darn.

> ...
> Hey, why aren't Arrays called Maps instead?

Sure arrays can be considered special kinds of maps. The ordering
problem could be solved by my_map.keys.sort.each instead of
my_array.each. The major difference I see is that Arrays have
type-checked and validated keys (non-negative integers), though I would
also say there's an assumption in how I've gotten used to using arrays
that if there is an element 5, there are elements 0-4 (even if nil).


Thanks for the reply!

-Chris
--
Posted via http://www.ruby-....

Tony Arcieri

3/4/2009 9:42:00 PM

0

[Note: parts of this message were removed to make it a legal post.]

On Wed, Mar 4, 2009 at 2:32 PM, C. Dagnon <c-soc-rubyforum@dagnon.net>wrote:

> Yossef Mendelssohn wrote:
> > key = map.keys.detect { |k| k.to_s.downcase == matcher.to_s.downcase
> }
>
> Hmmm, what is 'detect'?
>
> I had been doing that, but then I thought that compiling a single regex
> would be less expensive than downcasing everything every time they got
> compared.


You can also use String#casecmp to avoid making a new downcased string
object each time you do the comparison, e.g.

matcher.casecmp(k.to_s).zero?

--
Tony Arcieri

Iñaki Baz Castillo

3/4/2009 9:50:00 PM

0

El Mi=C3=A9rcoles, 4 de Marzo de 2009, C. Dagnon escribi=C3=B3:
> I had been doing that, but then I thought that compiling a single regex
> would be less expensive than downcasing everything every time they got
> compared.

Let's do some benchmarks:

=2D----------
irb> aaa=3D"HolaQueTAL"
irb> bbb=3D"holaQUEtal"

irb> Benchmark.realtime { aaa.downcase =3D=3D bbb.downcase }
1.97887420654297e-05

irb> Benchmark.realtime { aaa.casecmp(bbb) }
1.59740447998047e-05

irb> Benchmark.realtime { aaa =3D~ /^#{bbb}$/i }
3.19480895996094e-05
=2D--------------

Did you know the String#casecmp method? It seems to be the faster way.

=2D-=20
I=C3=B1aki Baz Castillo