[lnkForumImage]
TotalShareware - Download Free Software

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


 

Forums >

comp.lang.ruby

some questions on language syntax

Pavel Smerk

3/14/2006 8:51:00 PM

Hi, I'm new to this language and as I'm Perl user, some things seems
strange to me:

= %w{a b} produces ['a', 'b']. Is there some similarily easy way for
{'a' => 'b'}? Or, can I transform an array to some "list"? I can use
Hash['a', 'b'], but not Hash[%w{...}], because I cannot generate a list,
only an array.

= how can I do 'perlish' a[1] <=> b[1] || a[2] <=> b[2] if I want
compare a and b accordind to some my own rules, i.e. if a[1] == b[2],
"return" a[2] <=> b[2]? In Ruby this is not possible, because 0 is true.

= can I somehow make ruby produce warnings on 1 == '1' (number ==
string) like comparisons? In Perl true, in Ruby false. Many my mistakes
are of this kind and as these values seems same on output. ;-)

= why I can use {|...| ...} as argument for map, each etc., but I cannot
write foo = {|...| ...}, though I can write bar = [...] or bar = {...}?

Thanks,

P.
13 Answers

Bernhard 'elven' Stoeckner

3/14/2006 9:10:00 PM

0

Pavel Smerk scribbled on Tuesday 14 Mar 2006 21:50:

> Hi, I'm new to this language and as I'm Perl user, some things seems
> strange to me:
>
> = %w{a b} produces ['a', 'b']. Is there some similarily easy way for
> {'a' => 'b'}? Or, can I transform an array to some "list"? I can use
> Hash['a', 'b'], but not Hash[%w{...}], because I cannot generate a list,
> only an array.

You can, however, expand the array:
Hash[*%w{a b c d}] yields {"a"=>"b", "c"=>"d"}

> = how can I do 'perlish' a[1] <=> b[1] || a[2] <=> b[2] if I want
> compare a and b accordind to some my own rules, i.e. if a[1] == b[2],
> "return" a[2] <=> b[2]? In Ruby this is not possible, because 0 is true.

irb(main):006:0> 0 == true
=> false

0 is not true :)

> = can I somehow make ruby produce warnings on 1 == '1' (number ==
> string) like comparisons? In Perl true, in Ruby false. Many my mistakes
> are of this kind and as these values seems same on output. ;-)

Not that I know of. Well, you could extend the == operator on Fixnum (and
String) to throw a warning:

class Fixnum
def ==(a)
warn "Warn" unless a.is_a? Fixnum
super(a)
end
end

> = why I can use {|...| ...} as argument for map, each etc., but I cannot
> write foo = {|...| ...}, though I can write bar = [...] or bar = {...}?

You can't use {} literals in an assignment to denote a block because Ruby
thinks it is supposed to be a Hash. Use Kernel#proc (or the alias #lambda)
for that:

irb(main):026:0> p = proc {|n| puts n}
=> #<Proc:0xb7c98138@(irb):26>
irb(main):027:0> p.call(5)
5

You can pass that block to any method that wants a block (note the &
operator that denotes the passed argument is a block):

irb(main):029:0> [33, 44, 55].each &p
33
44
55

See also Method#block_given?

Hope that helps.

James Gray

3/14/2006 9:16:00 PM

0

On Mar 14, 2006, at 3:03 PM, Pavel Smerk wrote:

> Hi, I'm new to this language and as I'm Perl user, some things
> seems strange to me:
>
> = %w{a b} produces ['a', 'b']. Is there some similarily easy way
> for {'a' => 'b'}? Or, can I transform an array to some "list"? I
> can use Hash['a', 'b'], but not Hash[%w{...}], because I cannot
> generate a list, only an array.

You are looking for the "splat" operator:

>> Hash[*%w{a b}]
=> {"a"=>"b"}

> = how can I do 'perlish' a[1] <=> b[1] || a[2] <=> b[2] if I want
> compare a and b accordind to some my own rules, i.e. if a[1] == b
> [2], "return" a[2] <=> b[2]? In Ruby this is not possible, because
> 0 is true.

We use sort_by() for that:

>> %w{one two three}.sort_by { |str| [-str.length, str] }
=> ["three", "one", "two"]

> = can I somehow make ruby produce warnings on 1 == '1' (number ==
> string) like comparisons? In Perl true, in Ruby false. Many my
> mistakes are of this kind and as these values seems same on
> output. ;-)

Hmm, you could redefine ==(), but you don't want to do that, trust
me. ;) The transition phase will pass in time...

> = why I can use {|...| ...} as argument for map, each etc., but I
> cannot write foo = {|...| ...}, though I can write bar = [...] or
> bar = {...}?

You can use lambda() for this:

proc_object = lambda { |...| ... }

James Edward Gray II


Gene Tani

3/14/2006 9:24:00 PM

0


Pavel Smerk wrote:
> Hi, I'm new to this language and as I'm Perl user, some things seems
> strange to me:
>
> = %w{a b} produces ['a', 'b']. Is there some similarily easy way for
> {'a' => 'b'}? Or, can I transform an array to some "list"? I can use
> Hash['a', 'b'], but not Hash[%w{...}], because I cannot generate a list,
> only an array.
>
> = how can I do 'perlish' a[1] <=> b[1] || a[2] <=> b[2] if I want
> compare a and b accordind to some my own rules, i.e. if a[1] == b[2],
> "return" a[2] <=> b[2]? In Ruby this is not possible, because 0 is true.
>

use #sort_by like:
Enumerable#sort_by { |obj| obj.fld1, obj.fld2 }

