def [](v) xx; return yy; end # returned value is ignored !?

J

Jean-Hugues ROBERT

Hi,

For some class I am redefining operator []=(x). Works great.

However when I use it, p xx[] = zz prints zz, not the value
returned by my method. It makes some sense yet I would have
thought that the responsibility for that should belong to
my method. Am I missing something ?

class Test
def []=(x)
nil
end
end
p Test.new[] = "hello" # => "hello", I was expecting nil

Yours,

Jean-Hugues
 
R

Robert Klemme

Jean-Hugues ROBERT said:
Hi,

For some class I am redefining operator []=(x). Works great.

However when I use it, p xx[] = zz prints zz, not the value
returned by my method. It makes some sense yet I would have
thought that the responsibility for that should belong to
my method. Am I missing something ?

Yes, it's defined that way (see below).
class Test
def []=(x)
nil
end
end
p Test.new[] = "hello" # => "hello", I was expecting nil

Normally you want

def []=(idx, val)
nil
end

And that will always print val regardless of the return value to enforce
coherence with the simple "x = foo" which always evaluates to foo.

irb(main):007:0> class Foo
irb(main):008:1> def []=(idx, val)
irb(main):009:2> p [idx, val]
irb(main):010:2> nil
irb(main):011:2> end
irb(main):012:1> end
=> nil
irb(main):013:0> Foo.new["a"]="b"
["a", "b"]
=> "b"

Regards

robert
 
M

Mark Hubbart

Am I missing something ?

Short answer: assignment always returns the value assigned, regardless
of the return value of the function assigned to.

If you REALLY need to get around this, try:

Test.new.send:)[]=, "hello")

This eliminates the actual assignment, and treats it as a simple method
call. The return value is respected.

HTH,
--Mark
 
M

Mark Sparshatt

Mark said:
Am I missing something ?


Short answer: assignment always returns the value assigned, regardless
of the return value of the function assigned to.

If you REALLY need to get around this, try:

Test.new.send:)[]=, "hello")

Actually there's an easier way, you can just use

Test.new.[]= "hello"
 
M

Mark Hubbart

If you REALLY need to get around this, try:

Test.new.send:)[]=, "hello")

Actually there's an easier way, you can just use

Test.new.[]= "hello"

Ahhh. You're right; I guess it works differently with the brackets.

This behavior will not, however, translate to #foo=()...

Test.new.foo=("hello")
==>"hello"
Test.new.send:)foo=, "hello")
==>nil


regardless, It's not considered kosher to expect a return value from an
assignment to be different from the value being assigned.

--Mark
 
J

Jean-Hugues ROBERT

Jean-Hugues ROBERT said:
Hi,

For some class I am redefining operator []=(x). Works great.

However when I use it, p xx[] = zz prints zz, not the value
returned by my method. It makes some sense yet I would have
thought that the responsibility for that should belong to
my method. Am I missing something ?

Yes, it's defined that way (see below).

Humm, things are the way they are. When I get annoyed by my
kinds questions I end up answering "that's because it's been
that way for billion years". I am there quoting the E.T. answer
in movie Contact by Robert Zemeckis.

class Test
def []=(x)
nil
end
end
p Test.new[] = "hello" # => "hello", I was expecting nil

Normally you want

def []=(idx, val)
nil
end

And that will always print val regardless of the return value to enforce
coherence with the simple "x = foo" which always evaluates to foo.

"normally" is relative. Proc class defines some def [*args] call( *args) end
and this is rather convenient.

Coherence is a nice thing.

However, it this case it makes it *IMPOSSIBLE* to implement "by ref" versus
"by value" semantic in Ruby (this is probably *one* of the reasons, not the
only one). I hate to state that something is impossible in Ruby. Additionnaly
"Impossible is not French" quoting Napoleon. Let's say it is "difficult" and
let's hope it not an euphemism.

I am currently implementing a LogicVariable class. Ideally a LogicVariable
is exactly like a variable, wherever you can use a variable, you should
be able to use a LogicVariable.

This is similar to remote objects (on some other plane),
wherever you can use an object, you can use a remote object.
The remote object is a "proxy" for the actual
object. In this example, adding a level of indirection solve the issue
of transparent distribution.

So I want to do something similar with variables (which in Ruby today are
not Objects, whoever said "everything in Ruby is an Object" was almost right)

A LogicVariable is a "proxy" to a regular variable. The difference is
related to the fact that a LogicVariable is either "bound" or "free",
meaning "it has a value" or "it has no value". In Ruby all variables
are "bound", even if to nil (most variables actually don't exist at all,
as defined? can tell, this is another path I may want to explore).

LogicVariable is just an example of something impossible to do. Basic
References are impossible to do too. There is no way you can *transparently*
use a Reference to a variable instead of the variable's content itself.

This may be an academic discussion and one may think that I should
use a language with By Reference semantic if I really need it. OTOH,
if there is value in By Reference, it may prove interesting to introduce
that well known concept in Ruby.

How to do that is yet to be determined. But as I progress in prototyping
it, I am collecting requirements. That []= would control the expression
value is probably one of then. Once I am done, I will summarize my
discoveries and (if it makes sense) I will issue a RCR.

Thanks for your help.

Yours,

Jean-Hugues

irb(main):007:0> class Foo
irb(main):008:1> def []=(idx, val)
irb(main):009:2> p [idx, val]
irb(main):010:2> nil
irb(main):011:2> end
irb(main):012:1> end
=> nil
irb(main):013:0> Foo.new["a"]="b"
["a", "b"]
=> "b"

Regards

robert
 
J

Jean-Hugues ROBERT

Mark said:
Am I missing something ?


Short answer: assignment always returns the value assigned, regardless of
the return value of the function assigned to.

If you REALLY need to get around this, try:

Test.new.send:)[]=, "hello")

Actually there's an easier way, you can just use

Test.new.[]= "hello"
This eliminates the actual assignment, and treats it as a simple method
call. The return value is respected.

HTH,
--Mark

x.[]= y instead of x[] = y, Right.

All of this is going in the opposite direction from what I need to
implement a transparent Reference to a lvalue (kind of a "proxy" for
a variable instead of a "proxy" for an object).

Using r[] = zzz for References instead of plain x = zzz for regular variable is
not very transparent, using r.[]= is even less I guess. But it does
work and in the absence of anything better it is worth mentioning.

Thanks.

Jean-Hugues
 
J

Jean-Hugues ROBERT

Short answer: assignment always returns the value assigned, regardless of
the return value of the function assigned to.

OK. I guess I have to accept that.
If you REALLY need to get around this, try:

Test.new.send:)[]=, "hello")

This eliminates the actual assignment, and treats it as a simple method
call. The return value is respected.

OK. Thanks.

I actually don't want to avoid the actual assignment, I want to
control what get assigned.

This send() gets rid of the syntax sugar of the compiler where
(x[y]=z)
becomes
(tmp = z, x.[]=( y, tmp), tmp)

If compiler/language was to assume that .[]= does what it is supposed
to do and knows what it does, it would save some CPU cycles.

Many thanks,

Yours,

Jean-Hugues
 
M

Mark Hubbart

Newsbeitrag
Hi,

For some class I am redefining operator []=(x). Works great.

However when I use it, p xx[] = zz prints zz, not the value
returned by my method. It makes some sense yet I would have
thought that the responsibility for that should belong to
my method. Am I missing something ?

Yes, it's defined that way (see below).

Humm, things are the way they are. When I get annoyed by my
kinds questions I end up answering "that's because it's been
that way for billion years". I am there quoting the E.T. answer
in movie Contact by Robert Zemeckis.

It wasn't always that way. Calling "Foo.bar = value" used to respect
#bar='s return value. Later, it was decided by matz that consistancy
was best, and the behavior was changed to be consistant with the
behavior of the normal assignment operator.

One reason for this is that people would tend to expect this behavior,
and perhaps not think about return values when writing the functions.
So the following code might not do what is expected.

class Foo
def bar=(val)
@bar = val.to_i
end
end

f = Foo.new
g = f.bar = h = "23"

In this case, you would probably expect g, h and f.bar to have been
assigned the same way. If the return value of #bar= is respected,
however, h and g would have different values.

