What's New and Shiny in Ruby 1.8.0?

Since there were a number of requests around for a more detailed
explanation of 1.8.0 changes, I figured I’d start into my favorites and
cover as many as I can.

My 1.8.0 summary is up at:

http://whytheluckystiff.net/articles/2003/08/04/rubyOneEightOh

I’m about halfway done. I’ll post a link again when I feel like I’m
finished.

_why

Thanks for doing that. I like that you’ve not only mentioned the
changes but also given some background on why they’re interesting and
how they might be used.

Duck typing is an interesting idea – but I think to be used well it
will require more careful planning. I think the example of testing for
the method “read” is a good example. I can imagine a large number of
classes that would have a “read” method, but wouldn’t return what’s
expected from an IO type read.

Looking at the page, I also have another question concerning
Hash.merge. It does essentially the same thing is the set-union for
Arrays, right (Array#|)? Would anybody besides me like to see Hash#|
become an alias for Hash#merge? To me it would be more obvious that
{‘key’ => ‘val’} | {‘otherkey’ => ‘otherval’} returns a new hash and
doesn’t modify the original one.

Either way, the presence of this method is great for some HTTP stuff
I’m doing where the only difference between a GET and a POST is that
the POST requires a Content-type header.

Ben

···

On Monday, August 4, 2003, at 11:33 PM, why the lucky stiff wrote:

Since there were a number of requests around for a more detailed
explanation of 1.8.0 changes, I figured I’d start into my favorites and
cover as many as I can.

why the lucky stiff wrote:

My 1.8.0 summary is up at:

http://whytheluckystiff.net/articles/2003/08/04/rubyOneEightOh

I’m about halfway done. I’ll post a link again when I feel like I’m
finished.

One thing mentioned there is the new sort_by in Enumerable. A simple example I tried is:

text = [“the”, “quick”, “brown”, “fox”, “jumps”, “over”, “the”, “lazy”, “dog”]

puts text.sort_by { |x| x.length }.inspect

#=> [“the”, “the”, “fox”, “dog”, “over”, “lazy”, “quick”, “brown”, “jumps”]

Something that’s not mentioned, but I figured I’d try it, because I thought it would be nifty, is sorting by multiple values …

text = [“the”, “quick”, “brown”, “fox”, “jumps”, “over”, “the”, “lazy”, “dog”]

puts text.sort_by { |x| [x.length, x] }.inspect

#=> [“dog”, “fox”, “the”, “the”, “lazy”, “over”, “brown”, “jumps”, “quick”]

Ie, we now have the values sorted first by their length, and when the length is the same, they’re sub-sorted by the text itself. I think that’s great!

This would be particularly useful if the data items in the enumeration were instances of more complex objects. Then, you could do things like:

sorted = people.sort_by { |p| [p.last_name, p.first_name, p.salary] }

I just love Ruby!

Hi,
Thanks for the detailed explanation.
I am interested to know more about ext/dl (an interface to the dynamic
linker) as mentioned in http://dev.faeriemud.org/changes-1.8.0.html.

Regards,
Srijit

why the lucky stiff ruby-talk@whytheluckystiff.net wrote in message news:20030805033123.GA73854@rysa.inetz.com

···

Since there were a number of requests around for a more detailed
explanation of 1.8.0 changes, I figured I’d start into my favorites and
cover as many as I can.

My 1.8.0 summary is up at:

http://whytheluckystiff.net/articles/2003/08/04/rubyOneEightOh

I’m about halfway done. I’ll post a link again when I feel like I’m
finished.

_why

Hi,

···

In message “Re: What’s New and Shiny in Ruby 1.8.0?” on 03/08/05, Ben Giddings ben@thingmagic.com writes:

Looking at the page, I also have another question concerning
Hash.merge. It does essentially the same thing is the set-union for
Arrays, right (Array#|)? Would anybody besides me like to see Hash#|
become an alias for Hash#merge? To me it would be more obvious that
{‘key’ => ‘val’} | {‘otherkey’ => ‘otherval’} returns a new hash and
doesn’t modify the original one.

The | operator is not suitable for the cases like

{“key” => “val1”} | {“key” => "val2}

That’s the reason I chose “merge” for the name of the method.

						matz.

Something that’s not mentioned, but I figured I’d try it, because I
thought it would be nifty, is sorting by multiple values …

text = [“the”, “quick”, “brown”, “fox”, “jumps”, “over”, “the”, “lazy”,
“dog”]

puts text.sort_by { |x| [x.length, x] }.inspect

#=> [“dog”, “fox”, “the”, “the”, “lazy”, “over”, “brown”, “jumps”,
“quick”]

Ie, we now have the values sorted first by their length, and when the
length is the same, they’re sub-sorted by the text itself. I think that’s
great!

This would be particularly useful if the data items in the enumeration
were instances of more complex objects. Then, you could do things like:

sorted = people.sort_by { |p| [p.last_name, p.first_name, p.salary] }

I just love Ruby!

Agreed. I’ll file the multi-key sort under T for Things That
Make Me Go Ahhh…

Hal

···

----- Original Message -----
From: “Harry Ohlsen” harryo@qiqsolutions.com
To: “ruby-talk ML” ruby-talk@ruby-lang.org
Sent: Tuesday, August 05, 2003 8:17 PM
Subject: Re: What’s New and Shiny in Ruby 1.8.0?


Hal Fulton
hal9000@hypermetrics.com

If you don’t mind, I’m going to add this tiny example to the page. This is
incredibly readable and demonstrates a number of Ruby’s brilliant features at
once.

I’ve also just finished a section on Procs, StringIO, -run, and fixed the
Class.new and Module.new section. Just now starting on marshal_load,
marshal_dump, String#, String#to_i, and Array#zip.

Whew! There’s so much!

_why

···

On Tuesday 05 August 2003 07:17 pm, Harry Ohlsen wrote:

This would be particularly useful if the data items in the enumeration were
instances of more complex objects. Then, you could do things like:

sorted = people.sort_by { |p| [p.last_name, p.first_name, p.salary] }

I just love Ruby!

#=> [“dog”, “fox”, “the”, “the”, “lazy”, “over”, “brown”, “jumps”, “quick”]

It doesn’t roll off the tongue like the original IMHO :slight_smile:
but you may be the first person to discover programmatically
that there’s a redundant word in there.

In response to this crisis, I offer:

‘Quick dogs jump over the lazy brown fox’

Ie, we now have the values sorted first by their length,
and when the length is the same, they’re sub-sorted by the
text itself. I think that’s great!

Agreed. That is/will be bl**dy useful.

I just love Ruby!

It’s okay :slight_smile:

daz

···

“Harry Ohlsen” harryo@qiqsolutions.com wrote:

text = [‘the quick brown fox jumped over the lazy dog’,
‘the quick brown fox jumps over the lazy dog’,
‘quick dogs jump over the lazy brown fox’]
text.each do |phr|
puts; p phr
z = (‘a’…‘z’).to_a - phr.split(‘’)
puts " … doesn’t contain "#{z}"" unless z.empty?
end

#->“the quick brown fox jumped over the lazy dog”
#-> … doesn’t contain “s”

Wow. Sooo good.

Sooo good. Makes implementing lexicographic sorting soo much easier.
:o)

-Kurt

···

On Wed, Aug 06, 2003 at 10:17:44AM +0900, Harry Ohlsen wrote:

why the lucky stiff wrote:

My 1.8.0 summary is up at:

http://whytheluckystiff.net/articles/2003/08/04/rubyOneEightOh

I’m about halfway done. I’ll post a link again when I feel like I’m
finished.

One thing mentioned there is the new sort_by in Enumerable. A simple
example I tried is:

text = [“the”, “quick”, “brown”, “fox”, “jumps”, “over”, “the”, “lazy”,
“dog”]

puts text.sort_by { |x| x.length }.inspect

#=> [“the”, “the”, “fox”, “dog”, “over”, “lazy”, “quick”, “brown”, “jumps”]

Something that’s not mentioned, but I figured I’d try it, because I thought
it would be nifty, is sorting by multiple values …

text = [“the”, “quick”, “brown”, “fox”, “jumps”, “over”, “the”, “lazy”,
“dog”]

puts text.sort_by { |x| [x.length, x] }.inspect

#=> [“dog”, “fox”, “the”, “the”, “lazy”, “over”, “brown”, “jumps”, “quick”]

Ie, we now have the values sorted first by their length, and when the
length is the same, they’re sub-sorted by the text itself. I think that’s
great!

This would be particularly useful if the data items in the enumeration were
instances of more complex objects. Then, you could do things like:

sorted = people.sort_by { |p| [p.last_name, p.first_name, p.salary] }

I just love Ruby!

======= End of Original Message =======<

I really like this. But is there a simple easy way to get a descending
sort here without reverting to sorted = people.sort { … } ?

···

On Aug 6, Harry Ohlsen wrote:

sorted = people.sort_by { |p| [p.last_name, p.first_name, p.salary] }

How does one use this with one’s own objects, though?

I just cooked up an example Person class to play with and then tried to
sort it as above:

class Person
include Enumerable

attr_accessor :first_name, :last_name, :age

def initialize(f,l,a)
@first_name = f
@last_name = l
@age = a.to_i
end
end

p [d, g, i, j, p, j2, j3].sort_by { |x| [x.last_name, x.first_name, x.age] }

and I get:

./sort_by:23: undefined method `’ for #Person:0x4014e37c
(NoMethodError)

I’m fine with implementing Person#, but I can’t imagine how it should
look.

Ian

···

On Wed 06 Aug 2003 at 10:17:44 +0900, Harry Ohlsen wrote:

This would be particularly useful if the data items in the enumeration were
instances of more complex objects. Then, you could do things like:

sorted = people.sort_by { |p| [p.last_name, p.first_name, p.salary] }


Ian Macdonald | If God wanted us to have a President, He
System Administrator | would have sent us a candidate. – Jerry
ian@caliban.org | Dreshfield
http://www.caliban.org |
>

Ruby/DL is now covered. Prototyping functions, casting into structs, and
pointer math! Everything you never wanted to do in Ruby but can! :slight_smile:

Thanks for reading, Srijit.

_why

···

On Tuesday 05 August 2003 11:01 pm, srijit@yahoo.com wrote:

Hi,
Thanks for the detailed explanation.
I am interested to know more about ext/dl (an interface to the dynamic
linker) as mentioned in http://dev.faeriemud.org/changes-1.8.0.html.

Regards,
Srijit

why the lucky stiff ruby-talk@whytheluckystiff.net wrote in message
news:20030805033123.GA73854@rysa.inetz.com

Since there were a number of requests around for a more detailed
explanation of 1.8.0 changes, I figured I’d start into my favorites and
cover as many as I can.

My 1.8.0 summary is up at:

http://whytheluckystiff.net/articles/2003/08/04/rubyOneEightOh

I’m about halfway done. I’ll post a link again when I feel like I’m
finished.

_why

Hi Matz,

Thanks for the clarification. I hadn’t thought of which hash “wins”
when both contain a key. Using “merge” does make it more clear.

Ben

···

On Tuesday, August 5, 2003, at 01:50 AM, Yukihiro Matsumoto wrote:

The | operator is not suitable for the cases like

{“key” => “val1”} | {“key” => "val2}

That’s the reason I chose “merge” for the name of the method.

why the lucky stiff wrote:

If you don’t mind, I’m going to add this tiny example to the page. This is
incredibly readable and demonstrates a number of Ruby’s brilliant features at
once.

Certainly! That’s the first time someone’s called something I wrote “readable” :-).

I’ve also just finished a section on Procs, StringIO, -run, and fixed the
Class.new and Module.new section. Just now starting on marshal_load,
marshal_dump, String#, String#to_i, and Array#zip.

Great. I’ll go have another read.

Whew! There’s so much!

Yes, there certainly is. I’ve been avoiding using the 1.8 features until we got to preview releases, so it’s all new (and fantastic!) to me.

H.

I wrote:

that there’s a redundant word in there.

Arghh, there’s a redundant variable in that sig.

[‘the quick brown fox jumped over the lazy dog’,
‘the quic brown ox jumps over the lazy dog’,
‘quick dogs jump over the lazy brown fox’].
each do |phr|
puts; p phr
z = (‘a’…‘z’).to_a - phr.split(‘’)
puts " … doesn’t contain "#{z}"" unless z.empty?
end

ISBN: 0385722435 :slight_smile:

    Hugh
···

On Wed, 6 Aug 2003, daz wrote:

In response to this crisis, I offer:

‘Quick dogs jump over the lazy brown fox’

How about

sorted = people.sort_by { |p| [p.last_name, p.first_name, p.salary] }.reverse

I haven’t looked, but I suspect you can’t selectively make individual
criteria ascending/descending. Now, if we had a #stable_sort_by,
then we could chain them together to get the desired
results without crafting complex comparisons . . . :slight_smile:

-Mark

···

On Thu, Aug 07, 2003 at 01:35:40AM +0900, Brett H. Williams wrote:

On Aug 6, Harry Ohlsen wrote:

sorted = people.sort_by { |p| [p.last_name, p.first_name, p.salary] }

I really like this. But is there a simple easy way to get a descending
sort here without reverting to sorted = people.sort { … } ?

I would guess that there’s something in the code you didn’t show (ie, that
defines d, g, i, j, p, j2 and j3) that’s causing this error message.

Here’s an example that works just fine …

···

On Thu, 7 Aug 2003 03:26, Ian Macdonald wrote:

How does one use this with one’s own objects, though?

I just cooked up an example Person class to play with and then tried to
sort it as above:

class Person
include Enumerable

attr_accessor :first_name, :last_name, :age

def initialize(f,l,a)
@first_name = f
@last_name = l
@age = a.to_i
end
end

p [d, g, i, j, p, j2, j3].sort_by { |x| [x.last_name, x.first_name, x.age]
}

and I get:

./sort_by:23: undefined method `’ for #Person:0x4014e37c
(NoMethodError)


class Person
include Enumerable

attr_accessor :first_name, :last_name, :age

def initialize(l,f,a)
@first_name = f
@last_name = l
@age = a.to_i
end

def to_s
“{#{@last_name}, #{@first_name}, #{@age}}”
end
end

a = Person.new(“Wall”, “Larry”, 40)
b = Person.new(“Matsumoto”, “Yukihiro”, 20)
c = Person.new(“Van Rossum”, “Guido”, 30)

puts [a, b, c].sort_by { |x| [x.last_name, x.first_name, x.age] }.join(“\n”)

#=>
{Matsumoto, Yukihiro, 20}
{Van Rossum, Guido, 30}
{Wall, Larry, 40}

Please note that those fake ages aren’t intended to be accurate :-).

That’s a really great page you have, some things that might help clarify:

Regarding LocalJumpError, my understanding is that the problem with

return ( x > 25 && y > 25 )

is that because it’s a block and not a proc, it is trying to return to the
context at the end of add_click_handler, which may be defined somewhere
really far away from where you use simulate_click. What you want instead is
for it to go here: “return false unless h.call( x, y )”. If instead of using
“return” you just go to the end of the block, that’s what will happen, and
the return value will be the value of the last expression evaluated.

If my understanding is correct, that might be some good text to put on there
to make it clear what Ruby is trying to do, compared to what you want it to
do.

Another suggestion for initialize_copy is to use a value that would be bad to
copy using .dup, for instance a “password” field. If it weren’t cleared,
then by default the new Person would have the same password as the previous
person. Using initialize_copy would allow you to make sure that .dup doesn’t
dup someone’s password too.

I think it would also be a good idea to note that this breaks the convention
of what .dup does, in that it no longer provides a true duplicate of the
other object, so that it should be used carefully. My suggestion would be
that it might decide not to copy over certain details, but that it never
creates new details “out of thin air”. Using Time.now like this kind-of
breaks this exception, but it seems like an acceptable deviation from the
rule… so long as this odd behaviour is documented. :slight_smile:

Ben

···

On Wed August 6 2003 6:29 pm, why the lucky stiff wrote:

Ruby/DL is now covered. Prototyping functions, casting into structs, and
pointer math! Everything you never wanted to do in Ruby but can! :slight_smile:

This would be particularly useful if the data items in the enumeration were
instances of more complex objects. Then, you could do things like:

sorted = people.sort_by { |p| [p.last_name, p.first_name, p.salary] }

How does one use this with one’s own objects, though?

I just cooked up an example Person class to play with and then tried to
sort it as above:

class Person
include Enumerable
^^^^^^^^^^^^^^^^^^
Person doesn’t implement #each, why mixin Enumerable?

attr_accessor :first_name, :last_name, :age

def initialize(f,l,a)
@first_name = f
@last_name = l
@age = a.to_i
end
end

p [d, g, i, j, p, j2, j3].sort_by { |x| [x.last_name, x.first_name, x.age] }

and I get:

/sort_by:23: undefined method `’ for #Person:0x4014e37c
(NoMethodError)

I’m fine with implementing Person#, but I can’t imagine how it should
look.

~/prog/ruby$ ruby -v
ruby 1.8.0 (2003-08-04) [i686-linux]
~/prog/ruby$ cat person.rb
class Person
attr_accessor :first_name, :last_name

def initialize(f,l)
@first_name = f
@last_name = l
end

def inspect
“#{@first_name} #{@last_name}”
end
end

ary = [ Person.new(“Joe”, “Blow”),
Person.new(“John”, “Doe”),
Person.new(“Bill”, “Blow”),
Person.new(“Jane”, “Doe”) ]
p ary.sort_by { |x| [x.last_name, x.first_name ] }
~/prog/ruby$ ruby person.rb
[Bill Blow, Joe Blow, Jane Doe, John Doe]

BTW, your original example worked fine on my version of Ruby. Another
option, of course, is to implement <=> for Person like so (untested)

class Person
def <=>(other)
[ @last_name, @first_name ] <=> [ other.last_name, other.first_name ]
end
end

Jason Creighton

···

On Thu, 7 Aug 2003 02:26:35 +0900 Ian Macdonald ian@caliban.org wrote:

On Wed 06 Aug 2003 at 10:17:44 +0900, Harry Ohlsen wrote: