Purpose of replace method

Hi,

I was just wondering what the methods Array#replace, Hash#replace and
String#replace achieve that can’t be done with simple assignment.

I’m going to have a guess and say that assignment of an array, a hash or
a string to an already assigned variable creates a second object and
then changes the variable to point to the new object, whereas the
replace method does not cause a second object to be instantiated, but
simply wipes out the old one.

If my guess is right, then replace is there simply for the sake of
efficiency, in the same way that foo << bar is better than foo += bar.

Well, I’ve just decided to put my theory to the test:

#!/usr/bin/ruby -w

require 'benchmark’
include Benchmark

n = 5000000
bm(12) do |test|
test.report(‘assignment:’) do
foo = "bar"
1.upto(n) do
foo = "foo"
end
end
test.report(‘replacement:’) do
foo = "bar"
1.upto(n) do
foo.replace(“foo”)
end
end
end

              user     system      total        real

assignment: 8.210000 0.000000 8.210000 ( 8.202920)
replacement: 12.240000 0.010000 12.250000 ( 12.257115)

So, it would seem that replacement is 50% less efficient than simple
assignment.

What, then, is the purpose of the replace method?

Ian

···


Ian Macdonald | Far duller than a serpent’s tooth it is to
System Administrator | spend a quiet youth.
ian@caliban.org |
http://www.caliban.org |
>

Ian Macdonald wrote:

Hi,

I was just wondering what the methods Array#replace, Hash#replace and
String#replace achieve that can’t be done with simple assignment.

I’m going to have a guess and say that assignment of an array, a hash or
a string to an already assigned variable creates a second object and
then changes the variable to point to the new object, whereas the
replace method does not cause a second object to be instantiated, but
simply wipes out the old one.

If my guess is right, then replace is there simply for the sake of
efficiency, in the same way that foo << bar is better than foo += bar.

Well, I’ve just decided to put my theory to the test:

#!/usr/bin/ruby -w

require ‘benchmark’
include Benchmark

n = 5000000
bm(12) do |test|
test.report(‘assignment:’) do
foo = “bar”
1.upto(n) do
foo = “foo”
end
end
test.report(‘replacement:’) do
foo = “bar”
1.upto(n) do
foo.replace(“foo”)
end
end
end

              user     system      total        real

assignment: 8.210000 0.000000 8.210000 ( 8.202920)
replacement: 12.240000 0.010000 12.250000 ( 12.257115)

So, it would seem that replacement is 50% less efficient than simple
assignment.

What, then, is the purpose of the replace method?

For String#replace, this means that you can change a text you have
spread to several places without doing a reassignment again. This can be
handy if you have it a zillion places. (I.e. consider one replace
versus N assignments.)

As for your test, I get the sinking feeling that the assignment part
doesn’t really measure anything useful. An assignment is pretty cheap,
the “foo” is probably implemented with some kind of copy-on-write, while
a replace has to write the source string over into the destination
string byte-by-byte. Naturally, the latter would be slower.

One potential efficiency of replace would be to reuse created objects to
avoid creating new objects and using alot of memory. This kind of
optimization is not measured by benchmark.

···


([ Kent Dahl ]/)_ ~ [ http://www.pvv.org/~kentda/ ]/~
))_student_/(( _d L b_/ (pre-) Master of Science in Technology )
( __õ|õ// ) )Industrial economics and technological management(
_
/ö____/ (_engineering.discipline=Computer::Technology)

Ah, I see. So:

irb(main):001:0> foo = bar = “string”
=> “string”
irb(main):002:0> foo = “new”
=> “new”
irb(main):003:0> bar
=> “string”
irb(main):004:0> foo = bar = “string”
=> “string”
irb(main):005:0> foo.replace(“new”)
=> “new”
irb(main):006:0> bar
=> “new”

OK, that makes sense. replace is useful when multiple pointers point to
the same object.

Ian

···

On Fri 04 Jul 2003 at 19:35:21 +0900, Kent Dahl wrote:

For String#replace, this means that you can change a text you have
spread to several places without doing a reassignment again. This can be
handy if you have it a zillion places. (I.e. consider one replace
versus N assignments.)


Ian Macdonald | Never try to keep up with the Joneses; they
System Administrator | might be newlyweds.
ian@caliban.org |
http://www.caliban.org |
>

My ruby program processes web pages, which it collects using the
methods in net/http. Every now and again, it tries to access a web
page which is no longer available, is protected with a password, is on
a slow server that yields a timeout, and so on. What I’d like to do,
therefore, is protect the page fetching method with a
begin…rescue…end construction that will cause the program simply to
move on to the next web page that needs to be fetched if there is an
access error. However, I don’t want to trap any other kinds of error
(e.g. I’d still like to be able to interrupt the program with ^C).

Now, the obvious way of doing this is to append exception classes for
all the different types of web access error to the rescue clause, thus:

rescue ProtocolError, ProtoSyntaxError, …, TimeoutError => e

where … represents all the other possible errors. As far as I can
see, however, there are two problems with this. The first is that
ProtocolError (etc.) is defined in net/protocol.rb, which is 'required’
by ‘net/http’, which in turn is required by my program. The
consequence is that my program has no knowledge of ProtocolError and
the compiler objects that it is an uninitialized constant. The second
problem is that I don’t know how to construct a complete list of all
the different types of exception that I should include in my rescue
clause. I’ve already discovered relevant exceptions defined in
http.rb, protocol.rb and timeout.rb, but there may be more. How can I
find a list of all the exceptions that could occur?

Nigel

Ian Macdonald wrote:

···

On Fri 04 Jul 2003 at 19:35:21 +0900, Kent Dahl wrote:

For String#replace, this means that you can change a text you have
spread to several places without doing a reassignment again. This can be
handy if you have it a zillion places. (I.e. consider one replace
versus N assignments.)

Ah, I see. So:

irb(main):001:0> foo = bar = “string”
=> “string”
irb(main):002:0> foo = “new”
=> “new”
irb(main):003:0> bar
=> “string”
irb(main):004:0> foo = bar = “string”
=> “string”
irb(main):005:0> foo.replace(“new”)
=> “new”
irb(main):006:0> bar
=> “new”

OK, that makes sense. replace is useful when multiple pointers point to
the same object.

for this purpose it would be nice to have in Object. Why isn’t there a
replace method in Object?


dc -e
4ddod3dddn1-89danrn10-dan3+ann6dan2an13dn1+dn2-dn3+5ddan2/9+an13nap

My ruby program processes web pages, which it collects using the
methods in net/http. Every now and again, it tries to access a web
page which is no longer available, is protected with a password, is on
a slow server that yields a timeout, and so on. What I’d like to do,
therefore, is protect the page fetching method with a
begin…rescue…end construction that will cause the program simply to
move on to the next web page that needs to be fetched if there is an
access error. However, I don’t want to trap any other kinds of error
(e.g. I’d still like to be able to interrupt the program with ^C).

^C does not generate an exception. Try it:

begin
loop do
puts “hello”
sleep 1
end
rescue Exception => e
print
end

^C gets you out of this program quite easily

Now, the obvious way of doing this is to append exception classes for
all the different types of web access error to the rescue clause, thus:

rescue ProtocolError, ProtoSyntaxError, …, TimeoutError => e

where … represents all the other possible errors. As far as I can
see, however, there are two problems with this. The first is that
ProtocolError (etc.) is defined in net/protocol.rb, which is ‘required’
by ‘net/http’, which in turn is required by my program. The
consequence is that my program has no knowledge of ProtocolError and
the compiler objects that it is an uninitialized constant.

Err…?

If you do ‘requre “net/http”’ then the constant is available in your
program, end of story. However you need to give the correct constant name,
because it’s defined in a different module: e.g.

rescue Net::ProtocolError

The second
problem is that I don’t know how to construct a complete list of all
the different types of exception that I should include in my rescue
clause. I’ve already discovered relevant exceptions defined in
http.rb, protocol.rb and timeout.rb, but there may be more. How can I
find a list of all the exceptions that could occur?

That’s down to the modules. But exceptions are organised in a hierarchy so
usually you can find a sensible parent exception which catches all the
things you want. Notice, for example, that all the exceptions in
net/protocol.rb are subclasses of Net::ProtocolError, so a rescue on just
that will catch all the more specific subclass errors as well. The
higher-level exceptions RuntimeError or StandardError might also be
appropriate for catching a wider range of exceptions.

Regards,

Brian.

···

On Sat, Jul 05, 2003 at 05:58:37AM +0900, Nigel Gilbert wrote:

My ruby program processes web pages, which it collects using the
methods in net/http. Every now and again, it tries to access a web
page which is no longer available, is protected with a password, is on
a slow server that yields a timeout, and so on. What I’d like to do,
therefore, is protect the page fetching method with a
begin…rescue…end construction that will cause the program simply to
move on to the next web page that needs to be fetched if there is an
access error. However, I don’t want to trap any other kinds of error
(e.g. I’d still like to be able to interrupt the program with ^C).

^C aka SIGINT does not raise an exception.
you have to trap it (ri trap)

Now, the obvious way of doing this is to append exception classes for
all the different types of web access error to the rescue clause, thus:

now that you avoided ^C you can just

rescue
…stuff…

hope this helps

···

il Sat, 5 Jul 2003 05:58:37 +0900, Nigel Gilbert n.gilbert@soc.surrey.ac.uk ha scritto::

I’ve already discovered relevant exceptions defined in
http.rb, protocol.rb and timeout.rb, but there may be more. How can I
find a list of all the exceptions that could occur?

Nigel

···

“Nigel Gilbert” n.gilbert@soc.surrey.ac.uk wrote:
#------------------------------------------
require ‘net/http’
require ‘net/protocol’
require ‘timeout’

require ((… this))

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

class_tree(StandardError)
#------------------------------------------

  • StandardError

    • ArgumentError

    • IOError

      `- EOFError

    • IndexError

    • LocalJumpError … exit_value
      :… reason

    • NameError … name

      `- NoMethodError … args

    • Net::HTTPBadResponse

    • Net::HTTPHeaderSyntaxError

    • Net::ProtocolError

      • Net::HTTPError

      • Net::ProtoAuthError

      • Net::ProtoCommandError

      • Net::ProtoFatalError

        `- Net::HTTPFatalError

      • Net::ProtoRetriableError

        `- Net::HTTPRetriableError

      • Net::ProtoServerError

        `- Net::HTTPServerException

      • Net::ProtoSyntaxError

      `- Net::ProtoUnknownError

    [snip]

    • TypeError

    • URI::Error

      • URI::BadURIError

      • URI::InvalidComponentError

      `- URI::InvalidURIError

    `- ZeroDivisionError


ruby 1.8.0 (2003-06-23) [i586-bccwin32]

daz

“Anders Borch” spam@deck.dk wrote in message

for this purpose it would be nice to have in Object. Why isn’t there a
replace method in Object?

Array, Hash and String are containers. Object is not necessarily a
container.

I’ve written several simple command line tools in ruby to display
standard reports. These are all placed in the PATH, so that they can
be executed like this:

jobstatus.rb -j1233

to show the status for job 1233 (I’m using the getoptlong library.)
The default output is in fixed width, ASCII character built tables
(e.g., | for vertical line, - for horizontal line, and + for corners).
I’d like to be able to automatically sense when the output is being
piped to somewhere else, so that I can automatically make the report
switch to a tab delimited format a la the mysql command line client.
This, for example, allows for much easier use of command line tools
such as cut, uniq, sort, etc.

I’ve tried trapping signal 13 (SIGPIPE) and this doesn’t work. In
fact, I’ve tried trapping every signal from 0 to 64; 26 throws an
error, 0 executes on exit (of course), but none of them seem to
register for any kind of pipe; viz., ‘<’, ‘>’, and ‘|’ all fail to pass
a signal to the ruby program.

Am I doing something wrong here, or am I going about this entirely the
wrong way?

Best,

Dave

···

David King Landrith
(w) 617.227.4469x213
(h) 617.696.7133

One useless man is a disgrace, two
are called a law firm, and three or more
become a congress – John Adams

public key available upon request

I believe he wants #become.

···

On Fri, Jul 04, 2003 at 10:36:08PM +0900, Shashank Date wrote:

“Anders Borch” spam@deck.dk wrote in message

for this purpose it would be nice to have in Object. Why isn’t there a
replace method in Object?

Array, Hash and String are containers. Object is not necessarily a
container.


_ _

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

‘Ooohh… “FreeBSD is faster over loopback, when compared to Linux
over the wire”. Film at 11.’
– Linus Torvalds

David Landrith wrote:

… I’d like
to be able to automatically sense when the output is being piped to
somewhere else, so that I can automatically make the report switch to a
tab delimited format a la the mysql command line client.

In C, this is normally done using the standard library routine isatty(file_descriptor) which returns non-zero when output is going to a terminal.

Looking at the documentation for IO in pickaxe, there is an isatty() method.

So, I would imagine you can do something like (completely untested!) …

if $stdout.isatty
puts “Going to a terminal”
else
puts “Going somewhere else”
end

Note that this would also include if you redirect the output to a file.

Hope that helps.

Harry O.

Mauricio Fernández wrote:

···

On Fri, Jul 04, 2003 at 10:36:08PM +0900, Shashank Date wrote:

“Anders Borch” spam@deck.dk wrote in message

for this purpose it would be nice to have in Object. Why isn’t there a
replace method in Object?

Array, Hash and String are containers. Object is not necessarily a
container.

I believe he wants #become.

yep, but that’s not in Object either.


dc -e
4ddod3dddn1-89danrn10-dan3+ann6dan2an13dn1+dn2-dn3+5ddan2/9+an13nap

Works perfect! Thanks!

···

On Tuesday, July 29, 2003, at 12:54 AM, Harry Ohlsen wrote:

David Landrith wrote:

… I’d like to be able to automatically sense when the output is
being piped to somewhere else, so that I can automatically make the
report switch to a tab delimited format a la the mysql command line
client.

In C, this is normally done using the standard library routine
isatty(file_descriptor) which returns non-zero when output is going to
a terminal.

Looking at the documentation for IO in pickaxe, there is an isatty()
method.

So, I would imagine you can do something like (completely untested!)

if $stdout.isatty
puts “Going to a terminal”
else
puts “Going somewhere else”
end

Note that this would also include if you redirect the output to a file.

Hope that helps.

Harry O.


David King Landrith
(w) 617.227.4469x213
(h) 617.696.7133

Generic quotes offend nobody.
–Unknown

public key available upon request

I believe he wants #become.

yep, but that’s not in Object either.

See [ruby-core:1164]. I guess `become’ was added, then disappeared.
Cited as being too dangerous.

I think it’s a possible and valuable feature for Ruby, but some
disagree. You can actually get away with doing some of the same tricks
with a Delegator. If you check out Delegator and WeakRef classes,
you’ll see some semblance of pointers.

Here’s an initial stab at a WeakRef#become, which serves proper in most
of my cases.

require ‘weakref’

class WeakRef
def become(obj)
ID_MAP.delete self.id
initialize(obj)
self
end
end

Example usage:

a = [1, 2]
b = [3, 4]
c = WeakRef.new a
puts c.inspect
[1, 2]
c.become b
puts c.inspect
[3, 4]

Also see ObjectSpace#_id2ref.

_why

···

Anders Borch (spam@deck.dk) wrote:

David King Landrith wrote:

Works perfect! Thanks!

Don’t thank me; thank Matz :-).

Glad it be able to help. Most of the time, I’m the one asking the questions!

H.

See [ruby-core:1164]. I guess `become' was added, then disappeared.

A method *with the name* #become was added, then renamed in
#initialize_copy, but never this method made something similar to the
original #become

Cited as being too dangerous.

Just look at [ruby-talk:19761], if you want to know *one* of the *many*
problems that this method has.

Guy Decoux