From: Mat Schaffer Date: 2006-06-04T00:19:27+09:00 Subject: Re: Can you do Lisp-like macros in Ruby? On Jun 3, 2006, at 8:52 AM, Pat Maddox wrote: > I've never used lisp before until ~2am last night...and while working > on the very simple unit testing framework in Practical Common Lisp [1] > I came up with this macro: > > (defun report-result (result form) > (format t "~:[FAIL~;pass~] ... ~a~%" result form)) > > (defmacro test (test-form) > (let ((result (gensym))) > `(let ((,result ,test-form)) > (report-result ,result ',test-form) > ,result))) > > Using that macro, I can do: > CL-USER> (test (= (+ 1 2) 3)) > pass ... (= (+ 1 2) 3) > T > > I really like the syntax of that. How could I do the same thing in > Ruby? I took a quick shot and missed...it might be super easy and I'm > just dumb from this apparent insomnia. I really like using Ruby, but > I would absolutely love it if I could build syntax like I did with > Lisp. > > The Ruby translation of the syntax - not the code that actually makes > it work - would be like > > irb> test { (1 + 2) == 3 } > pass ... (1 + 2) == 3 > > Okay here's what I've come up with: > > def report_result(result, &block) > message = result ? "pass" : "FAIL" > puts "#{message} ... #{block}" > end > > def test(&block) > result = yield > report_result result, &block > result > end > > irb> test { (1 + 2) == 3 } > pass ... # > > So I guess the question is how to make the code show up. > > Here's my change: > > def report_result(result, code) > message = result ? "pass" : "FAIL" > puts "#{message} ... #{code}" > end > > def test(code) > result = eval code > report_result result, code > result > end > > irb> test "(1 + 2) == 3" > pass ... (1 + 2) == 3 > > I certainly don't like sticking my code in a string like that. That > just kind of sucks. > > Over all this is kind of a lame example anyway. Just after spending > some time with Lisp though, I get the feeling that I'll be able to do > some really cool stuff with it, stuff that I don't know how to do in > Ruby, despite using Ruby for several months now. I don't know exactly > what it is, but somehow I know that - at least with the Ruby coding > style I used above - I won't be able to do some things with Ruby that > I would be able to in Lisp. I appreciate any feedback...hopefully you > guys don't think I'm out in left field with this. > > Pat > > [1] http://www.gigamonkeys.com/book/ It seems like just giving a Proc a copy of the code used to create it would do this. There might even be a nice way to do it behind the scenes that wouldn't require actually storing a string. But I don't see any way to do this myself right now. Maybe some tricks with stack tracing? I do agree that Lisp has some neat tricks, but it made my eyes hurt trying to figure out where all the parens in that code started and stopped.... -Mat