Nested defs, what if

This is too half-baked to be an RCR, but here goes...

At the moment we cannot write

class Thingy
   def somefunc
     def newfunc
       ...
     end
   end
end

OK, fair enough, somefunc is an instance method, so what would
newfunc get defined as? It could not be an instance method because
it might depend on variables having values which differ in another
instance.

So, my half-baked idea: let the above code be a shorthand for

class Thingy
   def somefunc
     class << self
       def newfunc
         ...
       end
     end
   end
end

This would have the [questionable] advantage that it would hide that
relatively obscure class << self syntax used in constructing
singletons, and it would be better tnan passing a string to instance
eval because it would get syntax highlighted by the editor.

It is not legal now, so old code would not break.

So, now I'll push this idea out and see if it sinks...

         Hugh

irb(main):001:0> class Thingy
irb(main):002:1> def somefunc
irb(main):003:2> def newfunc
irb(main):004:3> end
irb(main):005:2> end
irb(main):006:1> end
irb(main):007:0> Thingy.instance_methods.grep(/func/)
=> ["somefunc"]
irb(main):009:0> Thingy.new.somefunc
=> nil
irb(main):010:0> Thingy.instance_methods.grep(/func/)
=> ["newfunc", "somefunc"]

-austin

···

On Thu, 2 Dec 2004 23:44:08 +0900, Hugh Sasse Staff Elec Eng <hgs@dmu.ac.uk> wrote:

This is too half-baked to be an RCR, but here goes...

At the moment we cannot write

class Thingy
   def somefunc
     def newfunc
       ...
     end
   end
end

--
Austin Ziegler * halostatue@gmail.com
               * Alternate: austin@halostatue.ca

Hi,

···

In message "Re: nested defs, what if..." on Thu, 2 Dec 2004 23:44:08 +0900, Hugh Sasse Staff Elec Eng <hgs@dmu.ac.uk> writes:

So, my half-baked idea: let the above code be a shorthand for

class Thingy
  def somefunc
    class << self
      def newfunc
        ...
      end
    end
  end
end

I had the same half-baked idea before, but has not been sure how much
it is useful. If you come up a new insight, it might be happened.

              matz.

OH!! This didn't work in the past. I never noticed it change.

I'll have to see what happens when it depends on variable values
then ...

         Hugh (somewhat embarrassed)

···

On Thu, 2 Dec 2004, Austin Ziegler wrote:

irb(main):007:0> Thingy.instance_methods.grep(/func/)
=> ["somefunc"]
irb(main):009:0> Thingy.new.somefunc
=> nil
irb(main):010:0> Thingy.instance_methods.grep(/func/)
=> ["newfunc", "somefunc"]

Hi,

         [...]

I had the same half-baked idea before, but has not been sure how much
it is useful. If you come up a new insight, it might be happened.

              matz.

Thanks, Matz. If I get struck by any "bolts of inspiration" I'll
let you know.
         Thank you,
         Hugh

···

On Fri, 3 Dec 2004, Yukihiro Matsumoto wrote:

But where is this usefull? It seems only complicated and inefficent to me
(Doesn't it create a new instance method on each call?):

class A
  def a()
    def b()
      self
    end
    self
  end
end
    ==>nil
A.new.b
NoMethodError: undefined method `b' for #<A:0x402c0834>
        from (irb):2
A.new.a
    ==>#<A:0x402a9cb0>
A.new.a.b
    ==>#<A:0x4029bad4>
A.new.b
    ==>#<A:0x40295864>

···

On Thu, 2 Dec 2004 23:57:09 +0900 Austin Ziegler <halostatue@gmail.com> wrote:

On Thu, 2 Dec 2004 23:44:08 +0900, Hugh Sasse Staff Elec Eng > <hgs@dmu.ac.uk> wrote:
> This is too half-baked to be an RCR, but here goes...
>
> At the moment we cannot write
>
> class Thingy
> def somefunc
> def newfunc
> ...
> end
> end
> end

irb(main):001:0> class Thingy
irb(main):002:1> def somefunc
irb(main):003:2> def newfunc
irb(main):004:3> end
irb(main):005:2> end
irb(main):006:1> end
irb(main):007:0> Thingy.instance_methods.grep(/func/)
=> ["somefunc"]
irb(main):009:0> Thingy.new.somefunc
=> nil
irb(main):010:0> Thingy.instance_methods.grep(/func/)
=> ["newfunc", "somefunc"]

--
Brian Schröder
http://www.brian-schroeder.de/

It is interesting. Does this mean that an _object_ could dynamically change
the state of all objects of its class? I have to test....

class T
  def a
    def b
      puts "Hello"
    end
end
end => nil
t = T.new => #<T:0x4032cb14>
t2 = T.new => #<T:0x4032ae90>
t.b => NoMethodError: undefined method `b' for #<T:0x4032cb14>
t2.b => NoMethodError: undefined method `b' for #<T:0x4032ae90>
t.a => nil
t.b => nil
Hello
t2.b => nil
Hello

Yep. It sure does. This is very strange indeed. I wonder if you could write
extentions in this way.

  class String
    def use(x)
      case x
      when :chars
        def chars
          self.split(//)
        end
      when :tab
        # ...
      end
    end
  end

Of course, you have to instantiate a string first.

Well, it's an idea, but I don't think a very good one. In general I don't
think this is useful, and would rather obfuscate code if actually used. I
think what would be more useful is if such methods were local methods, like
local variables:

  class A
    def a
      def b(x)
        x + 1
      end
      10.times{ |i| print b(i) }
    end
  end

  o = A.new
  o.b => NoMethodError
  A.a => 12345678910
  o.b => NoMethodError

This would allow for embedded subroutines --much more useful.

T.

···

On Thursday 02 December 2004 12:22 pm, Brian Schröder wrote:

But where is this usefull? It seems only complicated and inefficent to me
(Doesn't it create a new instance method on each call?):

class A
  def a()
    def b()
      self
    end
    self
  end
end
    ==>nil
A.new.b
NoMethodError: undefined method `b' for #<A:0x402c0834>
        from (irb):2
A.new.a
    ==>#<A:0x402a9cb0>
A.new.a.b
    ==>#<A:0x4029bad4>
A.new.b
    ==>#<A:0x40295864>

Hi,

At Fri, 3 Dec 2004 08:20:34 +0900,
trans. (T. Onoma) wrote in [ruby-talk:122265]:

Well, it's an idea, but I don't think a very good one. In general I don't
think this is useful, and would rather obfuscate code if actually used. I
think what would be more useful is if such methods were local methods, like
local variables:

I also have thought the idea, though haven't implemented it.
I'm still worndering whether this should be valid or error.

  class A
    def a(y)
      def b(x)
        x + y # `y' in a or `undefined local variable'?
      end
      10.times{ |i| print b(i) }
    end
  end

···

--
Nobu Nakada

This would also make Ruby more like LISP, which allows any depth of inner functions to be defined. Those inner functions are only in scope in the defining function.

Ruby's blocks function this way right now, actually. That is, to achieve the above effect, you could do:

class A
   def a
     b = proc do |x|
       x + 1
     end
     10.times { |i| print b.call(i) }
   end
end

o = A.new
     ==>#<A:0x49708>
o.b
NoMethodError: undefined method `b' for #<A:0x49708>
         from (irb):10
o.a
12345678910 ==>10
o.b
NoMethodError: undefined method `b' for #<A:0x49708>
         from (irb):13

In this example, b is a reference to a block, rather than a method, and b is only in scope within a().

Embedded subroutines can indeed be useful, especially in recursive methods that use an "interface method" and a "worker method" that takes extra parameters. For example:

def fact( n )
   def fact_iter( n, total )
     if n == 1
       total
     else
       fact_iter( n - 1, total * n )
     end
   end

   fact_iter( n, 1 )
end

fact( 3 ) ==> 6

In this case, fact_iter() doesn't need to be visible to the outside world; but the way Ruby currently works, the following can happen:

fact_iter( 3 ) ==> 6

The question becomes, though, whether or not fact_iter() is being defined every time fact() is called. It shouldn't be hard to optimize around this redefinition problem. (Does Ruby already do so?)

Pacem in terris / Mir / Shanti / Salaam / Heiwa
Kevin R. Bullock

···

On Dec 2, 2004, at 5:20 PM, trans. (T. Onoma) wrote:

Well, it's an idea, but I don't think a very good one. In general I don't
think this is useful, and would rather obfuscate code if actually used. I
think what would be more useful is if such methods were local methods, like
local variables:

  class A
    def a
      def b(x)
        x + 1
      end
      10.times{ |i| print b(i) }
    end
  end

  o = A.new
  o.b => NoMethodError
  A.a => 12345678910
  o.b => NoMethodError

This would allow for embedded subroutines --much more useful.

I tried this in fact while learning ruby, and was disappointed, that it did not
work the way I expected. The last language before Ruby was Delphi (Object
Pascal) where you can have nested subroutines. I think they are a lot clearer
than having to flatten everything out.

Regards,

Brian

···

On Fri, 3 Dec 2004 08:20:34 +0900 "trans. (T. Onoma)" <transami@runbox.com> wrote:

[snip]
Well, it's an idea, but I don't think a very good one. In general I don't
think this is useful, and would rather obfuscate code if actually used. I
think what would be more useful is if such methods were local methods, like
local variables:

  class A
    def a
      def b(x)
        x + 1
      end
      10.times{ |i| print b(i) }
    end
  end

  o = A.new
  o.b => NoMethodError
  A.a => 12345678910
  o.b => NoMethodError

This would allow for embedded subroutines --much more useful.

--
Brian Schröder
http://www.brian-schroeder.de/

Is there any difference between an "inner method" (with 'y' in a) and
a lambda?

I've happily used lambdas to define private functionality before, but
I'm concerned about efficiency:

  class A
    def a(y)
      b = lambda { |x| x + y }
      10.times { |i| print b(i) }
    end
  end

Does the lambda attached to b get regenerated with each call to a?

Gavin

···

On Friday, December 3, 2004, 1:47:32 PM, nobu wrote:

Hi,

At Fri, 3 Dec 2004 08:20:34 +0900,
trans. (T. Onoma) wrote in [ruby-talk:122265]:

Well, it's an idea, but I don't think a very good one. In general I don't
think this is useful, and would rather obfuscate code if actually used. I
think what would be more useful is if such methods were local methods, like
local variables:

I also have thought the idea, though haven't implemented it.
I'm still worndering whether this should be valid or error.

  class A
    def a(y)
      def b(x)
        x + y # `y' in a or `undefined local variable'?
      end
      10.times{ |i| print b(i) }
    end
  end

Hi,

At Fri, 3 Dec 2004 14:00:44 +0900,
Gavin Sinclair wrote in [ruby-talk:122305]:

> class A
> def a(y)
> def b(x)
> x + y # `y' in a or `undefined local variable'?
> end
> 10.times{ |i| print b(i) }
> end
> end

Is there any difference between an "inner method" (with 'y' in a) and
a lambda?

Actually, no. Just a syntax sugar, and it would be implemented
using a lambda. And another question; should b be visible from
other methods called from a?

I've happily used lambdas to define private functionality before, but
I'm concerned about efficiency:

  class A
    def a(y)
      b = lambda { |x| x + y }
      10.times { |i| print b(i) }
    end
  end

Does the lambda attached to b get regenerated with each call to a?

I guess so.

···

--
Nobu Nakada

Hi,

At Fri, 3 Dec 2004 14:00:44 +0900,
Gavin Sinclair wrote in [ruby-talk:122305]:

> class A
> def a(y)
> def b(x)
> x + y # `y' in a or `undefined local variable'?
> end
> 10.times{ |i| print b(i) }
> end
> end

Is there any difference between an "inner method" (with 'y' in a) and
a lambda?

Actually, no. Just a syntax sugar, and it would be implemented
using a lambda. And another question; should b be visible from
other methods called from a?

I don't think so. I can't imagine a use case, and the _appearance_ of
the code is that b() is private to a().

I've happily used lambdas to define private functionality before, but
I'm concerned about efficiency:

  class A
    def a(y)
      b = lambda { |x| x + y }
      10.times { |i| print b(i) }
    end
  end

Does the lambda attached to b get regenerated with each call to a?

I guess so.

So an inner method, which _looks_ static, would actually be
inefficiently regenerated each time? (You said the inner method would
be syntax sugar for a lambda.)

Gavin

···

On Friday, December 3, 2004, 4:18:38 PM, nobu wrote:

Hi --

Gavin Sinclair wrote in [ruby-talk:122305]:
> > class A
> > def a(y)
> > def b(x)
> > x + y # `y' in a or `undefined local variable'?
> > end
> > 10.times{ |i| print b(i) }
> > end
> > end
>
> Is there any difference between an "inner method" (with 'y' in a) and
> a lambda?

Actually, no. Just a syntax sugar, and it would be implemented
using a lambda. And another question; should b be visible from
other methods called from a?

First, it is debatable as to whether `y' should have an open scope like a
lambda. But I think "no". def a() cannot see vars outside its scope either,
so nor should def b(). This gives good inner namespace protection and
differentiates its functionality from a lambda. Second, b() should not be
visible from other methods just a local vars are not visible.

I am surprised to hear they would be implemented using lambdas. I was under
the impression that implementation of Procs and Methods are quite different.

> I've happily used lambdas to define private functionality before, but
> I'm concerned about efficiency:
>
> class A
> def a(y)
> b = lambda { |x| x + y }
> 10.times { |i| print b(i) }
> end
> end
>
> Does the lambda attached to b get regenerated with each call to a?

Yes, I think so since lambdas are not singleton/multiton (could they be?) Of
course the fix is something like:

   class A
     def a(y)
       @a_b ||= lambda { |x| x + y }
       10.times { |i| print @a_b(i) }
     end
   end

But true inner methods would be the bomb for these use cases (IMHO).

T.

···

On Friday 03 December 2004 12:18 am, nobu.nokada@softhome.net wrote:

Yea, that's not good. They need to persist, bound to the local scope.

T.

···

On Friday 03 December 2004 12:37 am, Gavin Sinclair wrote:

So an inner method, which _looks_ static, would actually be
inefficiently regenerated each time? (You said the inner method would
be syntax sugar for a lambda.)

Yes, I think so since lambdas are not singleton/multiton (could they be?) Of
course the fix is something like:

   class A
     def a(y)
       @a_b ||= lambda { |x| x + y }
       10.times { |i| print @a_b(i) }
     end
   end

Not quite...

class A; def a(y); @a_b ||= lambda { |x| x + y }; 10.times { |i|
print @a_b[i]}; end end

=> nil

a = A.new

=> #<A:0x401fda10>

a.a(10)

10111213141516171819=> 10

a.a(1000)

10111213141516171819=> 10

But true inner methods would be the bomb for these use cases (IMHO).

They don't seem any more powerful than lambdas, just sugar.
They would offer some opportunities for optimization though.

···

On Fri, Dec 03, 2004 at 03:02:49PM +0900, trans. (T. Onoma) wrote:

--
Hassle-free packages for Ruby?
RPA is available from http://www.rubyarchive.org/

> Yes, I think so since lambdas are not singleton/multiton (could they be?)
> Of course the fix is something like:
>
> class A
> def a(y)
> @a_b ||= lambda { |x| x + y }
> 10.times { |i| print @a_b(i) }
> end
> end

Not quite...
>> class A; def a(y); @a_b ||= lambda { |x| x + y }; 10.times { |i|
>> print @a_b[i]}; end end
=> nil
>> a = A.new
=> #<A:0x401fda10>
>> a.a(10)
10111213141516171819=> 10
>> a.a(1000)
10111213141516171819=> 10

Ah right. There's a gotchya. Try,

    class A
      def a(y)
        @a_b ||= lambda { |x,y| x + y }
        10.times { |i| print @a_b(i,y) }
      end
    end

I think this is another reason for having the inner defs with a protected
scope.

> But true inner methods would be the bomb for these use cases (IMHO).

They don't seem any more powerful than lambdas, just sugar.
They would offer some opportunities for optimization though.

Depends on the meaning of "powerful". But see above. Scope isolation can be
advantageous. And, yes, optimization would be nice too.

T.

···

On Friday 03 December 2004 04:00 am, Mauricio Fernández wrote:

On Fri, Dec 03, 2004 at 03:02:49PM +0900, trans. (T. Onoma) wrote: