How to know if a method is read-write or read-only

I’ve now come across a second usecase for knowing if a method is
read-write or read-only on it’s object’s state. Both cases boil-down to
having meta-method behave differently depending on the behavior of
method being delegated to, but the circumstances differ completely. To
give an example, the current case generates method wraps for any given
class, applying thread sycronization. If a method is read-only it’s
wraped in a Sync::SH, if read-write then Sync::Ex.

So I wonder, is there a way to determine this fact about a method?


I assume you mean methods that are property getters/setters, along the
lines of ‘’/‘’, and that read-write or
read-only refer to object properties like ‘name’?

There is no general way to determine whether a method updates object
state or not. (Unless you start parsing bytecodes or hook into the VM
parse tree, which is a somewhat larger project.)
You’ll have to rely on naming conventions, like “a method that takes
no arguments and has a name not ending with ‘=’ is a getter, a method
that takes one argument and has a name ending with ‘=’ is a setter”.

You can get the number of arguments from Method#arity, like
=> 0


Trans wrote:


Do you want to know if a method changes its object’s state? In that
case, you could duplicate the object, freeze the duplicate and try to
call the method. If an Exception is raised, then either the method has a
bug or it is state-changing.

class Object
def changes_state?(method)
return false
rescue TypeError
return true

“foo”.changes_state? :upcase => false
“foo”.changes_state? :upcase! => true

It would be nice if a special exception was thrown when attempting to
call a method on a frozen object, so that you could distinguish it from
the usual TypeErrors.

Note that this method isn’t very efficient, since it duplicates the
entire object on each invocation. If you were to check many methods on a
single object, you might want to keep the frozen duplicate in an
instance variable.


Thanks Daniel. That’s an interesting approach --probably the best
automatic way that can be done.

But I think for a practical approach I will have to create some sort of
annotation declaration and simply manually declare methods as read-only
vs. read-write. Not ideal, of course, but at least it will work