Tuesday, August 15, 2006

Thoughts on Erlang Metaprogramming with Smerl

Writing Smerl was a great exercise, because it let me delve deep into the Erlang language. Now I realize how much power lies in Erlang's simple design: in Erlang, a module is just a list of functions. No types. No classes. No interfaces. No nonsense.



Just functions.



Why is this so great? Didn't we learn in college that "real" languages have classes, vtables, instance variables, abstract methods, inheritance information, static variables, static methods, etc, etc?



Nope, they do not.



Just like Lisp, Erlang is great because Erlang is simple.



In fact, Erlang and Lisp are quite similar. They are both functional, dynamically typed languages, and if you think of Erlang tuples as non-mutable lists, you'd realize that just like Lisp, Erlang is mostly about list manipulation.



Update (8/16/06): it's been brought to my attention that I made a mistake by saying that Lisp is a pure functional language because Lisp has mutable values. It's been a while since I've used Lisp so I deserve pardon :)



However, Erlang is a better language than Lisp IMO because Erlang is designed for concurrent and distributed programming -- key component of many non-trivial pieces of software -- whereas Lisp is not.



To highlighting Erlang's simplicity, with Smerl, which took me a few hours to write, changing a module in runtime boils down to 4 basic functions: smerl:for_module, smerl:add_func, smerl:remove_func and smerl:compile.



That's it.



Heck, Smerl can even modify itself, and it only takes 3 lines:




{ok, C1} = smerl:for_module(smerl),
{ok, C2} = smerl:add_func(C1, "foo() -> 1+1."),
smerl:compile(C2).


You could easily write a function that reduces the above example to 1 line:




add_func_to_module(Module, Func) ->
{ok, C1} = smerl:for_module(Module),
{ok, C2} = smerl:add_func(C1, Func),
smerl:compile(C2).


So the example would be written as:




add_func_to_module(smerl, "foo()-> 1+1.")


Pretty cool, huh?



Compare Smerl with this ominous list of libraries for Java bytecode manipulation, none of which comes close Smerl's power. (For a real trip, read this manual for BCEL -- Byte Code Engineering Library. You wouldn't know whether to laugh or cry.) Why? Because a) the Java compiler doesn't let you get away with using things that don't exist in compile time and b) Java is much more complex than Erlang, so using those libraries generally requires some serious mental gymnastics.



Ok, I know Java is an easy target to pick on, but I think that Smerl makes runtime metaprogramming in Erlang even easier than in Ruby.



So what's the conclusion? Smerl is just one more reason to love Erlang! :)

6 comments:

Tieying Liu said...

this is very exciting but considered harmful without proper regulations. I would love to see a set of user friendly conventions developed in erl. It would be great to start something like rails framework with starting project structure and configuration files.

Yariv said...

If used irresponsibly, yes it could be harmful. However, Smerl doesn't make any system less secure -- it only makes runtime metaprogramming easy.

Such a framework is already brewing :)

Damir said...

I don't think Lisp is purely functional. You can modify symbol (variable) after it's been bound.

Are you pushing Smerl into "lisp macros alike"? ;-)

Yariv said...

Hi Damir, yeah I think you're right about Lisp not being purely functional. And no, Smerl isn't like Lisp macros because Smerl is purely for runtime metaprogramming, whereas Lisp macros are compile-time.

Cobo said...

Sorry if this has already been told thousands of times, but I'm studying exams and my mind may have missed it... Is there any information about that "similar to Ruby On Rails" framework?

I'm not an Erlangish yet (till I finish my exams), but this is one of the things I am most willingly to see.

Thanks for all your posts and great job, Yariv. I hope I'll soon benefit from it :).

Cheers!

Yariv said...

Cobo, right now the closest thing to Rails for Erlang is Yaws. However, Yaws does lack some components that Rails has. I know of some people -- including myself -- who are working to close that gap. Keep reading this blog and you'll hear more about it.