Hi,
is it possible to write a method that can “clear” a parameter in Ruby?
That is can a write a method “push” such that for the code below:
x = "Hello"
string_stack.push(x)
puts x
the output will be nil instead of “Hello”?
Hi,
is it possible to write a method that can “clear” a parameter in Ruby?
That is can a write a method “push” such that for the code below:
x = "Hello"
string_stack.push(x)
puts x
the output will be nil instead of “Hello”?
Hi,
is it possible to write a method that can “clear” a parameter in Ruby?
That is can a write a method “push” such that for the code below:x = "Hello" string_stack.push(x) puts x
the output will be nil instead of “Hello”?
Short answer is no.
Long answer is: If your parameter is something like
a String or an Array, you could do a ‘replace’ on
its contents. Likewise if it’s any complex object
whose state can change, you can change its state.
However, assignment works on variables, not objects.
In general it’s impossible to write a method that
knows the name of the variable passed to it, and
so it’s impossible to assign to the variable that
was passed into the method. You can manipulate the
object, but not the variable.
HTH,
Hal
----- Original Message -----
From: “Roy Patrick Tan” rtan@vt.edu
Newsgroups: comp.lang.ruby
To: “ruby-talk ML” ruby-talk@ruby-lang.org
Sent: Monday, August 04, 2003 12:36 PM
Subject: clearing a parameter in Ruby?
–
Hal Fulton
hal9000@hypermetrics.com
No. x is a local variable that refers to “Hello”. A method can’t affect an
outer local variable.
Why do you wish to do this? We might be able to help you figure out a better
way to do what you’re trying to do.
-austin
On Tue, 5 Aug 2003 02:36:32 +0900, Roy Patrick Tan wrote:
is it possible to write a method that can “clear” a parameter in Ruby?
That is can a write a method “push” such that for the code below:x = “Hello”
string_stack.push(x)
puts xthe output will be nil instead of “Hello”?
–
austin ziegler * austin@halostatue.ca * Toronto, ON, Canada
software designer * pragmatic programmer * 2003.08.04
* 14.23.07
As has already been mentioned the short answer is no.
The alternative answer is that the desired effect might be acheived
using SimpleDelegator.
e.g.
require ‘delegate’
def push(x)
x.setobj(nil)
end
x = SimpleDelegator.new(“Hello”)
puts x
push(x)
puts x
TTFN,
Geoff.
On Tue, Aug 05, 2003 at 02:36:32AM +0900, Roy Patrick Tan wrote:
Hi,
is it possible to write a method that can “clear” a parameter in Ruby?
That is can a write a method “push” such that for the code below:
x = “Hello”
string_stack.push(x)
puts x
the output will be nil instead of “Hello”?
I don’t recommend this (because I think I would get really annoyed if I
were using a library that did this).
But with the above disclaimer, you could do it this way:
class Pusher
def initialize
@stack = Array.new
end
def push(&block)
sym = block.call
@stack.push(eval(sym.to_s, block))
eval "#{sym.to_s} = nil", block
end
end
s = Pusher.new
x = “HI”
s.push { :x }
p x # => nil
On Mon, 2003-08-04 at 13:36, Roy Patrick Tan wrote:
Hi,
is it possible to write a method that can “clear” a parameter in Ruby?
That is can a write a method “push” such that for the code below:x = "Hello" string_stack.push(x) puts x
the output will be nil instead of “Hello”?
“Beware of bugs in the above code; I have only proved it correct,
not tried it.” – Donald Knuth (in a memo to Peter van Emde Boas)
Austin Ziegler wrote:
is it possible to write a method that can “clear” a parameter in Ruby?
That is can I write a method “push” such that for the code below:x = “Hello”
string_stack.push(x)
puts xthe output will be nil instead of “Hello”?
…
Why do you wish to do this? We might be able to help you figure out a better
way to do what you’re trying to do.
In essence, what I’m trying to do is create a set of container classes
that, when an object is inserted into a container, the container
guarantees that the object does not change state until it is taken out
again.
The problem is that in Ruby (and almost all modern imperative languages)
two variables can refer to the same object. So part of the solution is
never to use assignment except when creating an object (if you need a
copy of an object, clone it). But that still leaves us w parameter
passing, since a variable in the caller environment refers to an object
that is also referred to by a variable in the called method… so I
wanted to be able to clear the caller’s variable.
I thought of using a SimpleDelegator in a fashion similar to Mr. Young’s
solution:
x = SomeComplexObject.new
x = SimpleDelegator.new(x)
push(x)
But I was hoping there was a simple way to achieve this (for example,
using something similar to TCL’s upvar).
I guess your real question is, what kind of software am I building that
requires these kind of components? I don’t really need them, I was
writing what was supposed to be a quick and dirty program when I
realized how totally reliant I am on aliasing, and wondered how easy it
would be to implement in Ruby some of the non-aliasing components I’ve
been studying.
Anyway thanks to everyone who took the time to answer my question
On Tue, 5 Aug 2003 02:36:32 +0900, Roy Patrick Tan wrote:
[snip]
In essence, what I’m trying to do is create a set of container classes
that, when an object is inserted into a container, the container
guarantees that the object does not change state until it is taken out
again.
This sounds a little like a tuple.
See http://sourceforge.net/project/showfiles.php?group_id=50485
which includes an implementation of a tuple class (a container that is
ordered and immutable).
The code, which is not very long, is at the bottom of this page:
The problem is that in Ruby (and almost all modern imperative
languages) two variables can refer to the same object. So part of the
solution is never to use assignment except when creating an object (if
you need a copy of an object, clone it). But that still leaves us w
parameter passing, since a variable in the caller environment refers
to an object that is also referred to by a variable in the called
method… so I wanted to be able to clear the caller’s variable.
I don’t understand the problem here. Why are the variables important as
long as you are passing the object around? Every value in Ruby is also
an object – even if it’s assigned to a variable within a class, an
instance of a class or a method.
I still don’t understand what you want your program to do.
On Monday, August 4, 2003, at 03:56 PM, Roy Patrick Tan wrote:
[snip]
In essence, what I’m trying to do is create a set of container classes
that, when an object is inserted into a container, the container
guarantees that the object does not change state until it is taken out
again.
Hmm, perhaps just freeze the object when you
store it?
Hal
----- Original Message -----
From: “Roy Patrick Tan” rtan@vt.edu
Newsgroups: comp.lang.ruby
To: “ruby-talk ML” ruby-talk@ruby-lang.org
Sent: Monday, August 04, 2003 2:56 PM
Subject: Re: clearing a parameter in Ruby?
But there may well not be any variable to clear:
foo("hello") # immediate object
foo(MAX_ENTRIES) # constant
foo(x + 0) # expression
foo(bar()) # expression
foo(Baz.new) # expression
What gets passed in to the method as an argument is an object reference,
which may or may not have been stored in a local variable as an intermediate
stage.
“Never use assignment except when creating an object” also seems a strange
rule, as I think it would rule out “a = a + 1”, for example.
If the actual issue is “object cannot be changed while it is in the
container” then maybe you should look at Object#freeze. If you ‘dup’ it out
of the container then the copy looses the frozen status.
Regards,
Brian.
On Tue, Aug 05, 2003 at 04:56:50AM +0900, Roy Patrick Tan wrote:
The problem is that in Ruby (and almost all modern imperative languages)
two variables can refer to the same object. So part of the solution is
never to use assignment except when creating an object (if you need a
copy of an object, clone it). But that still leaves us w parameter
passing, since a variable in the caller environment refers to an object
that is also referred to by a variable in the called method… so I
wanted to be able to clear the caller’s variable.
Austin Ziegler wrote:
Why do you wish to do this? We might be able to help you figure out a
better way to do what you’re trying to do.
In essence, what I’m trying to do is create a set of container classes
that, when an object is inserted into a container, the container
guarantees that the object does not change state until it is taken out
again.
class ImmutablesArray < Array
def push(it)
it.freeze
super
end
end
Roughly. There’s a few other methods you would want to implement (like #pop)
to unfreeze as you pop the item, but this should work in general.
The problem is that in Ruby (and almost all modern imperative languages)
two variables can refer to the same object.
So can C++.
If you want objects in Ruby immutable, #freeze them.
I guess your real question is, what kind of software am I building that
requires these kind of components? I don’t really need them, I was
writing what was supposed to be a quick and dirty program when I realized
how totally reliant I am on aliasing, and wondered how easy it would be
to implement in Ruby some of the non-aliasing components I’ve been
studying.
I’m not sure what you mean by “aliasing” here.
-austin
“Roy Patrick Tan” rtan@vt.edu schrieb im Newsbeitrag
news:bgmcv4$orh$1@solaris.cc.vt.edu…
Austin Ziegler wrote:
is it possible to write a method that can “clear” a parameter in Ruby?
That is can I write a method “push” such that for the code below:x = “Hello”
string_stack.push(x)
puts xthe output will be nil instead of “Hello”?
…
Why do you wish to do this? We might be able to help you figure out a
better
way to do what you’re trying to do.In essence, what I’m trying to do is create a set of container classes
that, when an object is inserted into a container, the container
guarantees that the object does not change state until it is taken out
again.
class SomeContainer
def add_1(obj)
add_internal obj.clone.freeze
end
def add_2(obj)
add_internal Marshal.load(Marshal.dump(obj))
end
private
def add_internal(obj)
# put into the collection
end
end
The problem here is that you typically deal with graphs of instances. If
you freeze only the one put into the collection, there might still be
changes possible that defy your aim. If you copy a complete graph you are
sure that nobody changes state but you might loose references to instances
that you wanted to keep. It’s a tradeoff.
I guess your real question is, what kind of software am I building that
requires these kind of components? I don’t really need them, I was
writing what was supposed to be a quick and dirty program when I
realized how totally reliant I am on aliasing, and wondered how easy it
would be to implement in Ruby some of the non-aliasing components I’ve
been studying.
Aha! Akademic research.
Regards
robert
On Tue, 5 Aug 2003 02:36:32 +0900, Roy Patrick Tan wrote:
wrote (more or less):
The problem is that in Ruby (and almost all modern imperative languages)
two variables can refer to the same object. So part of the solution is
never to use assignment except when creating an object (if you need a
copy of an object, clone it). But that still leaves us w parameter
passing, since a variable in the caller environment refers to an object
that is also referred to by a variable in the called method… so I
wanted to be able to clear the caller’s variable.But there may well not be any variable to clear:
foo(“hello”) # immediate object
foo(MAX_ENTRIES) # constant
foo(x + 0) # expression
foo(bar()) # expression
foo(Baz.new) # expressionWhat gets passed in to the method as an argument is an object reference,
which may or may not have been stored in a local variable as an intermediate
stage.“Never use assignment except when creating an object” also seems a strange
rule, as I think it would rule out “a = a + 1”, for example.
Welcome to the Smalltalk-ey world of a.add(1)
If the actual issue is “object cannot be changed while it is in the
container” then maybe you should look at Object#freeze. If you ‘dup’ it out
of the container then the copy looses the frozen status.
Cheers,
Euan
Gawnsoft: http://www.gawnsoft.co.sr
Symbian/Epoc wiki: http://html.dnsalias.net:1122
Smalltalk links (harvested from comp.lang.smalltalk) http://html.dnsalias.net/gawnsoft/smalltalk
On Tue, 5 Aug 2003 07:23:34 +0900, Brian Candler B.Candler@pobox.com
On Tue, Aug 05, 2003 at 04:56:50AM +0900, Roy Patrick Tan wrote:
Austin Ziegler wrote:
…
class ImmutablesArray < Array
def push(it)
it.freeze
super
end
endRoughly. There’s a few other methods you would want to implement (like #pop)
to unfreeze as you pop the item, but this should work in general.
You can’t ``unfreeze’’ frozen objects (this should be quite easy in C b.t.w.) .
…
/Christoph