Freezing Variable Assignment

  • Thread starter Nicholas Van Weerdenburg
  • Start date
N

Nicholas Van Weerdenburg

Hi,

Is there a feature to freeze variable assignment?

e.g.
a="hello"
a.assignfreeze
a="goodbye" # ===> generates exception

Or, in a related vein, a type freeze, so that only similar objects can be added.

I realize that constants offer assignment freezing to a certain degree.

The reason I ask, is that I stepped over-top of some framework
variables today, and it was hard to find out what was going on. Where
as ruby protects keywords, it would be nice if frameworks or custom
domain specific languages could do the same.

Thanks,
Nick
 
D

David A. Black

Hi --

Hi,

Is there a feature to freeze variable assignment?

e.g.
a="hello"
a.assignfreeze
a="goodbye" # ===> generates exception

I tend to think this would be a pretty radical reconceptualization of
how variable identifiers relate to objects, rather than just a
feature. At the very least it would probably have to be something
like:

freeze_identifier:)a)

as opposed to sending a message to the object referenced by 'a'. (In
your example you'd be sending the message 'assignfreeze' to the string
"hello".)
Or, in a related vein, a type freeze, so that only similar objects can be added.

You'd have to define 'type' and/or 'similar object', which isn't
always easy :)


David
 
A

Austin Ziegler

Is there a feature to freeze variable assignment?

e.g.
a="hello"
a.assignfreeze
a="goodbye" # ===> generates exception

No, but you might be able to do something with WeakRef (weakref.rb)
or some other proxy class and freezing that.

class Var
def initialize(value)
@value = value
@const = false
end

def const!
@const = true
end

def const?
@const
end

attr_accessor :value
def value=(value)
raise "Var #{@value.inspect} is constant." if const?
@value = value
end

def class
@value.class
end

def id
@value.__id__
end

def method_missing(sym, *args)
@value.send(sym, *args)
end

def inspect
@value.inspect
end
end

a = Var.new("hello")
a.value = "goodbye"
a.class
a.const!
a.value = "yo!"
Or, in a related vein, a type freeze, so that only similar objects
can be added.

Define "similar objects". What if I want a variable to be only an
IO? Should I restrict it to items which inherit from IO? If so, I
lose the ability to transparently use StringIO or ZLib::GzipWriter
(or GzipReader) objects. This gets to the heart of why static typing
is generally a bad idea -- it makes classes less extensible, and
when you have static typing enforced by the language, there's almost
always ways to escape out of it with no protection from the compiler
involved (e.g., pointers).
I realize that constants offer assignment freezing to a certain
degree.

The reason I ask, is that I stepped over-top of some framework
variables today, and it was hard to find out what was going on.
Where as ruby protects keywords, it would be nice if frameworks or
custom domain specific languages could do the same.

What do you mean, specifically? Did you reopen the classes in the
framework, or something? If the framework put variables in such a
way as to make it easy for you to overwrite something that shouldn't
have been, then I think that it's a bug in the framework, not in
your code. In some ways, Transaction::Simple is a framework, and I
have deliberately made it "hard" to step on Transaction::Simple
variables.

I like this, specially if it also covers instance variables. I
think Ruby's current freeze is a special case, in which all
instance variables of the given object are frozen.

Um. Not really. Only the direct replacement of those objects is
frozen.

a = Struct.new("Effable", :a, :b).new
a.a = "abcdef"
a.b = %w(a b c d e f)
a.freeze
a.a = "ghijkl" # raises error
a.a.gsub!(/a/, 'z') # no error
a.b[0] = 'z' # no error

Freeze isn't necessarily recursive.
It's in the same vein that I think Observable should target a
instance variable (an attribute, more generally) of an object,
rather than an entire object.

Why?

-austin
 
J

Joel VanderWerf

Austin said:
On Mon, 6 Dec 2004 11:51:55 +0900, Nicholas Van Weerdenburg



Why?

It's useful in GUI code, where each control, field, etc. is wired up to
one or more attrs in the window instance, and other related windows can
be wired up to those attrs too, to keep their state synchronized. See,
for instance, foxtails on raa, which uses FXRuby and observable (also on
raa). That observable lib (which should have been called
observable-attr) is just what Nicholas described: it makes attrs observable.
 
E

Eric Hodel

Austin Ziegler said:
a = Struct.new("Effable", :a, :b).new
a.a = "abcdef"
a.b = %w(a b c d e f)
a.freeze
a.a = "ghijkl" # raises error
a.a.gsub!(/a/, 'z') # no error
a.b[0] = 'z' # no error

Freeze isn't necessarily recursive.

Correct. All instance variables of the object are frozen, not the
objects
they refer to.

No, the instance variables are not frozen, the instance 'a' of Effable
is.

#a= modifies a, which is disallowed because a is frozen.

You cannot freeze variables, just objects.

a = "foo"
a.freeze
a = "bar"
 
A

Austin Ziegler

I respecfully but heartily disagree. Ruby freezes objects by
freezing their instance variables. The latter is the fundamental
operation.

You may disagree, but you'd be incorrect.

irb(main):008:0> class << a
irb(main):009:1> def matz
irb(main):010:2> "matz"
irb(main):011:2> end
irb(main):012:1> end
TypeError: can't modify frozen object
from (irb):9

(Assuming the same Effable that has been discussed to this point.)

The object referred to by 'a' is frozen, not the instance variables
of said object.

The fundamental operation is *freezing the object*.
@a = "foo"
self.freeze
@a = "bar"

Ruby just happens to treat local variables differently. There is
no fundamental reason to do so.

Sure there is, and it's precisely because variables are simply
labels, but instance variables are part of the state of the object.

-austin
 
A

Austin Ziegler

It's useful in GUI code, where each control, field, etc. is wired up to
one or more attrs in the window instance, and other related windows can
be wired up to those attrs too, to keep their state synchronized. See,
for instance, foxtails on raa, which uses FXRuby and observable (also on
raa). That observable lib (which should have been called
observable-attr) is just what Nicholas described: it makes attrs observable.

That makes sense, and it seems that the observable-attr is the right
thing for what he needs there.

-austin
 
E

Eric Hodel

I respecfully but heartily disagree. Ruby freezes objects by freezing
their
instance variables. The latter is the fundamental operation.

variable.c disagrees with you:

VALUE
rb_ivar_set(obj, id, val)
VALUE obj;
ID id;
VALUE val;
{
if (!OBJ_TAINTED(obj) && rb_safe_level() >= 4)
rb_raise(rb_eSecurityError, "Insecure: can't modify instance
variable");
if (OBJ_FROZEN(obj)) rb_error_frozen("object");
a = "foo" # makes the variable a refer to the object "foo"

a.freeze # makes the instance variables of the object "foo" frozen.

Try this:

@a = "foo"
self.freeze
@a = "bar"

No, self is frozen, not @a. Your example is no different than the one
using Effable.

@a = "foo" # self.instance_variable_set "@a", "foo"
self.freeze
@b = "bar" # self.instance_variable_set "@b", "bar", raises because
self is frozen.
 
J

Jim Weirich

variable.c disagrees with you:

You guys are talking past each other ...

Itsme213: "Ruby freezes objects by freezing their instance variables"

Weirich Translation: When a Ruby object is frozen, the binding of its
instances variable names to values are made unchangeable (i.e. frozen).

Eric points to variable.c, which implements the policy annunciated by itsme.
And David correctly points out that the simple view of only looking at the
instance variables does not paint the whole picture (e.g. freezing arrays).

But as far as classes implemented in Ruby (as opposed to classes implemented
in C), the viewpoint is pretty right on.
 
D

David A. Black

Hi --

You guys are talking past each other ...

Itsme213: "Ruby freezes objects by freezing their instance variables"

Weirich Translation: When a Ruby object is frozen, the binding of its
instances variable names to values are made unchangeable (i.e. frozen).

David's previous statement on this: "One of the consequences of
[calling a.freeze] (though not the only consequence) is that a's
instance variables bindings are frozen." :)
Eric points to variable.c, which implements the policy annunciated by itsme.
And David correctly points out that the simple view of only looking at the
instance variables does not paint the whole picture (e.g. freezing arrays).

But as far as classes implemented in Ruby (as opposed to classes implemented
in C), the viewpoint is pretty right on.

But that, in turn, is because Kernel#freeze freezes an object's state,
and state for non-builtins is generally (always?) a matter of instance
variables. That's why I disagree with itsme213 that instance
variables are a good model for how to treat local variables. (Not
that that matters, really; if it's a good idea to be able to freeze
local variable bindings [I'm not convinced it is], it doesn't have to
depend on analogy with Kernel#freeze.)

One could perhaps reason that a Binding "has" local variables, in
somewhat the same way that an object "has" instance variables, and
that there should be some way to freeze those bindings too (i.e., the
bindings in a Binding). The cases are not exactly parallel, though,
since a Binding can also have instance variables.... But it might be
an alternative way to approach it.


David
 
A

Austin Ziegler

Eric points to variable.c, which implements the policy
annunciated by itsme. And David correctly points out that the
simple view of only looking at the instance variables does not
paint the whole picture (e.g. freezing arrays).
I was talking about the pure object model part of Ruby. In such a
pure object model, a[1] and a[2] are instance variables (some
Smalltalk descriptions calls these 'indexed instance variables' as
opposed to 'named instance variables'). How something is optimized
in C is a different matter.

Ruby isn't Smalltalk.

In a Hash, foo['bar'] and foo['baz'] are not instance variables of
the Hash. They are indexed items to the Hash, for certain, but they
aren't instance variables in the least.

Frankly, I think your view of freezing is one that is not one that
is useful in considering Ruby at all.

I don't think that freezing bindings is at all useful, and before I
could even think of supporting something this drastic, I'd need to
see use cases that couldn't be worked around in other ways.
In any case, consider my postings as a point of view; it is a
clean and potentially useful one. The part about local variables
was not central to me; I was just looking for a bit more
uniformity in treatment of all variable bindings, even temporary
(local) ones. It makes things like dynamic binding more uniform to
implement.

I don't see any uniformity in freezing bindings.

-austin
 
N

Nicholas Van Weerdenburg

Eric points to variable.c, which implements the policy
annunciated by itsme. And David correctly points out that the
simple view of only looking at the instance variables does not
paint the whole picture (e.g. freezing arrays).
I was talking about the pure object model part of Ruby. In such a
pure object model, a[1] and a[2] are instance variables (some
Smalltalk descriptions calls these 'indexed instance variables' as
opposed to 'named instance variables'). How something is optimized
in C is a different matter.

Ruby isn't Smalltalk.

In a Hash, foo['bar'] and foo['baz'] are not instance variables of
the Hash. They are indexed items to the Hash, for certain, but they
aren't instance variables in the least.

Frankly, I think your view of freezing is one that is not one that
is useful in considering Ruby at all.

I don't think that freezing bindings is at all useful, and before I
could even think of supporting something this drastic, I'd need to
see use cases that couldn't be worked around in other ways.
In any case, consider my postings as a point of view; it is a
clean and potentially useful one. The part about local variables
was not central to me; I was just looking for a bit more
uniformity in treatment of all variable bindings, even temporary
(local) ones. It makes things like dynamic binding more uniform to
implement.

I don't see any uniformity in freezing bindings.



-austin

I think immutability is usually a good thing from a design point of
view, so I can see a general need to have more freezing options. When
trying to extend old, bad Java code, I do some minor refactoring- 1.
kill singletons, 2. make primary business objects immutable, and 3.
add good logging (poor man's design-by-contract/testing). This makes
the code understandable enough that some more aggressive refactoring
can be done in the absense of a test suite, and well as enable some
component level testing to be added, since it's now easier to seperate
some of the concerns in the code (gui for application logic in a swing
application, for instance). The point being the essential importance
of immutability and being be able to control it from a contractual
perspective.

And is there anyway to may attributes private so that subclasses can't
see them? IIRC, this is possible feature of Rite. This would remove
some of the need, since immutability is enforced by invisibility.

BTW- Is freezing bindings simply a delayed constant? Or is there more to it?

Also, is there anything such as a deep freeze of an object graph? I'm
guessing not, since that would something hard to generalize easily (I
think of all the Java serializatoin performance problems where it
turned out that the data was pulling the application code along with
it).

Thanks,
Nick
 
A

Austin Ziegler

Austin Ziegler said:
In a Hash, foo['bar'] and foo['baz'] are not instance variables of
the Hash. They are indexed items to the Hash, for certain, but they
aren't instance variables in the least.
If there is a standard Ruby term to describe what it is? Is "indexed items
to the Hash" part of the Ruby model of what constitutes object state?

Simply "object state." Alternatively "members of the [Collection]".
They aren't instance variables, though, since that has a very specific
and precise meaning in Ruby.

-austin
 
A

Austin Ziegler

Eric points to variable.c, which implements the policy
annunciated by itsme. And David correctly points out that the
simple view of only looking at the instance variables does not
paint the whole picture (e.g. freezing arrays).
I was talking about the pure object model part of Ruby. In such
a pure object model, a[1] and a[2] are instance variables (some
Smalltalk descriptions calls these 'indexed instance variables'
as opposed to 'named instance variables'). How something is
optimized in C is a different matter.
Ruby isn't Smalltalk.
In a Hash, foo['bar'] and foo['baz'] are not instance variables
of the Hash. They are indexed items to the Hash, for certain, but
they aren't instance variables in the least.
Frankly, I think your view of freezing is one that is not one
that is useful in considering Ruby at all.
I don't think that freezing bindings is at all useful, and before
I could even think of supporting something this drastic, I'd need
to see use cases that couldn't be worked around in other ways.
In any case, consider my postings as a point of view; it is a
clean and potentially useful one. The part about local variables
was not central to me; I was just looking for a bit more
uniformity in treatment of all variable bindings, even temporary
(local) ones. It makes things like dynamic binding more uniform
to implement.
I don't see any uniformity in freezing bindings.
I think immutability is usually a good thing from a design point
of view, so I can see a general need to have more freezing
options.

Why? Convince me, because as someone who has done my share of design
work, I don't see immmutability as a positive on most things. On
primary key references, yes (e.g., a customer's identification
number should never change or be changed in any way), immutability
is good. But as a general rule? Immutability isn't necessarily what
you want.

(As a point of note, in my Ruby, I don't think that I've *ever* used
#freeze. In the billing design work that I did, none of it depended
upon immutability of the objects -- the only immutable things in my
code and design were *constants*.)

The "need" for immutability is very, erm, mutable and can be worked
around with various design decisions.
When trying to extend old, bad Java code, I do some minor
refactoring- 1. kill singletons, 2. make primary business objects
immutable, and 3. add good logging (poor man's design-by-contract/
testing). This makes the code understandable enough that some more
aggressive refactoring can be done in the absense of a test suite,
and well as enable some component level testing to be added, since
it's now easier to seperate some of the concerns in the code (gui
for application logic in a swing application, for instance). The
point being the essential importance of immutability and being be
able to control it from a contractual perspective.

You assert the value of immutability, but you haven't actually
demonstrated the value. I'm really not trying to be difficult here,
but what sort of immutability to you mean in Java -- and why do you
then need it in Ruby? I find that most of the time when people say
that they want particular features in Ruby they do so because
they're not *thinking* in Ruby, but in other languages that they
have to deal with on a daily basis to pay the bills. I know I do it,
from time to time, with C++ now that I'm making my money from that.
And is there anyway to may attributes private so that subclasses
can't see them? IIRC, this is possible feature of Rite. This would
remove some of the need, since immutability is enforced by
invisibility.

Um. What do you mean by "attributes"? If you mean that which is
generated by attr_accessor, then:

class A
attr_accessor :foo
private :foo, :foo=
end # => A
class B < A; end # => nil
B.new.foo = :bar
# => NoMethodError: private method `foo=' called for
# #<B:0x2b52c38>

If you mean instance variables, no, and that wouldn't work anyway --
it would simply be a source of errors.

class A
attr_accessor :foo
private_var :mad:foo
end

class B < A
def foo=(x)
@foo = x
end
end

Logically, this shouldn't cause a problem, because even if @foo in A
is private, then B should still be able to have it's own @foo.

Maybe there's a way around this -- and this could be potentially
very useful -- with something like:

module A
def foo=(x)
@<foo> = x
end
end

If Ruby mangles @<foo> to be something like @__A_foo__, then you can
BTW- Is freezing bindings simply a delayed constant? Or is there
more to it?

I don't know what itsme really wants, because I think that the idea
of making variable bindings -- instance or otherwise -- frozen is a
bad idea. Freezing an object freezes that object's state -- which
includes assignment to instance variables, certainly, but also
inclues adding singleton methods, modifying the singleton object,
extending the object, etc.
Also, is there anything such as a deep freeze of an object graph?
I'm guessing not, since that would something hard to generalize
easily (I think of all the Java serializatoin performance problems
where it turned out that the data was pulling the application
code along with it).

No, there isn't such built into Ruby. You could write one, but I
don't think it's a good idea.

-austin
 
N

Nicholas Van Weerdenburg

Why? Convince me, because as someone who has done my share of design
work, I don't see immmutability as a positive on most things. On
primary key references, yes (e.g., a customer's identification
number should never change or be changed in any way), immutability
is good. But as a general rule? Immutability isn't necessarily what
you want.

(As a point of note, in my Ruby, I don't think that I've *ever* used
#freeze. In the billing design work that I did, none of it depended
upon immutability of the objects -- the only immutable things in my
code and design were *constants*.)

The "need" for immutability is very, erm, mutable and can be worked
around with various design decisions.

I agree- good interface design effectively creates immutable classes
if desired. But that can be an issue because the object may only
desire immutability later in its lifecycle, or too certain clients.

Also, good design is an ideal case. In a large project, things can
become ugly and to be able to enforce a high-degree of control via
immutable objects can be beneficial, IMHO. Good design requires good
contracts to enforce it.

There are three things that make up an immutable object so far in our
discussion:
1. frozen objects
-this could also be done with good interface design for
certain cases. other alternatives to freeze would be useful to know-
wrap/delegate, undeffing, etc.
2. frozen attributes (assignmentFreeze)
-mostly appplies to inheritence, so private instance variables
would help here.
3. frozen value objects (referred to objects of a certain type)
-not really discussed yet, but seems important as without it,
freeze is only slushy.

And of course the question, why do you need it.

It's hard to describe the benefits of immutables in a short example,
but I think it's similar in nature to global variables- with
mutables, edits can be done in many places, leading to bugs as well as
maintenance issues.

That's why I mentioned singletons. They often raise the desire for
immutables since they facilitate uncontrolled access and program flow-
if you can't get to something, you can't change it. With singletons,
there is often too much coupling, which makes the issue of mutability
more pronounced. It's too easy for isolated pieces of code to break
with appropriate responsibility and assume too much knowledge of the
domain object.

For instance, in an asset manager:
asset=AssetManager.getAsset("id=1")
asset.value="10"
Being embedded in gui code.

With the singleton, this kind of code can be sprinkled throughout the
code. Bad design, sure. But this is often an issue where there is
gui-app logic bindings in different dialogs, tables, etc.

Of course, a better domain class can help.

class Asset
def initialize name, location, value
@name=name
@location=location
@value=value
end
attr_reader :name, :location, :value
end

This is essentially what I do with Java- creating interfaces that
present an immutable interface to the domain object. But that doesn't
work with duck typing. So in Ruby, it needs to be part of the class
interface, and the problem with that is that I may need to have more
write access to an object early in it's lifecycle. I suppose wrappers
or delegates are an option here, and that's not too hard to implement
in a nice way given Ruby's nature. Or even undefing methods. Any
suggestions welcome.

As a side note though, even with freezing, the above business object
is not immutable...
a=Asset.new "laptop", "home", 500
a.location << " is where the heart is" # regardless of a being frozen or not.

If an object should protect it's invariant nature, then it would be
nice for ruby to provide some capability for immutable value objects-
maybe something like:

value_reader :name, :location, :value # returns defensive copies

Some on the concept of value objects vs. reference objects:
http://c2.com/cgi/wiki?ValueObject
http://c2.com/cgi/wiki?ValueObjectsShouldBeImmutable
You assert the value of immutability, but you haven't actually
demonstrated the value. I'm really not trying to be difficult here,
but what sort of immutability to you mean in Java -- and why do you
then need it in Ruby? I find that most of the time when people say
that they want particular features in Ruby they do so because
they're not *thinking* in Ruby, but in other languages that they
have to deal with on a daily basis to pay the bills. I know I do it,
from time to time, with C++ now that I'm making my money from that.

I'm still learning to "think" in Ruby for sure, but the essence of the
need comes from non-trivial systems without a perfect design.

Removing singletons and making certain domain objects immutable is
somewhat like putting aspects of the "Law of Demeter" into place.
http://c2.com/cgi/wiki?LawOfDemeter

Another way of thinking about is in terms of object lifecycle- if it
becomes immutable at some point, there is less to worry about. In a
large system, I would freeze and object just prior to releasing into
the "wild"- e.g. outside the boundaries of my subsystem.
Um. What do you mean by "attributes"? If you mean that which is
generated by attr_accessor, then:

class A
attr_accessor :foo
private :foo, :foo=
end # => A
class B < A; end # => nil
B.new.foo = :bar
# => NoMethodError: private method `foo=' called for
# #<B:0x2b52c38>

I meant the case where the instance variable @foo is accessed in side
the class B.
If you mean instance variables, no, and that wouldn't work anyway --
it would simply be a source of errors.

class A
attr_accessor :foo
private_var :mad:foo
end

private_var is a concept?
class B < A
def foo=(x)
@foo = x
end
end

Logically, this shouldn't cause a problem, because even if @foo in A
is private, then B should still be able to have it's own @foo.

Maybe there's a way around this -- and this could be potentially
very useful -- with something like:

module A
def foo=(x)
@<foo> = x
end
end

If Ruby mangles @<foo> to be something like @__A_foo__, then you can


I don't know what itsme really wants, because I think that the idea
of making variable bindings -- instance or otherwise -- frozen is a
bad idea. Freezing an object freezes that object's state -- which
includes assignment to instance variables, certainly, but also
inclues adding singleton methods, modifying the singleton object,
extending the object, etc.

I think private variables would alleviate much of the need. That would
allow a better contract for inheritence, and that was largely the
interest in my first post.

Other issues requiring freezing probably point to an interface that
exposes too many internals - e.g. use of attr_accessor or a class that
has too much responsibility or is simply too big. There is still the
issue of value objects. Any thoughts on that?

http://c2.com/cgi/wiki?ValueObject
http://c2.com/cgi/wiki?ValueObjectsShouldBeImmutable
No, there isn't such built into Ruby. You could write one, but I
don't think it's a good idea.

Agreed- unless needed for a particular case.

Regards,
Nick
 
F

Florian Gross

itsme213 said:
I was talking about the pure object model part of Ruby. In such a pure
object model, a[1] and a[2] are instance variables (some Smalltalk
descriptions calls these 'indexed instance variables' as opposed to 'named
instance variables'). How something is optimized in C is a different matter.

Please call this Object state ("as in a[1] and a[2] are part of Object
state" / "@foo is part of Object state") instead. It's a more general
term and seems to already be well-established.
 
F

Florian Gross

Nicholas said:
I think immutability is usually a good thing from a design point of
view, so I can see a general need to have more freezing options. When
trying to extend old, bad Java code, I do some minor refactoring- 1.
kill singletons, 2. make primary business objects immutable, and 3.
add good logging (poor man's design-by-contract/testing). This makes
the code understandable enough that some more aggressive refactoring
can be done in the absense of a test suite, and well as enable some
component level testing to be added, since it's now easier to seperate
some of the concerns in the code (gui for application logic in a swing
application, for instance). The point being the essential importance
of immutability and being be able to control it from a contractual
perspective.

And is there anyway to may attributes private so that subclasses can't
see them? IIRC, this is possible feature of Rite. This would remove
some of the need, since immutability is enforced by invisibility.

Rite will do non-inherited instance variables via @_foo AFAIK. But I
think this is only for avoiding name clashes, not for absolute security
against modification. (Just think about .instance_eval and so on -- Ruby
doesn't usually forbid you from doing bad things -- instead it tries to
tell you that the thing is wrong and that you should think twice before
using it.)
Also, is there anything such as a deep freeze of an object graph? I'm
guessing not, since that would something hard to generalize easily (I
think of all the Java serializatoin performance problems where it
turned out that the data was pulling the application code along with
it).

I think this would only make sense when combined with a deep clone. It
would be nice to have GC's object graph traversal functionality exposed.
It is a good thing to have something like that available generally.

matz, are you listening?
 
F

Florian Gross

Nicholas said:
Is there a feature to freeze variable assignment?

e.g.
a="hello"
a.assignfreeze
a="goodbye" # ===> generates exception

Or, in a related vein, a type freeze, so that only similar objects can be added.

The proposed Syntax confuses the object a variable is referring to with
the variable itself. It would likely be assign_freeze :var instead.
But I don't think this is general enough to include it directly in Ruby.

Let me suggest an idea for a revised request instead: Request a way of
specifying a callback for local variable assignment. trace_var already
can be used for doing that with global variables. It would be a
generalization to also allow this with local ones. The interface would
be this:

trace_var:)string) do |arg|
raise(TypeError, "Can't assign #{arg.inspect} to variable 'string'," +
" because it is not a String.") unless arg.is_a?(String)
end

Using that you could implement assign_freeze() by yourself. But please
make sure to think about performance issues. It might be a good idea to
implement it and benchmark it and send the patch with statistics to
ruby-core. Note that slowdown that is only caused by *using* the new
feature (e. g. does not make old code slower) is not much of an issue.

Sorry if this sounds like a lot of work, but I think that if you do it
like that it would be a very nice feature that would be generally useful
to the community without having too much of a downside. It would allow
for very powerful meta programming.
 
N

Nicholas Van Weerdenburg

The proposed Syntax confuses the object a variable is referring to with
the variable itself. It would likely be assign_freeze :var instead.

Yes. My bad.
But I don't think this is general enough to include it directly in Ruby.

Let me suggest an idea for a revised request instead: Request a way of
specifying a callback for local variable assignment. trace_var already
can be used for doing that with global variables. It would be a
generalization to also allow this with local ones. The interface would
be this:

trace_var:)string) do |arg|
raise(TypeError, "Can't assign #{arg.inspect} to variable 'string'," +
" because it is not a String.") unless arg.is_a?(String)
end

Using that you could implement assign_freeze() by yourself. But please
make sure to think about performance issues. It might be a good idea to
implement it and benchmark it and send the patch with statistics to
ruby-core. Note that slowdown that is only caused by *using* the new
feature (e. g. does not make old code slower) is not much of an issue.

Sorry if this sounds like a lot of work, but I think that if you do it
like that it would be a very nice feature that would be generally useful
to the community without having too much of a downside. It would allow
for very powerful meta programming.

Those are good ideas. Maybe over Christmas I can take my ruby up an
notch and start working with c files.

Thanks,
Nick
 
Y

Yukihiro Matsumoto

Hi,

In message "Re: Freezing Variable Assignment"

|> Also, is there anything such as a deep freeze of an object graph? I'm
|> guessing not, since that would something hard to generalize easily (I
|> think of all the Java serializatoin performance problems where it
|> turned out that the data was pulling the application code along with
|> it).
|
|I think this would only make sense when combined with a deep clone. It
|would be nice to have GC's object graph traversal functionality exposed.
|It is a good thing to have something like that available generally.
|
|matz, are you listening?

Yes, I am. I think it's good to have general purpose object graph
traverser. But I'm not going to expose GC marker, for it's tailored
for garbage collection.

matz.
 

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,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top