private variables 
Author Message
 private variables

 Why I always write stupid things ? See the effect of attr_accessor with
 private variable

pigeon% cat b.rb
#!./ruby
class A
   attr_accessor :_n
   def initialize



   end
   def a

   end
end

class B < A
   attr_accessor :_m
   def initialize


      super
   end
   def a

      super
   end
end

b = B.new
b.a
b._m = 24
b._n = 36
b.a
pigeon%

pigeon% b.rb
a : 12 - _m : [2, 4] - _n : 6
a : 12 - _m : [1, 2] - _n : [3, 4]
a : 12 - _m : 24 - _n : 6
a : 12 - _m : [1, 2] - _n : 36
pigeon%

Guy Decoux



Sun, 27 Feb 2005 21:33:45 GMT  
 private variables

Quote:

> pigeon% b.rb
> a : 12 - _m : [2, 4] - _n : 6
> a : 12 - _m : [1, 2] - _n : [3, 4]
> a : 12 - _m : 24 - _n : 6
> a : 12 - _m : [1, 2] - _n : 36
> pigeon%

This is exactly what I would expect to happen.  I'm not sure why I'd
want to use a private variable and them make it visible with
attr_accessor.  Would there be any bug that could arise from doing this?

Paul



Sun, 27 Feb 2005 22:38:43 GMT  
 private variables

P> attr_accessor.  Would there be any bug that could arise from doing this?

 perhaps hard to understand what do the code in this case.

Guy Decoux



Sun, 27 Feb 2005 23:21:35 GMT  
 private variables
Hi,

In message "private variables"

| Why I always write stupid things ? See the effect of attr_accessor with
| private variable

Do you mean you've implemented private instance variable, even if it's
incomplete?  If so, show me the code please.

                                                        matz.



Mon, 28 Feb 2005 01:01:43 GMT  
 private variables

Y> Do you mean you've implemented private instance variable, even if it's
Y> incomplete?  If so, show me the code please.

 Well, here a quick diff (*WARNING* old 1.6.7 : you can see it with
 NODE_CVASGN)

 To understand what it do

pigeon% cat b.rb
#!./ruby
class A
   def initialize


   end
end

class B < A
   def initialize


      super
   end
end

Marshal.dump(B.new, File.new("aa", "w"))
pigeon%

pigeon% b.rb
pigeon%

pigeon% cat c.rb
#!/usr/bin/ruby
class A
end
class B < A
   def b

   end
end

Marshal.load(IO.readlines("aa", nil)[0]).b
pigeon%

pigeon% c.rb
a = 12 - _m = {B=>[2, 4], A=>[1, 2]} - _n = {B=>6}
pigeon%

 Now the problems :

  1) you need to have 2 hash access for a private variable, rather than one
     for a public variable

  2) I use

#define ID_PRIVATE 0x07

  which is used for ID_JUNK in 1.7.*

 For 1.7 I see only a possibility

#define ID_JUNK 0x00
#define ID_PRIVATE 0x07

 but this means that *all* bits are used and it will not possible to add
 new types after this

Guy Decoux

diff -u ruby-1.6.7/env.h ruby-1.6.m/env.h
--- ruby-1.6.7/env.h    2001-03-21 09:04:11.000000000 +0100

     ID last_func;
     VALUE last_class;
     VALUE cbase;
+    VALUE curr_class;
     struct FRAME *prev;
     struct FRAME *tmp;
     char *file;
diff -u ruby-1.6.7/eval.c ruby-1.6.m/eval.c
--- ruby-1.6.7/eval.c   2002-02-27 05:50:29.000000000 +0100

 static VALUE rb_cUnboundMethod;
 static VALUE umethod_bind _((VALUE, VALUE));
 static VALUE rb_mod_define_method _((int, VALUE*, VALUE));
+static VALUE remove_private_variable __((VALUE, VALUE));
+static VALUE rb_current_class __((void));

 static int scope_vmode;

 static struct FRAME *top_frame;
 static struct SCOPE *top_scope;

-#define PUSH_FRAME() {                 \
-    struct FRAME _frame;               \
-    _frame.prev = ruby_frame;          \
-    _frame.tmp  = 0;                   \
-    _frame.file = ruby_sourcefile;     \
-    _frame.line = ruby_sourceline;     \
-    _frame.iter = ruby_iter->iter;  \
-    _frame.cbase = ruby_frame->cbase;       \
-    _frame.argc = 0;                   \
-    _frame.argv = 0;                   \
-    _frame.flags = FRAME_ALLOCA;       \
-    ruby_frame = &_frame;          \
+#define PUSH_FRAME() {                         \
+    struct FRAME _frame;                       \
+    _frame.prev = ruby_frame;                  \
+    _frame.tmp  = 0;                           \
+    _frame.file = ruby_sourcefile;             \
+    _frame.line = ruby_sourceline;             \
+    _frame.iter = ruby_iter->iter;          \
+    _frame.cbase = ruby_frame->cbase;               \
+    _frame.curr_class = ruby_frame->curr_class;     \
+    _frame.argc = 0;                           \
+    _frame.argv = 0;                           \
+    _frame.flags = FRAME_ALLOCA;               \
+    ruby_frame = &_frame;

 #define POP_FRAME()                    \

        rb_call_inits();
        ruby_class = rb_cObject;
        ruby_frame->self = ruby_top_self;
+       ruby_frame->curr_class = rb_cObject;
        top_cref = rb_node_newnode(NODE_CREF,rb_cObject,0,0);
        ruby_cref = top_cref;

     ruby_top_self = rb_obj_clone(ruby_top_self);
     rb_extend_object(ruby_top_self, ruby_wrapper);
     PUSH_FRAME();
+    ruby_frame->curr_class = ruby_class;
     ruby_frame->last_func = 0;
     ruby_frame->last_class = 0;

       case NODE_IASGN:
        result = rb_eval(self, node->nd_value);
-       rb_ivar_set(self, node->nd_vid, result);
+       if (rb_is_instance_id(node->nd_vid)) {
+           rb_ivar_set(self, node->nd_vid, result);
+       }
+       else {
+           rb_pvar_set(self, rb_current_class(), node->nd_vid, result);
+       }
        break;


       case NODE_CVASGN:
        result = rb_eval(self, node->nd_value);
-       rb_cvar_set(ruby_cbase, node->nd_vid, result);
+       if (!FL_TEST(ruby_cbase, FL_SINGLETON)) {
+           rb_cvar_set(ruby_cbase, node->nd_vid, result);
+           break;
+       }
+       rb_cvar_set(rb_iv_get(ruby_cbase, "__attached__"), node->nd_vid, result);
        break;


        break;

       case NODE_IVAR:
-       result = rb_ivar_get(self, node->nd_vid);
+        if (rb_is_instance_id(node->nd_vid)) {
+           result = rb_ivar_get(self, node->nd_vid);
+       }
+       else {
+           result = rb_pvar_get(self, rb_current_class(), node->nd_vid);
+       }
        break;


        if (ruby_frame->argc != 1)
            rb_raise(rb_eArgError, "wrong # of arguments(%d for 1)",
                     ruby_frame->argc);
-       result = rb_ivar_set(self, node->nd_vid, ruby_frame->argv[0]);
+        if (rb_is_instance_id(node->nd_vid)) {
+           result = rb_ivar_set(self, node->nd_vid, ruby_frame->argv[0]);
+       }
+       else {
+           result = rb_pvar_set(self, rb_current_class(), node->nd_vid,
+                                ruby_frame->argv[0]);
+       }
        break;


     PUSH_SCOPE();
     PUSH_VARS();

+    ruby_frame->curr_class = ruby_class;
+
     if (node->nd_tbl) {
        VALUE *vars = TMP_ALLOC(node->nd_tbl[0]+1);

        ruby_dyna_vars = block->dyna_vars;
     }
     ruby_class = klass?klass:block->klass;
+    ruby_frame->curr_class = ruby_class;
     if (!klass) self = block->self;
     node = block->body;

        break;

       case NODE_CVASGN:
-       rb_cvar_set(ruby_cbase, lhs->nd_vid, val);
+       if (!FL_TEST(ruby_cbase, FL_SINGLETON)) {
+           rb_cvar_set(ruby_cbase, lhs->nd_vid, val);
+           break;
+       }
+       rb_cvar_set(rb_iv_get(ruby_cbase, "__attached__"), lhs->nd_vid, val);
        break;


     ruby_frame->self = recv;
     ruby_frame->argc = argc;
     ruby_frame->argv = argv;
