Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

like EliAndrewC said, __getattr__ is Python's version of method_missing: http://docs.python.org/ref/attribute-access.html

And no, that's not all method_missing. looks like method_missing plus a block.



How do you catch and transform method arguments with __getattr__? For instance:

   mov ebx, [ebp+4]
needs to detect that ebx matches a Register class constant and that [ebp+4] is not an array, but rather a register indirection expression.


__getattr__ needs to return a callable (usually a function, but you can 'call' other objects as well). And that callable will be called with the arguments to the method.

You can do all that stuff with python, though the syntax isn't as loose; you can't omit the () around method calls which is what I think you're doing here in Ruby. That restriction tends to improve readability and reduce bugs at the cost of making it harder to have a truly transparent DSL.


The parens thing is unfair; obviously, without parsing strings (avoiding which is the whole point of metaprogramming), you can't express assembly in Python.

But isn't it surprisingly annoying to do method_missing in Python? Again, you have to catch the exception case to the symbol table lookup, and cons up a callable that knows to catch the arguments the right way.

Here's the entire method_missing call I needed to make x86 work inside a Ruby block:

        def method_missing(meth, *args)
            k = Rasm.const_get(meth.to_s.capitalize)

            # If it's a class, it's an assembly opcode;                 
            # else it's a register or operand.
            if k.class == Class
                @insns << (k = k.new(*args))
            else
                k
            end
            return k
        end


Well, Python has the * args and * *kwargs thing too. So "knows how to catch the arguments the right way" isn't any more of a problem than it is in Ruby. I'm guessing you don't know much about Python; you keep saying "It must be hard not to be able to do X" when in fact you CAN do X.

No, it's not surprisingly annoying. You can override just about anything within the rules of the Python syntax. You can override what << and + and | all do. You can override [] and ().

You just have to live within the Python syntax, which unfortunately for DSLs is stricter than Ruby syntax. But when you're not doing DSLs, that stricter syntax is usually a good thing.


Instead of saying it "...isn't any more of a problem than it is in Ruby" and "I'm guessing you don't know much about Python", why don't you actually show us some Python code which does something similar? I know Ruby well but Python only rudimentarily, so I'm curious what the rough equivalent would look like. If you don't feel like doing that, fine, but I'm just going to ignore your arguments.


His example is too incomplete to translate properly (since I don't know the details of other stuff he's referencing), but the basic idea is this:

A callable object in Python (e.g., a function or method, though not necessarily limited to these) can take advantage of two special options in declaring its argument signature. One is a feature shared between Python and Ruby: you can prefix the final argument with a single asterisk, which will be interpreted as "accept any number of additional positional arguments, and store them as a list in a variable of this name".

So, for example:

    def print_args(*args):
        for arg in args:
            print arg
Which does pretty much what it looks like it should do; you pass any number of arguments, and it echoes them back, each argument printed on a separate line.

The other part is something Ruby doesn't really support, because Ruby doesn't have a true analogue of Python's keyword arguments: using a double asterisk says, essentially, "accept any number of keyword arguments, and store them as a key/value mapping in a variable of this name".

So, for example:

    def print_keyword_args(**kwargs):
        for key, value in kwargs.items():
            print "%s: %s" % (key, value)
If you then did, say, `print_keyword_args(name='Bob', email='bob@example.com')`, you'd get back the output (ordering of items may vary with the Python implementation, but usually you're not concerned with ordering -- that's what positional arguments are for):

    name: Bob
    email: bob@example.com
These can also be combined into a standard idiom for a callable which accepts any combination of any number of named and keyword arguments:

    def takes_any_arguments(*args, **kwargs):
        ...
These sorts of idioms are incredibly useful for dynamic programming; for example, I work with (and help develop) the Django web framework, and our object-relational mapper uses the `kwargs` idiom to set up query methods which dynamically adapt the arguments they accept to the particular data model you're querying against.


> That restriction tends to improve readability and reduce bugs at the cost of making it harder to have a truly transparent DSL.

I used to think this too. But, then I actually learned ruby, and it turns out to be pretty easy to discern method calls from local variables, unless you are working with horridly long methods, which is a separate issue.

Remember that an instance variable is prefixed with @ in ruby, so if you see something that looks like it could either be a method call or a reference to a local variable, it's pretty easy to quickly examine the local scope to check. It's usually so obvious that you don't need to, though.

There are definitely some potentially tricky situations (closures, etc), but in over a year of working with ruby full time, I have yet to encounter one.


  fun1 x

  fun1 x + y

  fun1 x + y.foo

  fun1 x + y.foo bar
What will happen in this perfectly valid Ruby code? Where do the parentheses belong? Do you know off the top of your head?

While any programmer who would write this deserves to be fired, I can't come up with a good reason why it should be valid to write it in the first place.


Yes, I do know where the parentheses belong. Like I said earlier, it isn't hard to read ruby like this once you get used to reading ruby.

> While any programmer who would write this deserves to be fired...

That's exactly my point. The only example you could come up with was a straw man.

> ...I can't come up with a good reason why it should be valid to write it in the first place.

Can you come up with a good reason it matters in practical, real world situations?


Looks contrived, because I dont know many ruby users who would write fun1 for a method. Why? Because in ruby there are methods. You dont find many people doing "fun" for a method - the intent clearly was a "function". But where are they? ;)

Anyway, here is the one that comes to my brain flow naturally. It seems python writers need () in order to feel happy, otherwise they think they get confused about things (hopefully they dont have a small brain):

  fun1 x

  fun1 x + y

  fun1 x + y.foo

  fun1 x + y.foo bar
What will happen in this perfectly valid Ruby code? Where do the parentheses belong? Do you know off the top of your head?

fun1(x) fun1(x + y) fun1(x + y.foo()) fun1(x + y.foo(bar))

Btw you omitted what x and y are. My first assumption is that these must be variables that allow the + method

It does not really make a lot of sense though, give the last example:

class Cat def initialize(name) @name = name end def foo(how = :h) case how when :h how = 'happily' when :u how = 'unhappily' end puts @name+' meows '+how+'.' end end

y = Cat.new 'Tom'

y.foo # "Tom meows happily." bar = :u y.foo bar # "Tom meows unhappily."

x = '"At the end of the day "

x + y.foo bar # "At the end of the day Tom meows unhappily."

etc.. I simply have no idea what fun1 should do. Maybe it will involve Jerry mouse and return a conditional story where it is explained why Tom the cat is unhappy.

Btw this is a really contrived example because I tried to model your stipulation of the above code into this. It really makes no sense at all to use variables without any real idea why one should use that.

Why do people WANT to be complex when simplicity is so much more elegant?


This comment field is not very good, it killed my newlines! :(

I demand the pre tag or a "code" tag or something that allows us to add code nicely formatted :P


Anything indented two spaces acts like it's inside pre tags.

  Like this.
  And This.
  Etc.




Consider applying for YC's Fall 2026 batch! Applications are open till July 27.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: