Page 1 of 1

[Ruby] aliasing a method name without copying the method?

PostPosted: Sat Oct 03, 2020 12:05 am
by tulamide
Is it possible?

Code: Select all
def foo
  bar
end
alias_method :foo, :tulamide

This will create a copy, so I now have foo and tulamide.

Of course I can do
Code: Select all
def foo
  bar
end
def tulamide
  foo
end


But what I'm really looking for is a way to call foo directly using a different name. Any chance?

Re: [Ruby] aliasing a method name without copying the method

PostPosted: Sat Oct 03, 2020 2:59 pm
by trogluddite
No, you can't make an alias which points to the same UnboundMethod ("method definition") object. In fact, all attempts to manipulate a method definition will result in a copy being made - for example, the below code will display two different object IDs for two unique UnboundMethod objects...
Code: Select all
watch "test1", RubyEdit.instance_method(:watch).__id__
watch "test2", RubyEdit.instance_method(:watch).__id__

...so there's no chance of a sneaky workaround by using "define_method" or other meta-programming tricks.


So, either you have to suffer the copy or, if you need the alias to reflect changes to the original, some kind of forwarding (your 2nd example being the simplest and most direct form of that).

Re: [Ruby] aliasing a method name without copying the method

PostPosted: Sat Oct 03, 2020 9:58 pm
by tulamide
Thanks Trog, for the confirmation.

This topic is something that is a bit annoying about Ruby. When I use something called "alias" I don't expect it to actually copy it. And the other way around: When you DO want to copy (a class), you have to be careful, because although the two methods are called dup and clone, one of them doesn't actually make a full copy, but more of a template copy.

Very unintuitive.

Re: [Ruby] aliasing a method name without copying the method

PostPosted: Sun Oct 04, 2020 12:55 am
by trogluddite
tulamide wrote:Very unintuitive.

It sure is! It's one of the bits of Ruby that most often catches me out (especially when objects are nested).

Even once the usual Ruby rules for copying are understood, there's another issue - many Ruby add-ons, including FlowStone's custom classes, don't obey the rules anyway!!

The base "Object" class has default definitions for "dup" and "clone" which work fine for most user-defined classes. But these assume that all of an object's state is stored in Ruby objects assigned to instance variables, and that's not the case for "C-extension" objects which encapsulate non-Ruby data - such as, for example, handles to GDI+ objects!

To see what I mean, try "dupping" or "cloning" some Ruby GUI objects (e.g. Brushes, Pens, GraphicsPaths etc.). The copying methods themselves won't complain, but when you try to use the returned copies, they either don't work or will crash FlowStone (on v3.0.6 at least - I should test this in the Alphas!).

To be fair, I don't recall anyone else complaining that they've run into this problem. However, all FS custom classes are kind_of?(Object), and "dup" and "clone" are part of the interface of "Object" - so in OO terms, it's very naughty not to implement them properly! When copying is really not possible, raising a "NotImplementedError" is a valid, documented option - but returning a broken object which might later crash the interpreter is not!!

Re: [Ruby] aliasing a method name without copying the method

PostPosted: Sun Oct 04, 2020 6:58 am
by tulamide
trogluddite wrote:When copying is really not possible, raising a "NotImplementedError" is a valid, documented option - but returning a broken object which might later crash the interpreter is not!!

Indeed!
And both, dup and clone, are often not usable. You brought up a very dangerous example. A not dangerous, but annoying one is, when I needed to copy the nodes in the Spline class. Those are nested. I learned about dup and clone the hard way, and ended up programming my own copy method that creates a true deep copy by creating a new node class instance and then filling it by calling itself for each layer. A lot of work!

At least we can program our own workarounds.