cheers,
--Mark
 
J

Jean-Hugues ROBERT

Hi,

For some class I am redefining operator []=(x). Works great.

However when I use it, p xx[] = zz prints zz, not the value
returned by my method. It makes some sense yet I would have
thought that the responsibility for that should belong to
my method. Am I missing something ?

Yes, it's defined that way (see below).

Humm, things are the way they are. When I get annoyed by my
kinds questions I end up answering "that's because it's been
that way for billion years". I am there quoting the E.T. answer
in movie Contact by Robert Zemeckis.

It wasn't always that way. Calling "Foo.bar = value" used to respect
#bar='s return value. Later, it was decided by matz that consistancy was
best, and the behavior was changed to be consistant with the behavior of
the normal assignment operator.

One reason for this is that people would tend to expect this behavior, and
perhaps not think about return values when writing the functions. So the
following code might not do what is expected.

class Foo
def bar=(val)
@bar = val.to_i
end
end

f = Foo.new
g = f.bar = h = "23"

In this case, you would probably expect g, h and f.bar to have been
assigned the same way. If the return value of #bar= is respected, however,
h and g would have different values.

cheers,
--Mark

That makes sense. Yet, I am missing the xxx= where I do control the value
assigned to the lvalue.
I am not alone. At this point there are multiple known cases where it would
be needed for transparency:
- Reference, a reference is an indirect mean of access to a lvalue's
value that is dereferenced when the value is needed and that also makes it
possible to assign a value to the lvalue at any time.
- Lazy, a Lazy is a value that is computed when it is needed, not before.
- Future, a Future is the returned value of an asynchronous method call
that is waited for when it is needed, not before.
- LogicVariable, a LogicVariable is a variable that can be free in
addition to being bound to some value as regular variables are.

Yours,

Jean-Hugues Robert
 
D

David Alan Black

Hi --

Jean-Hugues ROBERT said:
Coherence is a nice thing.

However, it this case it makes it *IMPOSSIBLE* to implement "by ref" versus
"by value" semantic in Ruby (this is probably *one* of the reasons, not the
only one). I hate to state that something is impossible in Ruby. Additionnaly
"Impossible is not French" quoting Napoleon. Let's say it is "difficult" and
let's hope it not an euphemism.

There's nothing wrong with something being impossible in Ruby. Ruby
is flexible and dynamic, but it's still a particular programming
language, designed a certain way with certain perfectly acceptable
consequences. There's no shame in Ruby's failing to supply everything
needed for every possible paradigm or programming technique or style.


David
 
M

Mark Hubbart

That makes sense. Yet, I am missing the xxx= where I do control the
value assigned to the lvalue.
I am not alone. At this point there are multiple known cases where it
would be needed for transparency:
- Reference, a reference is an indirect mean of access to a lvalue's
value that is dereferenced when the value is needed and that also
makes it possible to assign a value to the lvalue at any time.
- Lazy, a Lazy is a value that is computed when it is needed, not
before.
- Future, a Future is the returned value of an asynchronous method
call that is waited for when it is needed, not before.
- LogicVariable, a LogicVariable is a variable that can be free in
addition to being bound to some value as regular variables are.

I'm not sure what the problem is... What sort of circumstance will this
cause a problem? Perhaps you are thinking that assignment should do
something more than it was intended to.

Using your Pointer example, you could do this:

p = Pointer.new()
x = p[] = "hello"
(p[] = "hello").inspect

In line 2, would you expect something other than a simple "hello"
string to be assigned to x?
In line 3, would you expect #inspect to be called on p, rather than on
the assigned value?

You say that these are 'known cases', quite possibly I am ignorant
about this, but I don't see how you couldn't have an object that
computes it's value only when requested, and how assignement would be
at fault. Maybe a short example of a problem-causing situation would
help.

--Mark
 
J

Jean-Hugues ROBERT

Hi --



There's nothing wrong with something being impossible in Ruby. Ruby
is flexible and dynamic, but it's still a particular programming
language, designed a certain way with certain perfectly acceptable
consequences. There's no shame in Ruby's failing to supply everything
needed for every possible paradigm or programming technique or style.

