About 1.9 #__method__ feature

Yukihiro Matsumoto wrote:

#method_missing is and will be called when you invoke private methods
with the receiver specified.

Great! Thank you..

I have come up with the following implementation as a more flexible
solution to BlankSlate. I called it InterfaceFilter for lack of a
better name. I see one prbolem though. It cannot react dynmically when
a new method is added to an ancestor. While, it would make sense if
#method_added triggered the same callback in effected sublasses, I
suppose that's too much overhead. Still, is their anyway to achieve
dynamic behavior here?

T.

module InterfaceFilter

  ESSENTIAL = [ 'funcall', 'send', 'object_id', 'object_class'
'equal?', '==', 'dup', 'clone' ]
  SECONDARY = [ 'class', 'respond_to?', 'inspect', 'hash' ]
  OPERATOR = [ /^\W$/ ]
  SHADOW = [ /^__/ ]
  QUERY = [ /\?$/ ]
  INSTANCE = [ /^instance_/ ]

  DEFAULT = ESSENTIAL | SECONDARY | SHADOW | OPERATOR | QUERY

···

#

  def self.included( base )
    base.const_set( 'InterfaceFilter', self )
  end

  #

  def self.( *patterns )
    cls = self.dup
    cls.preserve_features( patterns, public_instance_methods(true) )
    cls
  end

  #

  def self.preserve_features( patterns, methods=nil )
    patterns.flatten!
    methods ||= Kernel.public_instance_methods
    methods.each do |m|
      case m
      when *patterns
        public m
      else
        private m
      end
    end
  end

  preserve_features( DEFAULT )

end

#= begin test

  class X
    include InterfaceFilter[ InterfaceFilter::ESSENTIAL ]
  end

  x = X.new
  p X.ancestors
  p x.class
  p x.instance_variables

#=end

Hi --

Can you show me an example? I'm still not understanding. I'm
thinking of:

obj.funcall(:meth)

but maybe there's a different/new syntax for funcall? Is it now a
top-level method?

David

meth is the "top level" method.

e.g.:

class A
def initialize
   jump_up_and_down( ) # look, I'm calling a "function" (No explicit receiver)
end
private
def jump_up_and_down( )
   ...
end

That's why top level declared methods are private. It's to distinguish "function" methods from method methods. Hence the name "funcall" (call a "function")

I don't like it. It seems wrong to go through a non-functional style
to tell an object to call something internally in a functional style,
when in fact the "style" only referred to the lexical and
typographical convention in the first place.

Besides, if jump_up_and_down were not private, it could still be
called with an implicit receiver in A#initialize. I don't think that
puts it in a different category of method.

It also seems that the notion of a function (or "function method") is
emerging in Ruby as a kind of side effect of the new method names. I
don't see anything here that can't be handled thoroughly without this
notion.

David

···

On Wed, 5 Jul 2006, Logan Capaldo wrote:

On Jul 4, 2006, at 2:53 PM, dblack@wobblini.net wrote:

--
  "To fully realize the potential of Rails, it's crucial that you take
    the time to fully understand Ruby--and with "Ruby for Rails" David
       has provided just what you need to help you achieve that goal."
       -- DAVID HEINEMEIER HANSSON, in the foreword to RUBY FOR RAILS.
  Complete foreword & sample chapters at http://www.manning.com/black\!

So:

  class Foo
    def foo(*args)
    end
    private :foo

    def bar(*args)
    end
  end

  obj = Foo.new

  obj.foo(5) # Throws an error, just as now.
  obj.send(:foo, 5) # ???
  obj.funcall(:foo, 5) # ???

Will #funcall be the way that I can circumvent private?

-austin

···

On 7/4/06, Yukihiro Matsumoto <matz@ruby-lang.org> wrote:

Ah, maybe I didn't express myself clear.
  obj.send(:foo, args)
does work like
  obj.foo(args)
and
  obj.funcall(:foo, args)
works like
  foo(args)

--
Austin Ziegler * halostatue@gmail.com * http://www.halostatue.ca/
               * austin@halostatue.ca * You are in a maze of twisty little passages, all alike. // halo • statue
               * austin@zieglers.ca

Florian Gross wrote:

···

ara.t.howard@noaa.gov wrote:

> any idea of the limitations of Binding.of_caller?

It depends on a bug in Ruby (but that can be fixed as soon as that bug
is fixed) and will only work 100% correctly if you are using it in a
method that is called in the same context as its caller. For example
breakpoint() is OK, but Breakpoint.breakpoint() will not give you the
correct instance variables.

I don't think it is too slow. Not being able to restore previous trace
funcs is another downside, however.

Perhaps it is time to write a C extension for this after all?

I was never quite sure why it wasn't already. After all you can get the
binding of the caller if you pass a block,even an empty one.

    def x( &blk )
      Kernel.eval( "self", blk.binding )
    end

T.

I once wrote another Binding.of_caller that didn't use continuations and it
was much faster. But the interface was ugly.

···

On Wed, Jul 05, 2006 at 12:35:29AM +0900, Logan Capaldo wrote:

>>>I've somtimes wanted a way to get at the binding of the caller but
>>>Binding.of_caller is just too much of a hack and I can't bring myself to
>>>use it. But this would be a very elegant solution.
>>
>>I'd prefer having the functionality built-in as well. It might
>>happen in the next few years from what I understand.
>
>any idea of the limitations of Binding.of_caller?
>
Well you can't use a trace function when you are using binding of
caller, it has to be the last bit of code in a method that uses it,
and it uses continuations (which are slow).

--
Mauricio Fernandez - http://eigenclass.org - singular Ruby

transfire@gmail.com wrote:

I have come up with the following implementation as a more flexible
solution to BlankSlate. I called it InterfaceFilter

Hmm... I may again have overshot the solution. It's easy enough to
privatize methods as needed, one doesn't need a intervening module to
do that. So I'll push this back to a BlankSlate like class.

