Pattern matching and defining methods

4 views
Skip to first unread message

candlerb

unread,
Nov 24, 2010, 9:30:43 AM11/24/10
to Reia
I notice Reia nicely implements pattern matching on calls:

>> module Foo
.. def bar(:z)
.. "The answer is z".puts()
.. end
.. def bar(:y)
.. "Or is it y?".puts()
.. end
.. end
=> Foo
>> Foo.bar(:z)
The answer is z
=> "The answer is z"
>> Foo.bar(:y)
Or is it y?
=> "Or is it y?"

However, this doesn't work if you define bar(:z) first, then later
reopen the module and define bar(:y). In this case the whole bar
definition is replaced with just the bar(:y) one.

Why would it be useful to add definitions in this way? To start with,
you could implement String#parse variants just by defining
String#parse(:json) and String#parse(:reia) separately, instead of
having the dispatcher which currently exists in String:

def parse(format)
"#{format.to_s().capitalize()}Parser".to_module().parse(self)
end

However I can see a more general use.

Imagine that when you def method(args), this definition was put *in
front* of all the other definitions at that arity. This would allow
you to override a method with a more specific definition for
particular input patterns. But suppose there were also some way to
call the old method definition starting from the next point in the
chain, like 'super' for class inheritance. This would give you a way
to enhance any method with extra processing before or after - like
alias_method_chain but less ugly.

Anyway, that's just a random thought.

Regards, Brian.

P.S. Pattern matching also allows some type checking, if you know the
reia internals:

>> module Foo
.. def bar(s = (:reia_string,_))
.. "Hello #{s}".puts()
.. end
.. end
>> Foo.bar("x")
Hello x
>> Foo.bar(:x)
exception error: no function clause matching 'Foo':bar({x},nil)

Perhaps it would be useful to support this directly - I don't know
what it would look like though.
"def bar(s =~ String)" perhaps?

Tony Arcieri

unread,
Nov 25, 2010, 12:55:07 AM11/25/10
to re...@googlegroups.com
On Wed, Nov 24, 2010 at 7:30 AM, candlerb <b.ca...@pobox.com> wrote:
I notice Reia nicely implements pattern matching on calls:

>> module Foo
.. def bar(:z)
.. "The answer is z".puts()
.. end
.. def bar(:y)
.. "Or is it y?".puts()
.. end
.. end
=> Foo
>> Foo.bar(:z)
The answer is z
=> "The answer is z"
>> Foo.bar(:y)
Or is it y?
=> "Or is it y?"

However, this doesn't work if you define bar(:z) first, then later
reopen the module and define bar(:y).

This is by design. Reia doesn't support any mechanism for "reopening" modules at the present time. This is to better match Erlang code change semantics: redefining a class or a module with the same name as the old one will cause the old one to be unloaded and the new one loaded in its place.

At some point I'd like to add some metaprogramming facilities to alter loaded modules, how right off the bat this is how code change is going to work.
 
Imagine that when you def method(args), this definition was put *in
front* of all the other definitions at that arity. This would allow
you to override a method with a more specific definition for
particular input patterns. But suppose there were also some way to
call the old method definition starting from the next point in the
chain, like 'super' for class inheritance. This would give you a way
to enhance any method with extra processing before or after - like
alias_method_chain but less ugly.

I can add some pretty awesome metaprogramming tricks like this in the future, but I wouldn't recommend using anything that requires modifying an existing module for anything other than debugging. It would complicate Erlangy code change, which is definitely a feature I must support.

The problem with a lot of the metaprogramming tricks that Ruby provides or what you're suggesting here is that it's hard to make work in a concurrent environment. For that reason I'm trying to follow Erlang a bit more closely and implement as much metaprogramming as possible in the form of declarative parse transforms, rather than modifying live code.

--
Tony Arcieri
Medioh! A Kudelski Brand

candlerb

unread,
Nov 29, 2010, 9:20:08 AM11/29/10
to Reia
On Nov 25, 5:55 am, Tony Arcieri <tony.arci...@medioh.com> wrote:
> I can add some pretty awesome metaprogramming tricks like this in the
> future, but I wouldn't recommend using anything that requires modifying an
> existing module for anything other than debugging. It would complicate
> Erlangy code change, which is definitely a feature I must support.

OK, I understand that.

I guess Reia could keep its own set of definitions of the function,
then redefine the function as the new def followed by the old def(s).
But certainly I think it's right to keep as close to the Erlang way of
doing things as possible. I think it should be as easy as possible to
use reia as a dynamic 'glue' language on top of all the existing
Erlang libraries.

Regards,

Brian.

Phil Pirozhkov

unread,
Nov 29, 2010, 10:27:20 AM11/29/10
to re...@googlegroups.com
Hi

It all sound like a global scope monkey patching.
There's a healthy alternative to this in Ruby:
http://timeless.judofyr.net/refinements-in-ruby

I think Reia may adopt it when it codes to library growth
(and disable monkey patching for reasons other than loading
new code)

Phil


-----Original Message-----

> --
> You received this message because you are subscribed to the Google Groups "Reia" group.
> To post to this group, send email to re...@googlegroups.com.
> To unsubscribe from this group, send email to reia+uns...@googlegroups.com.
> For more options, visit this group at http://groups.google.com/group/reia?hl=en.
>

Tony Arcieri

unread,
Nov 29, 2010, 4:29:10 PM11/29/10
to re...@googlegroups.com
I was looking at refinements yesterday. I like the idea.
Reply all
Reply to author
Forward
0 new messages