Case of sub! not working

Yukihiro Matsumoto wrote:

how about making the interpreter running a $ENV.freeze at the beginning
of
the program?

Do you mean freezing strings from ENV? Hmm, maybe.

don’t take this seriously…

what if ENV’s = doesn’t return strings, but string-like objects (or
instances of some subclass of String) that has a custom sub! (and all
other MODIFY! methods) containing setenv?

perhaps that could complete the hash-like illusion of ENV? :slight_smile:

Someone posted a solution like this and it got me
to thinking…

The problem is: What if you do this:

str = ENV[‘foo’]

and then 100 lines farther down, you do:

str.gsub!(/this/,“that”)

It’s not obvious that this statement is
going to change the environment. So I think
this is a bad idea in general.

Cheers,
Hal

···

----- Original Message -----
From: “David Garamond” lists@zara.6.isreserved.com
To: “ruby-talk ML” ruby-talk@ruby-lang.org
Sent: Saturday, June 07, 2003 8:53 PM
Subject: Re: case of sub! not working

Which again needs the setenv() call to actually alter the value in the
environment. and it did modify the copy of ENV[‘PATH’] it made, but it
didn’t propagate it back to ENV :slight_smile:

ENV[‘bla’] = “banzai”
echo $bla # ← banzai\n
x=ENV[‘bla’].sub!(/banzai/, “ayaken”) # here the copy is modified, result => x
echo #{x} # ← ayaken\n <<- see, it did modify the copy
echo $bla # ← banzai\n <<- but no setenv() call.

Oh lord, now I realize I only half understood what was going on.

Do I understand this correctly now?

  • no method modifies the parents environment (standard unix behavior)

  • ENV#= modifies the ENV contents, and as such the current and any
    subsequent subprocesses environments through a delegated call to setenv
    (standard unix behavior, and how perl does it with its %ENV hash)

  • ENV##sub! DOESN’T modify the actual ENV contents, nor as such any
    environment; current nor subprocess.

?

I understand your reasoning, but why is = any different to sub! ?
If assignment (=) is just a method call with some syntactic sugar thrown
in, then why is it that sub! tries to modify the outside environment,
while = only modifies the singleton copy?

Ian

···

On Wed 04 Jun 2003 at 11:38:02 +0900, Yukihiro Matsumoto wrote:

In message “Re: case of sub! not working” > on 03/06/04, Ian Macdonald ian@caliban.org writes:

In my program, however, I would have been quite happy to have sub! just
modify the copy of ENV[‘PATH’] that it had made, as I wanted to modify
the path that would be used to find the location of a binary I was about
to open with popen. I wasn’t trying to modify the outside environment,
just that of my script and any of it children.

I understand what you feel, but still, environment variables are
entities in the operating system, the outside world from Ruby. You
were trying to modify the environment outside of Ruby, without
knowing. Read Hal’s explanation again in [ruby-talk:72787].


Ian Macdonald | Before borrowing money from a friend,
System Administrator | decide which you need more. – Addison H.
ian@caliban.org | Hallock
http://www.caliban.org |
>

Yes, except there’s really no ENV##sub! method, if you know
what I mean… ENV simply returns a string, and then you invoke
the String#sub! method.

And the string has no way of knowing that it came from the
environment, and the ENV object has no way of knowing that
the string object changed.

Hal

···

----- Original Message -----
From: “Mike Campbell” michael_s_campbell@yahoo.com
To: “ruby-talk ML” ruby-talk@ruby-lang.org
Sent: Tuesday, June 03, 2003 10:13 PM
Subject: Re: case of sub! not working

Do I understand this correctly now?

  • no method modifies the parents environment (standard unix behavior)

  • ENV#= modifies the ENV contents, and as such the current and any
    subsequent subprocesses environments through a delegated call to setenv
    (standard unix behavior, and how perl does it with its %ENV hash)

  • ENV##sub! DOESN’T modify the actual ENV contents, nor as such any
    environment; current nor subprocess.

It’s not really =, it’s =.

Real assignment is not a method. The =
is a method, one that is named so that it
looks like an assignment and fits nicely
inside our brains.

This is not nitpicking. In some languages,
x[y] would give you an lvalue, and then
you would call another method =. Here there
is only one method call, =.

Look at it this way: Suppose the and =
methods were renamed to #get and #set.

You would not expect ENV.get(x).sub! to
change ENV just because ENV.set(x) does so.
Makes sense?

Hal

···

----- Original Message -----
From: “Ian Macdonald” ian@caliban.org
To: “ruby-talk ML” ruby-talk@ruby-lang.org
Sent: Tuesday, June 03, 2003 10:31 PM
Subject: Re: case of sub! not working

I understand your reasoning, but why is = any different to sub! ?
If assignment (=) is just a method call with some syntactic sugar thrown
in, then why is it that sub! tries to modify the outside environment,
while = only modifies the singleton copy?

That’s a very lucid explanation and I find I can now appreciate the
issue a lot more easily.

It’s the fact that the get method is invisible within ‘ENV[foo]=’ that
makes the issue so tricky.

Thanks for taking the time to explain this so well (and repeatedly).

Ian

···

On Wed 04 Jun 2003 at 12:39:20 +0900, Hal E. Fulton wrote:

Look at it this way: Suppose the and =
methods were renamed to #get and #set.

You would not expect ENV.get(x).sub! to
change ENV just because ENV.set(x) does so.
Makes sense?


Ian Macdonald | I never pray before meals – my mom’s a
System Administrator | good cook.
ian@caliban.org |
http://www.caliban.org |
>

No problem. Explaining is the best way to
understand something yourself. :wink:

This probably does belong in the FAQ, as it
is non-obvious.

There are similar confusing issues with certain
other objects, though I can’t think what they are
right now.

Hal

···

----- Original Message -----
From: “Ian Macdonald” ian@caliban.org
To: “ruby-talk ML” ruby-talk@ruby-lang.org
Sent: Tuesday, June 03, 2003 11:30 PM
Subject: Re: case of sub! not working

On Wed 04 Jun 2003 at 12:39:20 +0900, Hal E. Fulton wrote:

Look at it this way: Suppose the and =
methods were renamed to #get and #set.

You would not expect ENV.get(x).sub! to
change ENV just because ENV.set(x) does so.
Makes sense?

That’s a very lucid explanation and I find I can now appreciate the
issue a lot more easily.

It’s the fact that the get method is invisible within ‘ENV[foo]=’ that
makes the issue so tricky.

Thanks for taking the time to explain this so well (and repeatedly).