From: nolan_d@... (Nolan J. Darilek) Date: 2003-09-28T09:30:15+09:00 Subject: Thoughts on yield I've begun working on a music-related ruby project, and recently I've been pondering the idea of a music composition environment somewhat similar to cm, clm and friends for lisp, but in ruby instead. Today I was thinking about how ruby blocks make constructing domain-specific languages a snap. I've been reading Lisp as a Second Language at http://www.ircam.fr/equipes/repmus/LispSecondLanguage/, a Lisp tutorial for musicians, and was considering using a list-based structure for storing music. I sorta envisioned the language as looking something like: clef do measure("4/4") do c d e f g a b c chord do c e g end end end In this example, a-g are methods returning note objects. What I'd like is to have that return a list like so: ["c", "d", "e", "f", "g", "a", "b", "c", ["c", "e", "g"]] But, as it stands, each expression is evaluated and discarded. I'd like to avoid having to include actual lists in the blocks; while arbitrary ruby expressions would be possible, I'm aiming to hide much of that from the casual user. So, my question. Is there any way to achieve something like that using blocks? Is there any way to have yield do something other than run the given code? Assuming not, I was wondering how practical/horrible it would be to have yield accept an optional block which, when given one parameter, sets that parameter to the value of every top-level expression run within the block? So, for instance, if I wanted to evaluate all of the above expressions and concatenate their results into a list, I could do: score = [] yield { |x| score += [x] } Of course, I realize that probably breaks the principle of least surprise in a few instances, as many would expect the contents of a block to be executed and only the result of all code returned, but in my rather humble and untrained opinion, this would be useful for implementing domain-specific languages. Or is there a better way to accomplish what I'm trying?