str1 = str2 is not a copy?!?

  • Thread starter Joe Ruby MUDCRAP-CE
  • Start date
J

Joe Ruby MUDCRAP-CE

I have:

File.foreach(data_file) do |line|
line.strip!

puts line

base_name = line

puts line

base_name.sub!('www.', '')
base_name.sub!(/\.\w+$/, '')

puts line
end

Which outputs:

www.domain.com
www.domain.com
domain

WHY is var line getting changed by operations on var base_name? Isn't
'base_name = line' supposed to create a copy? '=' in this case seems to
be acting like an alias or something.

BTW, is there a foreach function that automatically strips off the
newlines from line? Returning the record separators is silly.

Currently hating Ruby,
Joe
 
J

Jamey Cribbs

Joe said:
I have:

File.foreach(data_file) do |line|
line.strip!

puts line

base_name = line

puts line

base_name.sub!('www.', '')
base_name.sub!(/\.\w+$/, '')

puts line
end

Which outputs:

www.domain.com
www.domain.com
domain

WHY is var line getting changed by operations on var base_name? Isn't
'base_name = line' supposed to create a copy? '=' in this case seems to
be acting like an alias or something.
Nope. Now, you have two variables, base_name and line, referencing the
same object. Try:

base_name = line.dup
BTW, is there a foreach function that automatically strips off the
newlines from line? Returning the record separators is silly.

line.chomp!
Currently hating Ruby,
Be a lover not a fighter! ;-)

Jamey

Confidentiality Notice: This email message, including any attachments, is for the sole use of the intended recipient(s) and may contain confidential and/or privileged information. If you are not the intended recipient(s), you are hereby notified that any dissemination, unauthorized review, use, disclosure or distribution of this email and any materials contained in any attachments is prohibited. If you receive this message in error, or are not the intended recipient(s), please immediately notify the sender by email and destroy all copies of the original message, including attachments.
 
F

Farrel Lifson

I have:

File.foreach(data_file) do |line|
line.strip!

puts line

base_name = line

puts line

base_name.sub!('www.', '')
base_name.sub!(/\.\w+$/, '')

puts line
end

Which outputs:

www.domain.com
www.domain.com
domain

WHY is var line getting changed by operations on var base_name? Isn't
'base_name = line' supposed to create a copy? '=' in this case seems to
be acting like an alias or something.

BTW, is there a foreach function that automatically strips off the
newlines from line? Returning the record separators is silly.

Currently hating Ruby,
Joe

It doesn't create a copy, both variables reference the same object. If
you don't want to modify the original value use sub rather than gsub!

Farrel
 
A

Austin Ziegler

WHY is var line getting changed by operations on var base_name? Isn't
'base_name = line' supposed to create a copy? '=' in this case seems
to be acting like an alias or something.

No, it isn't. You're not understanding Ruby variables and assignment.

Variables in Ruby aren't locations; they're names. Objects are the only
things that take up (meaningful) space.

Assignment doesn't copy.
BTW, is there a foreach function that automatically strips off the
newlines from line? Returning the record separators is silly.

No, it isn't silly. Sometimes, that's what people want. You should be
using #chomp or #chomp! to strip that (use #strip or #strip! if and only
if you want to remove whitespace from beginning and end of the line).

-austin
 
S

snacktime

I have:

File.foreach(data_file) do |line|
line.strip!

puts line

base_name = line

puts line

base_name.sub!('www.', '')
base_name.sub!(/\.\w+$/, '')

puts line
end

Which outputs:

www.domain.com
www.domain.com
domain

WHY is var line getting changed by operations on var base_name? Isn't
'base_name = line' supposed to create a copy? '=' in this case seems to
be acting like an alias or something.

As far as my understanding goes most assignments just copy object
references. Try something like base_name = line.clone.

Chris
 
L

Louis J Scoras

As has been pointed out, you are creating a new binding to the same
object. Where it can get tricky is with multiple value assignments:

array = ['you', 'loose.']
a, b = array

p [a,b]
p array

b = 'win!'
p array # Doh!!

x = array ; x[1] = 'win!'
p array # array has been changed
 
D

dblack

Hi --

Joe Ruby MUDCRAP-CE wrote:

/ ...


Because in most cases, variable names contain references for the sake of
efficiency. To get the behavior you want, try:

base_name = "" + line

You don't have to resort to a workaround like that; you can do:

base_name = line.dup


David

--
David A. Black | (e-mail address removed)
Author of "Ruby for Rails" [1] | Ruby/Rails training & consultancy [3]
DABlog (DAB's Weblog) [2] | Co-director, Ruby Central, Inc. [4]
[1] http://www.manning.com/black | [3] http://www.rubypowerandlight.com
[2] http://dablog.rubypal.com | [4] http://www.rubycentral.org
 
C

Chris Gernon

Joe said:
WHY is var line getting changed by operations on var base_name? Isn't
'base_name = line' supposed to create a copy? '=' in this case seems to
be acting like an alias or something.

Yep. All variables in Ruby are actually references to objects ... so
using the = operator actually signifies "this variable now points at the
same object as that variable". What you want is probably either:

base_name = line.clone

or

base_name = String.new(line)

but it would probably make more sense to just create base_name at the
first operation where you want the two to be different - for example:

line.strip!
puts line

base_name = line.sub('www.', '')
base_name.sub!(/\.\w+$/, '')

puts line
BTW, is there a foreach function that automatically strips off the
newlines from line? Returning the record separators is silly.

Hmmm, not that I know of. However, I just want to mention that you
probably want String#chomp rather than String#strip, unless you actually
want to strip whitespace from the beginning of the string as well.
Currently hating Ruby,
Joe

Watch it - you may be in danger of losing your MUDCRAP certification ...
;)
 
D

David Vallner

--------------enig9EE945A6973ADD854A747717
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable

Paul said:
=20
Because in most cases, variable names contain references for the sake o= f
efficiency.

And I'm guessing the sake of simplicity too. The Ruby basic data item
object is thus one-dimensional, objects hold data, and variables point
to objects. Contrasting with C, where either variables hold data, or
heap memory holds data, and variables point to heap memory, or (ye gods)
C++, where references add yet another dimension to the variable / data
relationship (and that you can override the behaviour to do something
else when a data item changes the way it's being referenced
arbitrarily), this is -much- simpler to understand (when learning as a
first system, not if used to a PHPesque ad-hoc mixture of behaviours),
and what's more important, it's easier to keep a single set of quirks to
watch out for when using other peoples' code, or designing reusable code
(e.g. to avoid clobbering a library's internal state, etc.); although it
-is- a net loss of language expressivity. Indeed, AFAIK, even the
predominant C++ practice is "pick pointers or references and stick with
them throughout your code" for the common case.

David Vallner


--------------enig9EE945A6973ADD854A747717
Content-Type: application/pgp-signature; name="signature.asc"
Content-Description: OpenPGP digital signature
Content-Disposition: attachment; filename="signature.asc"

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.5 (MingW32)

iD8DBQFFSnQCy6MhrS8astoRAor5AJ97WkR/nzHVZyWVupeNu65fLKKZYwCfRqun
Mg/Z9R2MrfpZyA9EYJweZ1k=
=rBF0
-----END PGP SIGNATURE-----

--------------enig9EE945A6973ADD854A747717--
 
G

Gregory Brown

As has been pointed out, you are creating a new binding to the same
object. Where it can get tricky is with multiple value assignments:

array = ['you', 'loose.']
a, b = array

p [a,b]
p array

b = 'win!'
p array # Doh!!

x = array ; x[1] = 'win!'
p array # array has been changed

I get the point of this example, but it's worth noting that you can
change the array via b if you just use String#replace
=> ["you", "win"]
 

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,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top