Nothing wrong, I for sure agree. And "by ref" is probably not something very
common (yet it is useful). OTOH, I'll keep investigating what is missing to
implement it.

If only a few things are missing (I suspect this is the case), I'll provide
a prototype implementation in an RCR. It may then prove worthwhile to introduce
the missing parts, assuming they have no or very acceptable drawbacks.

At this point I believe that the key missing mechanism is some kind of a
Lvalue Class. More on this when I am done.

The reason I "hate" stating that something is impossible in Ruby is mainly
fear that people may take it as a critic, where I would want it to be taken
as a challenge. I guess "hate" was a bad verb, sorry about that.

Yours,

Jean-Hugues
 
J

Jean-Hugues ROBERT

I'm not sure what the problem is... What sort of circumstance will this
cause a problem? Perhaps you are thinking that assignment should do
something more than it was intended to.

Something more than was intended, Yes, but only when the assignee is a
Reference. This requires
a change in Ruby implementation. What for ?
A Lazy is a very good example: the invoked method does need not to know
about it, it uses it as a regular
object. In Ruby today, the invoked method needs to call some type of
value() checking first
that something.kind_of? Lazy. Not very transparent.
Using your Pointer example, you could do this:

p = Pointer.new()
x = p[] = "hello"
(p[] = "hello").inspect

In line 2, would you expect something other than a simple "hello" string
to be assigned to x?

something else ? No. However if p was a Reference, instead of a Pointer, I
would expect x to be assigned p
instead of "hello".
In line 3, would you expect #inspect to be called on p, rather than on the
assigned value?

No. Your example of using a Pointer works today as it should. However,
using a Reference
instead of a Pointer, I would get rid of the [] and []= to achieve the same
effect.
You say that these are 'known cases', quite possibly I am ignorant about
this, but I don't see how you couldn't have an object that computes it's
value only when requested, and how assignement would be at fault. Maybe a
short example of a problem-causing situation would help.

The issue is about "when requested". With a pointer it is when .[]() is
called. With a Reference
is it transparent, p() get the value when it needs it (when it uses it), it
does not care about
whether its parameter is a Reference or not.

For sure some example is welcome, here is one, about the difference between
a Pointer
(that you can implement decently in Ruby today) and a Reference (that
requires a change
in the Ruby interpretor) and how a Reference makes a transparent Lazy possible.

In this context I assume that the definition of a Reference is
something like:
A Reference is like a Pointer that is automatically dereferenced
to access the underlying value.

p = Pointer.new() # An anonymous Pointer, it holds the value itself.
x = p[] = "hello"
(p[] = "hello").inspect
meth_by_ref( p)
p[].inspect # => ["hello","world"]
p = meth_by_val( p[])
p.inspect # => ["hello", "world"]
...
def meth_by_ref( x )
x[] = [x[],"world"]
end
def meth_by_val( x )
[x, "world"]
end

A Pointer object requires explicit syntax to access the underlying
value:
syntax "ptr[]" means "content of ptr".
syntax "ptr[] = xx" means "the content of ptr is assigned the value of xx"

---

r = Reference.new() # An anonymous Reference, it holds the value itself.
r = "hello"
r.inspect
meth( r)
r.inspect # => ["hello", "world"]
...
def meth( x )
x = [x, "world"]
end

Result:
Thanks to Reference a method can change the value of a non local lvalue if
it is provided a Reference to an object instead of the object itself.
Yet, it can work with plain direct objects too.
It is up to the caller to decide.

As of today there is no way to implement the Reference class in Ruby.

I hope this example gives you some insight of what can be done with a
Reference and how it can help reduce the code size sometimes:

class Lazy < Reference
attr: block
attr: ready
def initialize( &ablock )
@ready = false
@block = ablock
end
def getter() # gets called at runtime when Reference's value is needed
if !@ready then
setter( @block.call())
@ready = true
end
super()
end
def setter(x) # gets called at runtime when assigning to a Reference object
super(x) unless @ready
raise "not supported, read only"
end
end

v = long_method()
p v
v = Lazy.new { long_method() }
p v