this list give good, quick, *accurate* answers, no?

Jim Weirich

3/14/2006 9:30:00 PM

0

> On Mar 14, 2006, at 3:03 PM, Pavel Smerk wrote:
>> = how can I do 'perlish' a[1] <=> b[1] || a[2] <=> b[2] if I want
>> compare a and b accordind to some my own rules, i.e. if a[1] == b
>> [2], "return" a[2] <=> b[2]? In Ruby this is not possible, because
>> 0 is true.
>
James Gray wrote:
> We use sort_by() for that:

Or nonzero? ... eg.

(a[1] <=> b[2]).nonzero? || (a[2] <=> b[2])

--
-- Jim Weirich

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


Ara.T.Howard

3/14/2006 10:03:00 PM

0

Pavel Smerk

3/14/2006 10:16:00 PM

0

Bernhard 'elven' Stoeckner wrote:
> Pavel Smerk scribbled on Tuesday 14 Mar 2006 21:50:
>>= %w{a b} produces ['a', 'b']. Is there some similarily easy way for
>>{'a' => 'b'}? Or, can I transform an array to some "list"? I can use
>>Hash['a', 'b'], but not Hash[%w{...}], because I cannot generate a list,
>>only an array.
>
> You can, however, expand the array:
> Hash[*%w{a b c d}] yields {"a"=>"b", "c"=>"d"}

Oh, that's great!!! How could I not notice that? ;-)

>>= how can I do 'perlish' a[1] <=> b[1] || a[2] <=> b[2] if I want
>>compare a and b accordind to some my own rules, i.e. if a[1] == b[2],
>>"return" a[2] <=> b[2]? In Ruby this is not possible, because 0 is true.
>
> irb(main):006:0> 0 == true
> => false
>
> 0 is not true :)

Well, to be more precise, 0 is not equal to false (as is in Perl). :-)

So, how do you do a[1] <=> b[1] || a[2] <=> b[2]? Or, may be a.x <=> b.y
|| a.w <=> b.z would be better --- I don't want to suppose anything
about the internal structure of a and b now. However, Jim Weirich's
(a[1] <=> b[2]).nonzero? || a[2] <=> b[2] seems OK (and it's even in
RDoc for Numeric#nonzero? ;-).

Gene Tani wrote:
> this list give good, quick, *accurate* answers, no?

;-) Must agree with this. Thank for all suggestions, they are very
valuable for me.

P.

Edward Faulkner

3/14/2006 10:28:00 PM

0

On Wed, Mar 15, 2006 at 07:23:46AM +0900, Pavel Smerk wrote:
> However, Jim Weirich's (a[1] <=> b[2]).nonzero? || a[2] <=> b[2] seems OK

I don't think that actually does what you want. The test should
return -1 if a[1] is less than b[2], but instead it will return
"true".

Pavel Smerk

3/14/2006 10:32:00 PM

0

ara.t.howard@noaa.gov wrote:
> that sorts strings like this
>
> /dmsp/nrt/data/incoming/afwa/2006.f13_0731556_DT.DAT
> /dmsp/nrt/data/incoming/afwa/2006.f13_0731737_DS.DAT
>
> where
>
> 2006.f13_0731556_DT.DAT
> ^^^^ ^^^ ^^^^^^^ ^^
> | | | |
> year sat time type
>
> first by sat, then by year, then by time and finally by type
>
> using only
>
> pats = %w[ f\d\d ^\d{4} _\d{7} _\w{2} ].map{|p|/#{p}/}
>
> basenames.sort!{|a,b| pats.map{|pat| a[pat]} <=> pats.map{|pat| b[pat]} }

Interesting idea, but may be _\w{2}\. would be more appropriate instead
of _\w{2} which can match also against a beginnig of the 'time' part. :)

P.

Mike Stok

3/14/2006 10:35:00 PM

0


On 14-Mar-06, at 5:28 PM, Edward Faulkner wrote:

> On Wed, Mar 15, 2006 at 07:23:46AM +0900, Pavel Smerk wrote:
>> However, Jim Weirich's (a[1] <=> b[2]).nonzero? || a[2] <=> b[2]
>> seems OK
>
> I don't think that actually does what you want. The test should
> return -1 if a[1] is less than b[2], but instead it will return
> "true".
>

Are you sure?
------------------------------------------------------- Numeric#nonzero?
num.nonzero? => num or nil
------------------------------------------------------------------------
Returns _num_ if _num_ is not zero, +nil+ otherwise. This behavior
is useful when chaining comparisons:

a = %w( z Bb bB bb BB a aA Aa AA A )
b = a.sort {|a,b| (a.downcase <=> b.downcase).nonzero? || a
<=> b }
b #=> ["A", "a", "AA", "Aa", "aA", "BB", "Bb", "bB", "bb",
"z"]

Mike

--

Mike Stok <mike@stok.ca>
http://www.stok...

The "`Stok' disclaimers" apply.






Jim Weirich

3/14/2006 10:53:00 PM

0

Edward Faulkner wrote:
> On Wed, Mar 15, 2006 at 07:23:46AM +0900, Pavel Smerk wrote:
>> However, Jim Weirich's (a[1] <=> b[2]).nonzero? || a[2] <=> b[2] seems OK
>
> I don't think that actually does what you want. The test should
> return -1 if a[1] is less than b[2], but instead it will return
> "true".

No, it works:

> (0 <=> 1).nonzero?
=> -1

It was for this exact purpose that nonzero? was introduced.

BTW, I hope no one was confused by the typo ... the first b[2] should
have been a b[1].

-- Jim Weirich

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