Also, I see now where the limitation on the dynamic behavior actually
lies:

  class X
    private :q
  end

  NameError: undefined method `q' for class `X'
        from (irb):2:in `private'
        from (irb):2

As with my method annotation system, one might wish to _predefine_ a
characeristic, in this case the visibility of a *potential* method. In
this way it could even be reused. Eg.

  module Shh
    private :s
  end

  class S
    include Shh
    def s
       "s"
    end
  end

  S.new.s #=> Error private method

Possible?

T.

···

from :0

Hi --

Can you show me an example? I'm still not understanding. I'm
thinking of:

obj.funcall(:meth)
but maybe there's a different/new syntax for funcall? Is it now a
top-level method?
David

meth is the "top level" method.

e.g.:

class A
def initialize
   jump_up_and_down( ) # look, I'm calling a "function" (No explicit receiver)
end
private
def jump_up_and_down( )
   ...
end

That's why top level declared methods are private. It's to distinguish "function" methods from method methods. Hence the name "funcall" (call a "function")

I don't like it. It seems wrong to go through a non-functional style
to tell an object to call something internally in a functional style,
when in fact the "style" only referred to the lexical and
typographical convention in the first place.

Besides, if jump_up_and_down were not private, it could still be
called with an implicit receiver in A#initialize. I don't think that
puts it in a different category of method.

It also seems that the notion of a function (or "function method") is
emerging in Ruby as a kind of side effect of the new method names. I
don't see anything here that can't be handled thoroughly without this
notion.

David

Well this is basically what matz. has said before, I just put my own words to it. The function method concept didn't come from the method name, matz. named the method #funcall based on his function method concept.

···

On Jul 4, 2006, at 3:21 PM, dblack@wobblini.net wrote:

On Wed, 5 Jul 2006, Logan Capaldo wrote:

On Jul 4, 2006, at 2:53 PM, dblack@wobblini.net wrote:

--
"To fully realize the potential of Rails, it's crucial that you take
   the time to fully understand Ruby--and with "Ruby for Rails" David
      has provided just what you need to help you achieve that goal."
      -- DAVID HEINEMEIER HANSSON, in the foreword to RUBY FOR RAILS.
Complete foreword & sample chapters at http://www.manning.com/black\!

Hi,

···

In message "Re: About 1.9 #__method__ feature." on Wed, 5 Jul 2006 04:23:51 +0900, "Austin Ziegler" <halostatue@gmail.com> writes:

Will #funcall be the way that I can circumvent private?

  obj.foo(5) # Throws an error, just as now.
  obj.send(:foo, 5) # Throws an error, it's private.
  obj.funcall(:foo, 5) # Success. funcall can call private.

what improvement does that give over

   obj.instance_eval{ send :foo, 5 }

??

i mean, what's the purpose of a public method which can call private methods?

-a

···

On Wed, 5 Jul 2006, Yukihiro Matsumoto wrote:

Hi,

In message "Re: About 1.9 #__method__ feature." > on Wed, 5 Jul 2006 04:23:51 +0900, "Austin Ziegler" <halostatue@gmail.com> writes:

>Will #funcall be the way that I can circumvent private?

obj.foo(5) # Throws an error, just as now.
obj.send(:foo, 5) # Throws an error, it's private.
obj.funcall(:foo, 5) # Success. funcall can call private.

--
suffering increases your inner strength. also, the wishing for suffering
makes the suffering disappear.
- h.h. the 14th dali lama

Okay. Next: what will the non-overridable versions of these methods be?
Will I have to do

  Object.method(:send).bind(obj).call(:foo, 5)

or will there be an equivalent to #__send__ still? Will #object_id be
overridable? I would prefer to have a simple, clear way that *cannot be
overridden* to get at these values which, for readability purposes, can
or should be overridden. (#send is a particularly nasty example, since
Mail#send would be appropriate. :wink:

I am not a fan of #funcall -- yes, it's called without an explicit
receiver, but it *is* called with an implicit receiver. Given that this
is the case, I think that the #send/#send! dichotomy is not appropriate.

Trans had a suggestion that I've chewed on for a while and think might
be worthwhile considering for this sort of thing. Perhaps we need these
sorts of methods to be external to classes, say Meta:

  Meta.object_id(obj)
  Meta.send(obj, :foo, 5) # fails on private
  Meta.implicit_send(obj, :foo, 5) # succeeds on private

I'm not sure. I do think that #implicit_send is better than #funcall,
and maybe #explicit_send is better than #send.

-austin

···

On 7/4/06, Yukihiro Matsumoto <matz@ruby-lang.org> wrote:

Me:

Will #funcall be the way that I can circumvent private?

  obj.foo(5) # Throws an error, just as now.
  obj.send(:foo, 5) # Throws an error, it's private.
  obj.funcall(:foo, 5) # Success. funcall can call private.

--
Austin Ziegler * halostatue@gmail.com * http://www.halostatue.ca/
               * austin@halostatue.ca * You are in a maze of twisty little passages, all alike. // halo • statue
               * austin@zieglers.ca

transfire@gmail.com wrote:

Hmm... I may again have overshot the solution. It's easy enough to
privatize methods as needed, one doesn't need a intervening module to
do that. So I'll push this back to a BlankSlate like class.

I have to be honest. I feel like a complete schmuck here. Coming to the
full relaization that method_missing catches public calls to private
methods means that BlankSlate is a lot of fuse over a very little --a
handful of methods, whch could just as easily be declared private. If
only I had realized sooner! Oh, well. Live and learn. Anyway, throwing
out BlankSlate sure makes things simpler. Something I always like.

One thing though. Like #id before it, many times I find myself wanting
to use an attribute called 'class' but that gets in the way of the
Kernel method. Maybe #object_class, like #object_id,would actually be
better?

Thanks for helping me see the light.
T.

Would obj.instance_eval { send(:foo, 5) } allow the call of private
methods? However, the purpose is that #send (and #__send__) allow the
call of private methods already. The change in 1.9 is that #send
doesn't allow, but people depend on that, and it seems to me that
#instance_eval (or #instance_exec -- which does what, exactly?) would
be heavier weight than an explicit method.

-austin

···

On 7/4/06, ara.t.howard@noaa.gov <ara.t.howard@noaa.gov> wrote:

> >Will #funcall be the way that I can circumvent private?
> obj.foo(5) # Throws an error, just as now.
> obj.send(:foo, 5) # Throws an error, it's private.
> obj.funcall(:foo, 5) # Success. funcall can call private.
what improvement does that give over

   obj.instance_eval{ send :foo, 5 }

i mean, what's the purpose of a public method which can call private methods?

--
Austin Ziegler * halostatue@gmail.com * http://www.halostatue.ca/
               * austin@halostatue.ca * You are in a maze of twisty little passages, all alike. // halo • statue
               * austin@zieglers.ca

Hi,

···

In message "Re: About 1.9 #__method__ feature." on Wed, 5 Jul 2006 06:26:14 +0900, ara.t.howard@noaa.gov writes:

obj.funcall(:foo, 5) # Success. funcall can call private.

what improvement does that give over

  obj.instance_eval{ send :foo, 5 }

??

Succinctness.

              matz.

Austin Ziegler wrote:

Okay. Next: what will the non-overridable versions of these methods be?
Will I have to do

  Object.method(:send).bind(obj).call(:foo, 5)

or will there be an equivalent to #__send__ still? Will #object_id be
overridable? I would prefer to have a simple, clear way that *cannot be
overridden* to get at these values which, for readability purposes, can
or should be overridden. (#send is a particularly nasty example, since
Mail#send would be appropriate. :wink:

I am not a fan of #funcall -- yes, it's called without an explicit
receiver, but it *is* called with an implicit receiver. Given that this
is the case, I think that the #send/#send! dichotomy is not appropriate.

Trans had a suggestion that I've chewed on for a while and think might
be worthwhile considering for this sort of thing. Perhaps we need these
sorts of methods to be external to classes, say Meta:

  Meta.object_id(obj)
  Meta.send(obj, :foo, 5) # fails on private
  Meta.implicit_send(obj, :foo, 5) # succeeds on private

It does seem appropriate that introspection be handled externally. I
sort like the idea of global functions:

   $object_id(obj)
   $send(obj, :foo, 5)
   $funcall(obj, :foo, 5)

That certianly makes it clear one is in the meta programming realm. But
do we need to go so far?
Well, I think something is in order. As it is the meta programmer is
roughing it, with things like you're binding example. When meta
programming it's important to have garunteed way to get the object_id
and other such information about an object. It's also important to be
able to bypass method privacy.

So what if we followed a simple rule that all methods starting with
#object_ or #instance_ were not overridable? And we could add
#object_send and #instance_send. The former always routes to the Object
binding and the later bypasses privacy. With a few other adjustments
(eg. object_class, object_tainted?, etc.) I think that would be an
effective and straight foward solution.

T.

instance_exec() is instance_eval() with arguments that get passed
through to the block, e.g.

   obj.instance_exec(42) {|x| instance_method_do_something_with(x) }

Regards,
Sean

···

On 7/4/06, Austin Ziegler <halostatue@gmail.com> wrote:

#instance_exec -- which does what, exactly?

You also mentioned performance in the past IIRC (on your blog?).

···

On Wed, Jul 05, 2006 at 04:37:50PM +0900, Yukihiro Matsumoto wrote:

Hi,

In message "Re: About 1.9 #__method__ feature." > on Wed, 5 Jul 2006 06:26:14 +0900, ara.t.howard@noaa.gov writes:

>> obj.funcall(:foo, 5) # Success. funcall can call private.
>
>what improvement does that give over
>
> obj.instance_eval{ send :foo, 5 }
>
>??

Succinctness.

--
Mauricio Fernandez - http://eigenclass.org - singular Ruby

Hi --

Hi,

>> obj.funcall(:foo, 5) # Success. funcall can call private.
>
>what improvement does that give over
>
> obj.instance_eval{ send :foo, 5 }
>
>??

Succinctness.

Until people start saying, "Wait -- I thought these things were called
'methods' in Ruby. What's a 'function'? Is it a method? Is it just
a method without an explicit receiver? And does that mean you can
never 'funcall' a setter method, since they *always* require an
explicit receiver? But when you 'funcall' a symbol, you're not using
method-call syntax anyway, so the idea of an 'explicit receiver' is
irrelevant and meaningless. Is there a 'function' method, similar to
'method' but including private methods? But why are private methods
called 'methods' at all, if they're 'functions' in 1.9?...."

Then it gets less succinct :slight_smile: I'm afraid I still don't know the
answers to these questions. I do understand the "functional style"
method call (though I don't understand how it relates to "funcall",
since funcall isn't done in a functional style). But I've always
thought that functional style was one of these things that grew
organically out of the design of the language, without having to be
named and ingrained at the language level:

     method call
   + situation where implied receiver can (or must) be used

···

On Wed, 5 Jul 2006, Yukihiro Matsumoto wrote:

In message "Re: About 1.9 #__method__ feature." > on Wed, 5 Jul 2006 06:26:14 +0900, ara.t.howard@noaa.gov writes:

     ----------------------------
   = functional style

Now it seems like this:

     method call <--------------------------------
   % explicitness of receiver ^
     ------------------------ ^
   = whoops -- "method" should have been "function" ^

and also:

     obj.funcall(:meth)
   % if this were a lexical method call,
       would the receiver have been explicit?
     ----------------------------------------
   = decision whether "funcall" was calling a method or a function

It all seems so non-linear, doesn't it?

David

--
  "To fully realize the potential of Rails, it's crucial that you take
    the time to fully understand Ruby--and with "Ruby for Rails" David
       has provided just what you need to help you achieve that goal."
       -- DAVID HEINEMEIER HANSSON, in the foreword to RUBY FOR RAILS.
  Complete foreword & sample chapters at http://www.manning.com/black\!

Hi,

···

In message "Re: About 1.9 #__method__ feature." on Wed, 5 Jul 2006 20:00:08 +0900, dblack@wobblini.net writes:

Until people start saying, "Wait -- I thought these things were called
'methods' in Ruby. What's a 'function'? Is it a method? Is it just
a method without an explicit receiver?

But we already have module_function, which has never been complained
for more than 10 years. I think it's OK to meet small confusion for
the first timers, if we can use the name with right mnemonic for the
functionality. Probably the reason behind the funcall is my Lisp
background.

              matz.

How about instance_send (on analogy with instance_eval and instance_exec)?

Regards,
Sean

···

On 7/7/06, Yukihiro Matsumoto <matz@ruby-lang.org> wrote:

... I think it's OK to meet small confusion for
the first timers, if we can use the name with right mnemonic for the
functionality. Probably the reason behind the funcall is my Lisp
background.

                                                        matz.

Hi --

Hi,

>Until people start saying, "Wait -- I thought these things were called
>'methods' in Ruby. What's a 'function'? Is it a method? Is it just
>a method without an explicit receiver?

But we already have module_function, which has never been complained
for more than 10 years. I think it's OK to meet small confusion for
the first timers, if we can use the name with right mnemonic for the
functionality. Probably the reason behind the funcall is my Lisp
background.

I'm not a first timer though, and I find it confusing :slight_smile: You're
right about module_function, but it also (in my experience) doesn't
get used much.

The functionality we're talking about, as I understand it, is: send a
message to an object, with the stipulation that the object treat the
message indifferently with respect to the access level of the method
(if any) that corresponds to the message.

To me, that leads to things like send! or absolute_send or inner_send
or instance_send (which I think Sean O'Halpin just suggested). It's
still basically a "send" operation.

The part I don't understand is why the inclusion of private methods
suddenly makes it something other than a "send" -- why it requires a
(basically) new concept, the concept of objects having "functions" and
responding directly to "call" requests.

David

···

On Fri, 7 Jul 2006, Yukihiro Matsumoto wrote:

In message "Re: About 1.9 #__method__ feature." > on Wed, 5 Jul 2006 20:00:08 +0900, dblack@wobblini.net writes:

--
  "To fully realize the potential of Rails, it's crucial that you take
    the time to fully understand Ruby--and with "Ruby for Rails" David
       has provided just what you need to help you achieve that goal."
       -- DAVID HEINEMEIER HANSSON, in the foreword to RUBY FOR RAILS.
  Complete foreword & sample chapters at http://www.manning.com/black\!