Is there a replacement for sub?

M

Morton Goldberg

Is there nothing in regular expressions where you can tell it to do
something up to n times?

OK, is this what you're looking for?

result = []
7.times do |n|
result << "a b c d e f".sub(/(\S\s){0,#{n}}/) { |m| m.delete(" ") }
end
result # =>
["a b c d e f", "ab c d e f", "abc d e f", "abcd e f", "abcde f",
"abcdef", "abcdef"]

Regards, Morton
 
M

Michael W. Ryder

Martin said:
Remember that a variable is not an object, it is just a label pointing
to an object.

sub: returns a *copy* of the string, with the substitution made (i.e.
a new object)
sub!: modifies the string in place (i.e. modifies the object itself)

Therefore

a = "a b c d e f"
a.sub(" ", "") # => returns "ab c d e f", but leaves a unchanged.
also, the return value will be garbage collected, since nothing is
pointing to it

b = a.sub(" ", "") # => b is now "ab c d e f", leaves a unchanged

a = a.sub(" ", "") # => a is now "ab c d e f", the old string is
garbage collected

a = "a b c d e f"
b = a
a = a.sub(" ", "") # => a is now "ab c d e f", b is still "a b c d e f"
Wrong. Unless you use b = a.dup b will be the same as a as it is
pointing to the same object. The result of the sub operation will
change b as well as a.

a = "a b c d e f"
a.sub!("", '') #=> a is now "ab c d e f"

a = "a b c d e f"
b = a.sub!("", '') #=> a is now "ab c d e f", a and b point to the same
object

a = "abcdef"
b = a.sub!("", '') #=> a is still "abcdef", b is nil

Note the last bit carefully - sub! modifies the object, and *returns*
either another pointer to the same object if it was modified, or nil
if it wasn't. Therefore the return value of sub! should ideally only
be used to check if the string was modified or not, and then
discarded.

As for running in a loop, you want either

10.times { a.sub!(" ", '')} #=> modifies a string 10 times

or

10.times {a = a.sub(" ", '')} # creates a series of 10 strings, the
intermediate ones being GCd

try this:

a = "a b c d e f"
intermediate = [a]
10.times {|i| intermediate[i+1] = intermediate.sub(" ", '')}
p intermediate


I guess my problem is that the sub operations return a nil if they don't
make a change rather than the unchanged object. This seems to be
inconsistent as you get the changed object back if it works but nothing
if it doesn't. Maybe I need to write a version of sub or a method for
it that returns the string regardless of whether it was changed or not.

# => ["a b c d e f", "ab c d e f", "abc d e f", "abcd e f", "abcde f",
"abcdef", "abcdef", "abcdef", "abcdef", "abcdef", "abcdef"]


martin
 
S

Sebastian Hungerecker

Michael said:
Martin DeMello wrote:

Nope.

Unless you use b = a.dup b will be the same as a as it is
pointing to the same object.
Yes.

The result of the sub operation will
change b as well as a.

No, sub won't change the actual string - that's what sub! would do. It will
create a new string which will be assigned to a, at which point a and b won't
be pointing at the same object anymore.

I guess my problem is that the sub operations return a nil if they don't
make a change rather than the unchanged object.

They don't. sub! (the destructive method) will return nil, sub will return the
unchanged object.

Maybe I need to write a version of sub or a method for
it that returns the string regardless of whether it was changed or not.

sub does that already.
 
M

Michael W. Ryder

Sebastian said:
No, sub won't change the actual string - that's what sub! would do. It will
create a new string which will be assigned to a, at which point a and b won't
be pointing at the same object anymore.
My mistake. Too many tests with and without the ! operator. I guess
that my test used sub! instead of sub. This just proves my point that
the whole thing is too confusing.
 
D

dblack

Hi --

My mistake. Too many tests with and without the ! operator. I guess that my
test used sub! instead of sub. This just proves my point that the whole
thing is too confusing.

Keep in mind that the ! means that the method is the "dangerous"
version. In this case, the danger consists of both the changing of
the object in place, and the returning of nil when there's no change.
Any time you see a ! in a method name you've been warned that there's
probably something you need to be particular aware of and careful
about.


David

--
* Books:
RAILS ROUTING (new! http://www.awprofessional.com/title/0321509242)
RUBY FOR RAILS (http://www.manning.com/black)
* Ruby/Rails training
& consulting: Ruby Power and Light, LLC (http://www.rubypal.com)
 
M

Michael W. Ryder

Hi --



Keep in mind that the ! means that the method is the "dangerous"
version. In this case, the danger consists of both the changing of
the object in place, and the returning of nil when there's no change.
Any time you see a ! in a method name you've been warned that there's
probably something you need to be particular aware of and careful
about.
Unfortunately, my background has always been that a function never
returns nil if nothing is done. C has the ++ operator which can be very
dangerous but it never returns nil. It may be safer to use a = a + 1 or
even better b = a + 1, but I don't have to worry that a++ will return 0
unless a was -1 before. I realize that the ! operator is a shortcut, but
if it is going to be a shortcut that is all it should be. They
current way it is used with sub and gsub is that sometimes it returns
the results in the specified object and other times it wipes out the
object. This makes it Very hard to write a program where you are not
always sure of the data, which in my case is a lot of the time.
For example if I was cleaning a data file from a customer where he used
dashes in a Social Security Number and I only wanted to remove up to the
first two dashes in the number, knowing that if more are present that
the number is invalid, I would use a variant of sub. I would not want
to have to program for cases where there were no or one dash in the
number. True, I could spend a lot of time trying to catch every
abnormality, but then where is the advantage in using a language like
Ruby, when I could do less work with a "primitive" language that does
what I want without having to check what it is doing.
I am not saying that Ruby is a "bad" language, as it has a lot of very
nice features. My problem is that I am not always expecting some of the
idiosyncrasies of the language. When I see something like sub! I expect
that it will return my string with the substitution made or the
unchanged string, not a nil.
 
D

dblack

Hi --

Unfortunately, my background has always been that a function never returns
nil if nothing is done.

Think about the implications of that, though: what you're saying, in
effect, is that Ruby should adapt itself in great detail to everyone's
background -- which really means that Ruby should do everything the
same way *all* other languages (since someone has a background in
every language) do it. Of course, there's no such thing :)

It's not that Ruby is above criticism, of course; but it's best to
take it on its own terms as much as possible, and you'll find that
things are very well planned and thought through. The ! isn't
supposed to be a trap or a surprise; on the contrary, it's an explicit
indicator of exactly what you're concerned about -- namely, the fact
that the behavior of this method may do "dangerous" things that the
the non-! version doesn't do.

Have a look at: http://www.infoq.com/articles/coming-from-ruby for
more encouragement along these lines :)
C has the ++ operator which can be very dangerous but it never
returns nil.

It also doesn't tell you, right in its name, that you should be
cautious about danger.
It may be safer to use a = a + 1 or even better b = a + 1, but I
don't have to worry that a++ will return 0 unless a was -1 before. I
realize that the ! operator is a shortcut, but if it is going to be
a shortcut that is all it should be.

It's not a shortcut; as Robert K. said, it's just the last character
in the method name. It has no language-level significance, but the
contract in place is that it means "dangerous".


David

--
* Books:
RAILS ROUTING (new! http://www.awprofessional.com/title/0321509242)
RUBY FOR RAILS (http://www.manning.com/black)
* Ruby/Rails training
& consulting: Ruby Power and Light, LLC (http://www.rubypal.com)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,768
Messages
2,569,574
Members
45,051
Latest member
CarleyMcCr

Latest Threads

Top