Expected behaviour:
Without Lazy, long_method() is invoked immediatly
With Lazy, long_method() is invoked when value is needed by p()
The Key Point: p() does not need to know about that.
Nota: getter()/setter() are bad names, some better scheme need to be designed

You may note the similarity with the "proxy" pattern, as
applied to Remote Objects: existing code keeps working for
remote objects as it used to work for local ones, it is
transparent.

Reference provides a similar benefit for lvalues.

Yours,

Jean-Hugues
 
D

Dan Doel

I'm not quite sure agree with what what you're saying.

Ruby does have references. Every variable is a reference. For example:

def foo(str)
str << " baz"
end

x = "bar"
foo x
p x # => "bar baz"

The only thing you can't do is assign back to local variables in another
scope. The only reason you can do this in C (for example) is because you're
dealing with memory explicitly, so nothing is immutable (excepting constants).
If every object in Ruby were mutable, we might not be having this discussion.

What you're really doing when you wrap something like an integer is making an
immutable object appear mutable. We already have references.

About laziness: there aren't many languages with built-in lazy evaluation.
Haskell is the only one I know of. When you do lazy evaluation where not
everything is lazy, you need to have explicit syntax both ways, like:

(let (x (delay (foo y))) ; makes x point to the delayed result of (foo y)
(bar (force x))) ; calls bar with (foo y)

Ruby even has this level of lazy evaluation with blocks (as do all langauges
with lambda expressions, although making a delay macro in Lisp is a little
more convenient).

If you want lazy initialization, you can write a proxy that behaves exactly
the same as the underlying object (after all, an object is more or less
defined by what messages it responds to, and how it does so) by simply
mirroring all methods with #method_missing.

In fact, you could use exclusively proxies, and the only thing you'd have to
change is assignment to get what you desire (I think). Like:

def assign(obja, objb)
obja.value = objb.value
end

x = Proxy(obj1)
y = Proxy(obj2)

# use x and y
assign(x, y)
# now x == y

You could have the capability to have assigning to one variable assign to
another as a side effect, but I think that would be confusing, especially
since Ruby doesn't have declared varables. For example suppose:

x = ... # is a normal variable
r = ... # is a reference to x
y = r

Now, is y a reference to variable x, or is it the object that x refers to
(apologies for the confusing language)? If it's one, how do I get the
other? If it's the former, I'd need to do r.value or something, For the latter
I'd need to use the reference notation again. So you don't gain any calrity.
It'd be no better than rolling your own.

Also, how would you assign to r without changing x, supposing you wanted to?
What if you wanted to make r refer to another variable? You can't just assign
a new reference to it, because that'd make r a reference to a reference to an
object (which might work), but it would make x a reference to that variable,
which probably wasn't intended.

Any solution would require declaration of variables, because you'd need to
specify which are regular and which are reference variables. That's something
of a disadvantage. And the benefit would be non-obvious assignment side
effects, which are of dubious value if you ask any functional purist. :)

One last thing and I'll wrap this up because it's getting too long. The main
use for reference variables as they're used in C/C++ is for out parameters,
because you can only return one value from a function easily (you can wrap
multiple return values in a struct and such, but that's messy). This, however,
is easily done in Ruby, since you can do multiple assignment with implicit
arrays. The only thing I can think of that's anything like out parameters
I've seen used in Ruby is with blocks, like:

callcc { |foo.vaule| # implicitly does foo.value = continuation }

However, I think that's being done away with in favor of explicit assignment:

callcc { |cc| foo.value = cc }

Anyhow, we can agree to disagree, I suppose. :) The discussion is interesting
and I can see the use of having this. The only problem is that the situations
where you use it feel like (to me) "I shouldn't be doing it this way at all"
situations.

Cheers. And sorry for the long post.

- Dan
 
K

Kristof Bastiaensen

There is a problem with treating an lvalue this way, and that is
that not every lvalue is an storage location. In fact only
variables as an lvalue are storage locations, the other ones are
methods (i.e.: a[]=5 means a.[]=(5), a.foo=bar calls the method
foo=(bar) on a).

I wouldn't welcome the introduction of references on Ruby,
because it may mess things up. Let's say the method "alter"
takes a reference, and changes the value. Then calling
alter(a) will change the value of a, but this is not obvious
when invoking this method, or look at the code.

It may be interesting to be able to access variables indirectly
using binding() (outside eval).
for example:

a = 2
binding().local_get:)a)
=> a == 2

