How do I catch a missing method on a passed block?

[email protected] wrote:

class Foo
def bar(*args, &block)
if block_given?
class << block
@@return = {}
lambd.define_method(:method_missing, (m, *args, &b)
return @@return.merge!({ m.to_sym => args })
end

Whoops, that wasn’t actually my code :-/ Just to restore a little
credibility it should have read;

      def method_missing(m, *args, &block)
        return @@return << { m.to_sym => args }
      end
   end
   attributes = lambd.instance_eval(&block)
 end
 p attributes

end
end

Which works fine ( I do want to reset @@return each time).

   method_calls = {}

end
But this is nicer because the class variable was a kludge because I
couldn’t figure out how to keep a variable from outside the block in
scope.

Thanks,
James

I’ve some comments, on almost all code in this thread. Feel
free to ignore me…

All code is “polluted” with meta-code stuff and “class <<
object” stuff and “instance_eval” stuff and “class_eval” stuff
and other stuff. That doesn’t feel good. Well, you need this
code to do the trick, but…

It’s usually a good idea to separate business logic and low
level code. The novice programmers and mediocre programmers can
concentrate on the business level code, while the more seasoned
programmer can write the low-level code. The novice programmer
is the user of the code made by the smart guy.

The novice programmer only sees clean code: He understands what
he is doing and is happy. Smart Guy is the, well, uh, smart guy
and is happy too. Everybody’s happy!

I’ve mixed business code and low-level code myself, in the
past. After one month, I simply couldn’t read my own code,
solely because I was mixing both levels. So, even if you are a
smart guy and the only developer, it’s still a good idea to
think and code on different levels.

I’ve rewritten one of the examples. Lines 1-12 are (is?)
low-level code (generic) and can and should be hidden in a
library. Lines 14-28 are (is?) the business code (non-generic).

On line 16, we wrap the received block, which could easily be
commented out, if necessary. Method_missing_inspect calls
block_with_method_missing with the given block and a
(non-generic) method_missing block. Block_with_method_missing
enriches the given block1 with a method_missing (which is
implemented by block2) and returns the enriched block1.

The result is that Foo#bar, the business logic, is still very
clean and very readable. Method_missing_inspect is a bit more
sophisticated, but still understandable for Joe Average.
Block_with_method_missing is the work of Smart A^HGuy…

Just my thoughts. Ignore me, if appropriate…

gegroet,
Erik V. - http://www.erikveen.dds.nl/


 1  module Kernel
 2    def block_with_method_missing(block1, &block2)
 3      class << block1
 4        self
 5      end.module_eval do
 6        define_method(:method_missing, &block2)
 7        define_method(:call){block1.instance_eval(&block1)}
 8      end
 9
10      block1
11    end
12  end
13
14  class Foo
15    def bar(&block)
16      block = method_missing_inspect(block)
17
18      block.call
19    end
20
21    def method_missing_inspect(block)
22      block_with_method_missing(block) do |method_name, *args|
23        p [:mm, method_name, args]
24      end
25    end
26  end
27
28  Foo.new.bar{baz(1, 2, 3)}

Erik V. wrote:

concentrate on the business level code, while the more seasoned
smart guy and the only developer, it’s still a good idea to
think and code on different levels.

— snip —

Erik, thank you for pre-empting my next challenge and giving me a good
lesson in structure. Making the transition from mediocre to smart could
be more about structuring the code than knowing the language better :wink:

James

Hi –

On Wed, 13 Dec 2006, Erik V. wrote:

I’ve some comments, on almost all code in this thread. Feel
free to ignore me…

All code is “polluted” with meta-code stuff and “class <<
object” stuff and “instance_eval” stuff and “class_eval” stuff
and other stuff. That doesn’t feel good. Well, you need this
code to do the trick, but…

I guess “polluted” is relative. I admit I’ve never understood the
fuss that people make over these things, one way or the other – that
is, I neither see them as a badge of some kind of wizardry, nor think
that they are to be shunned or stigmatized. They’re just ways to live
productively in the Ruby landscape, where there are objects and
objects have singleton classes and there’s a ‘self’ and so on. I
guess class << obj requires more ramping up than x = 1, but on the
whole I think Ruby is much flatter than it’s often given credit for.

Most of what people need to grasp and embrace, in order to understand
and use the vast bulk of these techniques, and others, is:

  • classes are objects
  • each object (or almost each object) has both a “birth class” and a
    singleton class
  • objects don’t have methods; they look for them along a
    class/module search path, with well-defined rules of order and
    inclusion
  • there’s one and only one ‘self’ at every point in the program
  • instance variables belong to ‘self’, always
  • class variables are completely unrelated to instance variables,
    in spite of the use of @ in one and @@ in the other
  • the def and class keywords start new local scopes
  • the class keyword can take either a constant (for a named class)
    or a “<< object” expression (for a singleton class)

I’m not saying that’s the whole language, of course; but probably
about 90% of the problems I’ve seen people have with Ruby over the
years – with the language generally, with understanding code they
see, and with solving specific problems in their own code – come from
not understanding one or more of these points. Class variables are
perhaps the worst offenders: they cause no end of confusion. The role
of ‘self’, particularly as it governs ownership of instance variables,
is also a bit of a hurdle – but not insurmountable.

I’m all for organizing code nicely, and grouping together things that
belong together, as you suggest. But what’s been concerning me
recently is that it feels like people are being encouraged to feel
awestruck and out of their depth when they see “class << object”.
Yes, it looks different from “class C” but I just don’t think it’s
that big a deal. The underlying principles are relatively few; the
language is expressive; and it all works together rather nicely.

David

Hi –

On Wed, 13 Dec 2006, J2M wrote:

mind at the same time. Breaking the code into those 3 methods helped
encapsulate those concepts in a way that was less effort to think
about. To me it wasn’t about inspiring awe but rather removing the
complexity.

Definitely. I think breaking the code down is fine (I might avoid
adding to Kernel, but that’s another story :slight_smile: I was chiming in more
on some of the stuff Erik raised by way of context. And of course
there’s a long history of the dividing of “regular” from “meta” in
Ruby, and a fairly long history of my skepticism of it. Erik’s post
just put me in mind of the whole thing.

David

[email protected] wrote:

  • instance variables belong to ‘self’, always
  • class variables are completely unrelated to instance variables,
    in spite of the use of @ in one and @@ in the other
  • the def and class keywords start new local scopes
  • the class keyword can take either a constant (for a named class)
    or a “<< object” expression (for a singleton class)

This is a useful summary of the key concepts that moved me forward. I
have a long way to go, but it clearly encapsulates the crossing of a
rubicon (sic).

I’m not saying that’s the whole language, of course; but probably
about 90% of the problems I’ve seen people have with Ruby over the
years – with the language generally, with understanding code they
see, and with solving specific problems in their own code – come from
not understanding one or more of these points. Class variables are
perhaps the worst offenders: they cause no end of confusion. The role
of ‘self’, particularly as it governs ownership of instance variables,
is also a bit of a hurdle – but not insurmountable.

Absolutely, the questions I raised on this thread were founded in a
need to know how to apply these concepts, which is why everybody’s
feedback has been incredibly valuable. I may have grasped the concepts
but the application takes a little longer.

I’m all for organizing code nicely, and grouping together things that
belong together, as you suggest. But what’s been concerning me
recently is that it feels like people are being encouraged to feel
awestruck and out of their depth when they see “class << object”.
Yes, it looks different from “class C” but I just don’t think it’s
that big a deal. The underlying principles are relatively few; the
language is expressive; and it all works together rather nicely.

Erik’s code offered a clean way of extracting some of the aspects that
can be re-used, whether I call the remaining code business logic or not
in this example is irrelevant, but it does present a neat way of
structuring things but being reminded that I have a lot to learn
doesn’t always feel great!

The big lesson I got from Erik was in reflecting on both your comments
and Erik’s example code is the clarity of understanding comes from the
ability to grasp and reflect on a number of principles concurrently.
That can be a very hard thing to do - keeping all those principles in
mind at the same time. Breaking the code into those 3 methods helped
encapsulate those concepts in a way that was less effort to think
about. To me it wasn’t about inspiring awe but rather removing the
complexity.

James

Hi –

On Thu, 14 Dec 2006, Giles B. wrote:

  • instance variables belong to ‘self’, always
    these principles, and help me understand them.
    If they’re not of practical value, then they’re not of value. So I’ll
    give it a try :slight_smile:

but of course it doesn’t work, because it’s not an instance method but
a class method. Is this a good place for class_eval? I could be way
off.

Actually now that I re-read it, I think I do understand the basic
concepts, I think I’m just weak on the syntax.

In general, if you want to do:

alias old_x x

you want to do so inside a class definition body for the class where x
is defined (or a subclass of that class).

A “class method” is basically a singleton method of a Class object.
That means that the class where it’s defined is the singleton method
of that class object (because that’s what singleton classes are: the
places where objects’ singleton methods are defined).

In your case, the object in question is Thing. To get into a class
definition body for a singleton class, you use the class keyword plus
the “<< object” construct:

class << Thing

You can now perform the aliasing:

 alias original_full_text_search full_text_search
 # redefinitions etc. will follow here

end

Here’s a complete mini-example:

class Thing
def self.x
puts “old x”
end
end

class << Thing
alias old_x x
def x
puts “new x…”
old_x
end
end

Thing.x

David

Simple question, i come from a C/++ background and i’m just really
starting to get “real things done with ruby” ( that should be a book
title). Anyway as i start writing methods that return objects and
variables and take objects and variables i’ve started to wonder how they
actually get passed around. I haven’t found a specific pointer or
reference type construction, although since everything i’ve tried to do
has worked i’ve not tried very hard.

I’m guessing that everything gets passed around by reference? Is that
true? Also what about situations where you’d really want to use a
pointer, like referring to huge things or ,god forbid, doing grimy
things with arrays. It is very nice having all these things automated,
like the garbage collection etc, but i still find myself wanting to free
things. I’ve only just gotten over wanting to semi-colon every
statement.

Probably by asking this i’m showing how i really haven’t groked ruby at
all. I’m happy to admit that.

Thanks

On 12/13/06, Christopher Coleman-Smith [email protected]
wrote:

pointer, like referring to huge things or ,god forbid, doing grimy
things with arrays. It is very nice having all these things automated,
like the garbage collection etc, but i still find myself wanting to free
things. I’ve only just gotten over wanting to semi-colon every statement.

Probably by asking this i’m showing how i really haven’t groked ruby at
all. I’m happy to admit that.

Everything is being passed by reference, but the references themselves
are ‘hidden’, to enable GC.
data = File.read(‘ridiculously large file’)
some_object.some_method(data)

The data is not copied; some_method just receives a reference, and a
binding (the String object containing the data is bound to the name
‘data’).

Calling methods on ‘data’ implicitly dereferences it (this isn’t
really how it’s referred to in Ruby, but it seems to be how C people
like to think of it. heh.)

All you need to do to ‘free’ memory is keep your methods short. Local
variables will go out of scope, and be collected for you.

By the way… the “real things done with ruby” book is called ‘The Ruby
Way - 2nd Edition’, by Hal F… =)

Hi –

On Thu, 14 Dec 2006, Christopher Coleman-Smith wrote:

is very nice having all these things automated, like the garbage collection
etc, but i still find myself wanting to free things. I’ve only just gotten
over wanting to semi-colon every statement.

Basically, everything (or almost everything) is a reference:

a = [1,2,3] # a is assigned a reference to the array
b = a # b gets a copy of that reference
b.push(4) # the array now has four elements
p a # as you’ll see if you print it via any reference

When you pass objects around via variables, technically you’re passing
by value… but the “value” of the variable is a reference to an
object.

When you pass objects around via literals (like puts “hello”), a
reference to the literal is sent.

All of this means that if you do something to the arguments in a
method, the changes are permanent in the original object:

def add_element(array)
array.push(“new element!”)
end

a = [1,2,3]
add_element(a)
p a

So you’ll see a fair amount of "dup"ing going on in methods that want
to be safe.

There’s no reference-to-a-reference. It’s not like C pointers, which
can point to other pointers. Every Ruby reference is exactly one step
away from the object it refers to, and all references to an object are
equivalent to all other references to that object.

Some values are immediate; i.e., when you assign a variable to them,
they get stored directly and not via a reference: integers, true,
false, nil, and symbols (and any I’ve forgotten). Hence the “almost
everything” above.

David

  • instance variables belong to ‘self’, always
    these principles, and help me understand them.

If they’re not of practical value, then they’re not of value. So I’ll
give it a try :slight_smile:

Now I actually have the inverse problem. The good news is the code
works perfectly – thank you, by the way – but the bad news is I
don’t totally know why.

you want to do so inside a class definition body for the class where x
is defined (or a subclass of that class).

A “class method” is basically a singleton method of a Class object.
That means that the class where it’s defined is the singleton method
of that class object (because that’s what singleton classes are: the
places where objects’ singleton methods are defined).

Ah, ok. The class object creates a singleton, which is where all the
method definitions live?

In your case, the object in question is Thing. To get into a class
definition body for a singleton class, you use the class keyword plus
the “<< object” construct:

class << Thing

And this is because the class, having been defined, now has a
singleton containing all its methods, and we don’t want to create a
new patch, we just want to append new methods to the existing
singleton?

def self.x
end

Thing.x

I think I do get it, although I admit I’m still puzzled on the
singleton class / birth class thing.

  • instance variables belong to ‘self’, always
  • class variables are completely unrelated to instance variables,
    in spite of the use of @ in one and @@ in the other
  • the def and class keywords start new local scopes
  • the class keyword can take either a constant (for a named class)
    or a “<< object” expression (for a singleton class)

I have to admit, I don’t understand what this means in practical
terms. In fact I have a question I need to find an answer to, and I
want to post it in this thread, rather than as its own thing, in the
possibly idealistic hope that somebody can frame an answer in terms of
these principles, and help me understand them.

Basically, I need to change a class method. It’s the Ferret method
full_text_search, in a Rails app.

e.g.:

Thing.full_text_search(“asdf”)

I need to modify this class method. I tried alias, but did it wrong.

alias original_full_text_search full_text_search

but of course it doesn’t work, because it’s not an instance method but
a class method. Is this a good place for class_eval? I could be way
off.

Actually now that I re-read it, I think I do understand the basic
concepts, I think I’m just weak on the syntax.

Hi –

On Thu, 14 Dec 2006, Eero S. wrote:

a = [1,2,3]
add_element(a)
p a

Just to make it clearer: anything destructive or mutating you do to the
object inside the method will propagate to the original object.

And yet clearer: the object inside the method IS the original object
:slight_smile:

Some values are immediate; i.e., when you assign a variable to them,
they get stored directly and not via a reference: integers, true,
false, nil, and symbols (and any I’ve forgotten). Hence the “almost
everything” above.

I think this can just be considered to be an implementation detail,
frankly. Fixnums etc. just do not have any destructive methods that
one could employ inside a method.

The immediate-value thing does play a role in some language-design
things, though, particularly the absence of x++ on the grounds that
doing 1++ doesn’t make any sense and, given x = 1, x is 1.

David

On 2006.12.14 05:20, [email protected] wrote:

has worked i’ve not tried very hard.
a = [1,2,3] # a is assigned a reference to the array

All of this means that if you do something to the arguments in a
method, the changes are permanent in the original object:

def add_element(array)
array.push(“new element!”)
end

a = [1,2,3]
add_element(a)
p a

Just to make it clearer: anything destructive or mutating you do to the
object inside the method will propagate to the original object.

One perhaps surprising aspect of the ‘everything is a reference value’
style of argument passing is that assignment to the variable name will
simply have it point to a different object rather than modify the
original:

a = “Hello!”

def foo(string)
string = “Hello to you too!”
end

foo a
p a # => “Hello!”

false, nil, and symbols (and any I’ve forgotten). Hence the “almost
everything” above.

I think this can just be considered to be an implementation detail,
frankly. Fixnums etc. just do not have any destructive methods that
one could employ inside a method.

Hi –

On Thu, 14 Dec 2006, Giles B. wrote:

  • instance variables belong to ‘self’, always
    these principles, and help me understand them.

off.

A “class method” is basically a singleton method of a Class object.
That means that the class where it’s defined is the singleton method
of that class object (because that’s what singleton classes are: the
places where objects’ singleton methods are defined).

Ah, ok. The class object creates a singleton, which is where all the
method definitions live?

All the singleton method definitions of that class object, yes. It’s
really just a not-very-special case of the general principle that an
object’s singleton methods live in the object’s singleton class.

It’s perhaps easier to see the workings of it when the object isn’t a
class:

str = "I am a string
class << str
def just_for_me
puts “This method is just for me!”
end
end

I’ve defined a singleton method on the one String object, str. No
other string will have that method. If I’d defined it in String, they
would. But I’ve defined it in str’s singleton class (class << str),
so only str will have it:

str.just_for_me # This method is just for me!
“other”.just_for_me # NoMethodError

Now, watch as I take that example – and the explanation – and
substitute a Class object for the String object:

class Thing; end
class << Thing
def just_for_me
puts "This method is just for me!
end
end

I’ve defined a singleton method on the one Class object, Thing. No
other class will have that method. If I’d defined it in Class, they
would. But I’ve defined it in Thing’s singleton class (class <<
Thing), so only Thing will have it:

Thing.just_for_me # This method is just for me!
Array.just_for_me # NoMethodError

Note that in the Thing example, just_for_me is what we would call a
“class method”. A class method, then, is just a singleton method
defined for a class object.

In your case, the object in question is Thing. To get into a class
definition body for a singleton class, you use the class keyword plus
the “<< object” construct:

class << Thing

And this is because the class, having been defined, now has a
singleton containing all its methods, and we don’t want to create a
new patch, we just want to append new methods to the existing
singleton?

Yes, we want to define methods inside the singleton class of Thing.
The singleton class of Thing is not actually created until we ask to
get inside it, but that’s really an implementation detail.

I think I do get it, although I admit I’m still puzzled on the
singleton class / birth class thing.

It’s nature vs. nurture. Every object comes into existence with
certain capabilities – that is, when you send it messages, it
searches through specific classes and modules, in a specific order,
looking for corresponding methods. From that perspective, all
instances of a given class are the same as each other.

But you can also add capabilities to an object. An object that is
“born” ignorant of a certain message need not remain that way. You
can do this by adding to the object’s class – if you want all
instances of that class to have the new capability. Or, if you just
want one object to have it, you can add a method to that object’s
singleton class.

So by its nature, a String instance can do certain things:

str = “hello there”
str.split(/ll/)
str.upcase
str.reverse

etc. By way of nurture, we can add to this string by adding to all
strings:

class String
def new_method

end
end

or by adding a method to this one string’s singleton class, as in the
examples above.

(You can, by the way, also insert a method into an object’s singleton
class with the “def” keyword, like this:

def str.new_method

end

or

def Thing.some_class_method

end

.)

The main thing going on in all this is that Ruby objects can change
over the course of their lives. That’s the principle being enforced;
and singleton classes are just the way Matz has chosen to bring that
principle to life.

I get a lot of mileage out of thinking of the method look-up path.
When you send a message to an object, it walks the path – a
succession of classes and modules, like rooms strung along a corridor
– and looks for the method. First, it checks in its own singleton
class (if you’ve created one), and in any modules mixed in to the
singleton class. If no method with the right name is found, it
proceeds to its “birth” class, and then to the modules mixed in there.
And so on – until it gets to Object, and the module that’s mixed in
there (Kernel). Then, if it still hasn’t found the method, it gives
up.

This post could probably do with some more editing but I don’t have it
in me right now :slight_smile: I hope it’s helpful. You might also have a look
at a little essay that covers similar material:
http://www.wobblini.net/singletons.html. (And my book, of course :slight_smile:

David

This post could probably do with some more editing but I don’t have it
in me right now :slight_smile: I hope it’s helpful. You might also have a look
at a little essay that covers similar material:
http://www.wobblini.net/singletons.html. (And my book, of course :slight_smile:

Actually I might as well give you some free advertizing, I did in fact
check your book on this. I only just saw this e-mail today, missed it
somehow, but I was thinking about the question, so I re-read bits of
your book and it did actually clear some of this up for me.
Specifically the singleton/birth class thing.

Hi –

On Sat, 16 Dec 2006, Giles B. wrote:

This post could probably do with some more editing but I don’t have it
in me right now :slight_smile: I hope it’s helpful. You might also have a look
at a little essay that covers similar material:
http://www.wobblini.net/singletons.html. (And my book, of course :slight_smile:

Actually I might as well give you some free advertizing, I did in fact
check your book on this. I only just saw this e-mail today, missed it
somehow, but I was thinking about the question, so I re-read bits of
your book and it did actually clear some of this up for me.
Specifically the singleton/birth class thing.

Cool – on all counts: the advertising of course :slight_smile: but particularly
the fact that it’s coming clear for you.

David