+    if (nd_type(body) != NODE_CFUNC) {
+       ruby_frame->curr_class = klass;
+    }

     switch (nd_type(body)) {

     if (TYPE(ruby_class) == T_ICLASS) {
        ruby_class = RBASIC(ruby_class)->klass;
     }
+    ruby_frame->curr_class = ruby_class;
     PUSH_TAG(PROT_NONE);
     if ((state = EXEC_TAG()) == 0) {

     ruby_frame->last_class = _frame.prev->last_class;
     ruby_frame->argc = _frame.prev->argc;
     ruby_frame->argv = _frame.prev->argv;
+    ruby_frame->curr_class = ruby_class;
     if (ruby_cbase != under) {
        ruby_frame->cbase = (VALUE)rb_node_newnode(NODE_CREF,under,0,ruby_frame->cbase);

     ruby_frame->last_class = 0;
     ruby_frame->self = self;
     ruby_frame->cbase = (VALUE)rb_node_newnode(NODE_CREF,ruby_class,0,0);
+    ruby_frame->curr_class = ruby_class;
     PUSH_SCOPE();
     /* default visibility is private at loading toplevel */

     rb_define_method(rb_mKernel, "send", rb_f_send, -1);
     rb_define_method(rb_mKernel, "__send__", rb_f_send, -1);
     rb_define_method(rb_mKernel, "instance_eval", rb_obj_instance_eval, -1);
+    rb_define_private_method(rb_mKernel, "remove_private_variable",
+                            remove_private_variable, 1);

     rb_define_private_method(rb_cModule, "append_features", rb_mod_append_features, 1);

        tt = tt->prev;
     }
 }
+
+static VALUE
+rb_current_class()
+{
+    return ruby_frame->curr_class;
+}
+
+static VALUE
+remove_private_variable(obj, name)
+    VALUE obj, name;
+{
+    return rb_obj_remove_private_variable(obj, rb_current_class(), name);
+}
diff -u ruby-1.6.7/gc.c ruby-1.6.m/gc.c
--- ruby-1.6.7/gc.c     2002-02-13 10:02:15.000000000 +0100

 {
     mark_locations_array(frame->argv, frame->argc);
     rb_gc_mark(frame->cbase);
+    rb_gc_mark(frame->curr_class);
 }

 #ifdef __GNUC__
diff -u ruby-1.6.7/intern.h ruby-1.6.m/intern.h
--- ruby-1.6.7/intern.h 2002-02-27 05:50:30.000000000 +0100

 void rb_parser_while_loop _((int, int));
 int rb_is_const_id _((ID));
 int rb_is_instance_id _((ID));
+int rb_is_private_id _((ID));
 int rb_is_class_id _((ID));
 VALUE rb_backref_get _((void));

 void rb_mark_generic_ivar _((VALUE));
 void rb_mark_generic_ivar_tbl _((void));
 void rb_free_generic_ivar _((VALUE));
+VALUE rb_pvar_get _((VALUE, VALUE, ID));
+VALUE rb_pvar_set _((VALUE, VALUE, ID, VALUE));
+VALUE rb_pvar_defined _((VALUE, VALUE, ID));
+VALUE rb_obj_private_variables _((VALUE, VALUE));
+VALUE rb_obj_remove_private_variable _((VALUE, VALUE, VALUE));
 VALUE rb_ivar_get _((VALUE, ID));
 VALUE rb_ivar_set _((VALUE, ID, VALUE));
 VALUE rb_ivar_defined _((VALUE, ID));
diff -u ruby-1.6.7/marshal.c ruby-1.6.m/marshal.c
--- ruby-1.6.7/marshal.c        2002-02-28 07:52:47.000000000 +0100

     return v;
 }

+struct obj_id {
+    VALUE obj;
+    ID id;
+};
+
+static VALUE
+r_i_pvar(ary, st)
+    VALUE ary;
+    struct obj_id *st;
+{
+    rb_pvar_set(st->obj, RARRAY(ary)->ptr[0], st->id, RARRAY(ary)->ptr[1]);
+    return Qnil;
+}
+
 static void
 r_ivar(obj, arg)
     VALUE obj;
     struct load_arg *arg;
 {
     long len;
+    struct obj_id st;

     len = r_long(arg);
     if (len > 0) {
        while (len--) {
            ID id = r_symbol(arg);
            VALUE val = r_object(arg);
-           rb_ivar_set(obj, id, val);
+           if (rb_is_private_id(id)) {
+               st.obj = obj;
+               st.id = id;
+               rb_iterate(rb_each, val, r_i_pvar, (VALUE)&st);
+           }
+           else {
+               rb_ivar_set(obj, id, val);
+           }
        }
     }
 }
diff -u ruby-1.6.7/object.c ruby-1.6.m/object.c
--- ruby-1.6.7/object.c 2002-02-04 09:09:10.000000000 +0100
+++ ruby-1.6.m/object.c 2002-09-11
...

read more »



Mon, 28 Feb 2005 01:29:20 GMT  
 private variables
Hi,

In message "private variables"

| Why I always write stupid things ? See the effect of attr_accessor with
| private variable

Oh, I forget to mention that private instance variables should not be
exported by attr_accessor etc., because of the fact these variables
are private.  Publicly exported private instance variable is
contradicting existence.

                                                        matz.



Mon, 28 Feb 2005 01:58:48 GMT  
 private variables
<code snipped>

Quote:
> pigeon% b.rb
> a : 12 - _m : [2, 4] - _n : 6
> a : 12 - _m : [1, 2] - _n : [3, 4]
> a : 12 - _m : 24 - _n : 6
> a : 12 - _m : [1, 2] - _n : 36
> pigeon%

Hi Guy, I got the following:

a : 12 - _m : [1, 2] - _n : [3, 4]
a : 12 - _m : [1, 2] - _n : [3, 4]
a : 12 - _m : 24 - _n : 36
a : 12 - _m : 24 - _n : 36

This is on WinXP with the WindowsInstaller 1.72-4 release.

I'm still new to ruby, but the output I have looks correct.

Rob



Mon, 28 Feb 2005 01:58:16 GMT  
 private variables
"ts" wrote in
...

Quote:
>  To understand what it do

Wouldn't the


thing break a lot of code?

/Christoph



Mon, 28 Feb 2005 02:29:09 GMT  
 private variables

Quote:

> "ts" wrote in
> ....
> >  To understand what it do

> Wouldn't the


> thing break a lot of code?

I doubt there are many people who begin their instance variable names

accessed by derived classes anyway.

Paul



Mon, 28 Feb 2005 03:37:03 GMT  
 private variables
"Paul Brannan" wrote in
...

Quote:
> I doubt there are many people who begin their instance variable names

> accessed by derived classes anyway.


a ``_'' prefix with being  ``private" until this discussion.

We also could use your ``secret'' method frame work
(it simulates private methods of C++ right?) and only implement
``private_attributes'' or "secret_attribute"?   Here is a half baked
Ruby implementation (without your secret_method stuff).

/Christoph

----
module PrivateAttribute
    def instance_variables
      # needs more work
      super() -
      type.instance_eval {

      }
    end

    class << self
     # helper methods
      def mangle(klass,sym)
        "__pa__#{klass.id}_#{sym.to_s}"
      end

      #actuall code
      private
      def append_features(klass)
        Class === klass or raise TypeError, "Expected klass .."
        super
      end

      def included(klass)
        klass.instance_eval {



        }
        class << klass
          attr_reader :private_attributes
          private
          def private_attribute(attr)
            # silly tests
            unless String === attr or Symbol === attr
              raise TypeError, "expected ..."
            end
            attr = attr.to_s
            class_eval <<-PRIVATE_ATTR
              def #{attr}

              end
              def set_#{attr}(x)

              end
            PRIVATE_ATTR


          end

          def inherited(sub_klass)

            sub_klass.instance_eval {



            }

              sub_klass.class_eval <<-INHERITED
                def #{attr}
                  raise NoMethodError, "privacy violation of ..."
                end
                def set_#{attr}(x)
                  raise NoMethodError, "privacy violation of ..."
                end
              INHERITED
            }
            # potenieal source of conflict with other mixins
            # like singleton
            super
          end
        end
      end
    end

end

class A
  include PrivateAttribute
  private_attribute :xxx
  def initialize(x)
    set_xxx x
  end
end

#####
a = A.new "a"

p a.instance_variables
p A.private_attributes

class B < A
 private_attribute :yyy
 def initialize(a)
    set_yyy a
    #  super(a)
 end
end

b = B.new "b"
p b.yyy

p b.instance_variables
p B.private_attributes

class B
  def initialize(a)
    super a
 end
end
B.new ("boom") #  NoMethodError
---

["xxx"]
"b"
"you"

["yyy"]
(eval):5:in `set_xxx': privacy violation of ... (NoMethodError)
 from D:\Ruby\mswin\samples\rb58.tmp:84:in `initialize'
 from D:\Ruby\mswin\samples\rb58.tmp:111:in `initialize'
 from D:\Ruby\mswin\samples\rb58.tmp:114:in `new'
 from D:\Ruby\mswin\samples\rb58.tmp:114



Mon, 28 Feb 2005 04:42:36 GMT  
 private variables

Quote:

> We also could use your ``secret'' method frame work
> (it simulates private methods of C++ right?) and only implement
> ``private_attributes'' or "secret_attribute"?   Here is a half baked
> Ruby implementation (without your secret_method stuff).

I'm not sure there's much value in secret attributes/accessors.  I can
see why you'd want it (if you need to call a method every time you
update a private instance varaible), but every method in the class still
has access to both the accessor and the private instance variable, I
can't help but feeling that there is a better solution.

Paul



Mon, 28 Feb 2005 05:08:23 GMT  
 private variables

"Paul Brannan"  wrote in
...

Quote:
> I'm not sure there's much value in secret attributes/accessors.  I can
> see why you'd want it (if you need to call a method every time you

Actually I am fairly neutral about ``private_variables''  ...

Quote:
> update a private instance varaible), but every method in the class still
> has access to both the accessor and the private instance variable, I
> can't help but feeling that there is a better solution.

Oh well my half-baked ``solution'' is well-done nonsense anyway
(semantically it is plain wrong)

In the mean time how about using


- this also makes Guy's ``attr_reader problem'' obsolete?

/Christoph



Mon, 28 Feb 2005 08:28:26 GMT  
 private variables

C> Wouldn't the

C> thing break a lot of code?

 Yes, because you've introduced a new type of variable but this is not a
 problem with the implementation (i.e. you'll have the same problem with
 any implementations)

Guy Decoux



Mon, 28 Feb 2005 13:56:05 GMT  
 private variables

C> - this also makes Guy's ``attr_reader problem'' obsolete?

 attr_reader (or attr_accessor) is not a problem : you can always check if
 the name of the attribute is private or not. For example you have in
 eval.c

rb_attr(klass, id, read, write, ex)
    VALUE klass;
    ID id;
    int read, write, ex;
{
    const char *name;
    char *buf;
    ID attriv;
    int noex;
[...]

    name = rb_id2name(id);
[...]

 Just add

    if (rb_is_private_id(id)) {
       rb_raise(rb_eArgError, "private variable ... ");
    }
    name = rb_id2name(id);

Guy Decoux



Mon, 28 Feb 2005 14:08:31 GMT  
 private variables

Quote:

> Hi,

> In message "private variables"

> | Why I always write stupid things ? See the effect of attr_accessor with
> | private variable

> Oh, I forget to mention that private instance variables should not be
> exported by attr_accessor etc., because of the fact these variables
> are private.  Publicly exported private instance variable is
> contradicting existence.

>                                                    matz.

I wonder why. Could you give some concrete reason for it?

I thought, being private for a variable means that it can
only be acessed by the methods of its class to avoid
name collisions with instance variables in derived classes.

Regards, Christian



Mon, 28 Feb 2005 17:52:31 GMT  
 
 [ 88 post ]  Go to page: [1] [2] [3] [4] [5] [6]

 Relevant Pages 

1. PRIVATE variables (was parameters)

2. Lots of Public and Private variables - no penalties on modern PC.

3. Private variables can be changed outsid e?

4. Private variables can be changed outside?

5. private variables (again)

6. private variable

7. cant see PRIVATE variable in MODULE SUBROUTINE when debugging with IFC/IDB v7.1

8. Accessing private variable as pointer

9. Private variables in Visual Studio

10. Private variables

11. Private variables

12. mixed PUBLIC and PRIVATE variables in NAMELIST (Compaq compilers)

 

 
Powered by phpBB® Forum Software