binding().local_set!:)a, 5)
=> a == 5

And also Binding::ivar_set!, Binding::ivar_get and
Binding::get_self
 
R

Robert Klemme

Jean-Hugues ROBERT said:
At 01:49 01/05/2004 +0900, you wrote:
Hi,

For some class I am redefining operator []=(x). Works great.

However when I use it, p xx[] = zz prints zz, not the value
returned by my method. It makes some sense yet I would have
thought that the responsibility for that should belong to
my method. Am I missing something ?

Yes, it's defined that way (see below).

Humm, things are the way they are. When I get annoyed by my
kinds questions I end up answering "that's because it's been
that way for billion years". I am there quoting the E.T. answer
in movie Contact by Robert Zemeckis.

It wasn't always that way. Calling "Foo.bar = value" used to respect
#bar='s return value. Later, it was decided by matz that consistancy was
best, and the behavior was changed to be consistant with the behavior of
the normal assignment operator.

One reason for this is that people would tend to expect this behavior, and
perhaps not think about return values when writing the functions. So the
following code might not do what is expected.

class Foo
def bar=(val)
@bar = val.to_i
end
end

f = Foo.new
g = f.bar = h = "23"

In this case, you would probably expect g, h and f.bar to have been
assigned the same way. If the return value of #bar= is respected, however,
h and g would have different values.

cheers,
--Mark

That makes sense. Yet, I am missing the xxx= where I do control the value
assigned to the lvalue.

Well, you can get close by using the same approach that OpenStruct uses: you
need an instance to host all variables and then you can fully control the
behavior of assignment. A simple example:

class Scope
def method_missing(sym, *args)
str = sym.to_s

case str
when /^(.+)=$/
define_member($1)
else
raise ArgumentError unless args.empty?
define_member(str)
end

send(sym, *args)
end

def define_member(name)
eval "def self.#{name}=(x);@#{name}=x;end"
eval "def self.#{name}();@#{name};end"
end
end


irb(main):058:0> env = Scope.new
=> #<Scope:0x101725e8>
irb(main):059:0> env.x
=> nil
irb(main):060:0> env.x=100
=> 100
irb(main):061:0> env.y="foo"
=> "foo"
irb(main):062:0> env.y
=> "foo"
irb(main):063:0> env
=> #<Scope:0x101725e8 @x=100, @y="foo">

Now you can modify those methods that are defined as accessors in
define_member() in any way you like and thus control the value assigned.
It's not the full integration into the language that you are looking for,
but it might come close enough.

The problem is that to achieve what you want the language would need to be
radically changed and I don't think it's a good idea to allow for global
redefinition of =. That could wreak too much havoc on existing code.

Btw, by adding:

class Scope
def with(&b)
instance_eval &b
end
end

You can use variables that you have defined already quite naturally:

irb(main):034:0> env.x=10
=> 10
irb(main):035:0> env.with { p x; x = 20; p x; p self }#
10
20
I am not alone. At this point there are multiple known cases where it would
be needed for transparency:
- Reference, a reference is an indirect mean of access to a lvalue's
value that is dereferenced when the value is needed and that also makes it
possible to assign a value to the lvalue at any time.
- Lazy, a Lazy is a value that is computed when it is needed, not
before.

You don't necessarily need references for that. Typically it is used as a
member and you can do it this way:

class Foo
def lazy=(x);@lazy=x;end
def lazy
if @lazy.nil?
@lazy = compute_lazy()
end
@lazy
end
end

You can even automate that by providing blocks that do the initialization
calculation.
- Future, a Future is the returned value of an asynchronous method call
that is waited for when it is needed, not before.
- LogicVariable, a LogicVariable is a variable that can be free in
addition to being bound to some value as regular variables are.

IMHO there are lots of ways to do what you want in Ruby, only the exact way
you want is not possible. Sometimes it's better to step back and open one's
mind for other solutions. As I suggested before, a Hash can pretty much do
what you want - it just doesn't give you the exact syntactic sugar you want.

env = Hash.new do |h,key|
# do whatever is needed to calculate the value of key
end

env[ :x ] = true
env[ :y ] = false
env[ :x ] && env[ :y ]
....

Or, with the example above:

env.x=true
env.y=false
env.x && env.y
....

Regards

robert
 
J

Jean-Hugues ROBERT

There is a problem with treating an lvalue this way, and that is
that not every lvalue is an storage location. In fact only
variables as an lvalue are storage locations, the other ones are
methods (i.e.: a[]=5 means a.[]=(5), a.foo=bar calls the method
foo=(bar) on a).

Ruby is cool, a lvalue can be a *method call*.
So when I say "lvalue" I mean Ruby's ones, not the subset that some
other languages provide.

I believe my version of Pointer works with any Ruby valid lvalue:
a = [1,2,3]
ptr = Pointer.new{ "a[2]"}
ptr[] = 4
p a # => [1,2,4]
See it at end of page http://www.c2.com/cgi/wiki?SinisterSchemeSampleInRuby
I wouldn't welcome the introduction of references on Ruby,
because it may mess things up. Let's say the method "alter"
takes a reference, and changes the value. Then calling
alter(a) will change the value of a, but this is not obvious
when invoking this method, or look at the code.

I agree that using reference is often a bad thing. I came to
realize that I needed them for some very special code that I
am prototyping. Usually I really don't miss them at all.
But when you need it hard, you miss it hard :)
It may be interesting to be able to access variables indirectly
using binding() (outside eval).
for example:

a = 2
binding().local_get:)a)
=> a == 2

You can !
eval( :a, binding()) ?
binding().local_set!:)a, 5)
=> a == 5

eval( "a = 5") or
tmp = arbitrary_expr; eval( "a=tmp", binding())
And also Binding::ivar_set!, Binding::ivar_get and
Binding::get_self

eval( "@a", binding)
tmp = expr; eval( "@a = tmp", a_binding)
that_self = eval( "self", a_ binding)

Yours,

Jean-Hugues
 
S

Simon Strandgaard

Jean-Hugues ROBERT said:
Ruby is cool, a lvalue can be a *method call*.
So when I say "lvalue" I mean Ruby's ones, not the subset that some
other languages provide.

I believe my version of Pointer works with any Ruby valid lvalue:
a = [1,2,3]
ptr = Pointer.new{ "a[2]"}
ptr[] = 4
p a # => [1,2,4]
See it at end of page http://www.c2.com/cgi/wiki?SinisterSchemeSampleInRuby

I have made iterator package, which does the same,
plus a few other goodies (continuation-iterator), see
http://raa.ruby-lang.org/list.rhtml?name=iterator

Only difference I see, is that you use a String, where I use a reference.
Any advantages in using a String over a reference ?


irb(main):001:0> require 'iterator'
=> true
irb(main):002:0> a = [1,2,3]
=> [1, 2, 3]
irb(main):003:0> ptr = a.create_iterator
=> #<Iterator::Collection:0x8190324 @position=0, @data=[1, 2, 3]>
irb(main):004:0> ptr.next(2)
=> #<Iterator::Collection:0x8190324 @position=2, @data=[1, 2, 3]>
irb(main):005:0> ptr.current = 4
=> 4
irb(main):006:0> p a
[1, 2, 4]
=> nil
 
K

Kristof Bastiaensen

Hi,

You can !
eval( :a, binding()) ?

I would rather get rid of the eval, because eval
has to recompile the statement, and I have the feeling it
is not really part of the language (it is more like
the language itself). From the point of a byte-code
interpreter, the eval statement doesn't generate a
bytecode, but will call a method that will do so.
eval( "a = 5") or
tmp = arbitrary_expr; eval( "a=tmp", binding())

The behaviour would be different if a is not set.
Eval would raise an error, while local_get:)a)
would just return nil.
 

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,763
Messages
2,569,562
Members
45,038
Latest member
OrderProperKetocapsules

Latest Threads

Top