From: pjb@... (Pascal J. Bourguignon) Date: 2009-02-25T20:29:16+09:00 Subject: Re: Nexus Programming Language Tom writes: >> And Ruby does have ParseTree. > > BTW does ParseTree work with ruby 1.9? The last time I tried it > didn't. > > Anyway, ruby isn't really made for that kind of thing. If you look at > the example at their homepage, the :scope and :block node seem to be > superfluous when dealing with code as data, and something like > "[:call, [:lvar, :arg1], :==, [:array, [:lit, 0]]]" also seems more > complicate than it could be. I think it's a good start but it doesn't > really match lisp capabilities in this respect where there is no > structural difference between the code and the data that represents > that code. That syntax most people in this thread were mocking has its > advantages and if you're denying that, the difference to "those cl > advocates" is only a marginal one. > > Maybe you should rather ask if in ruby it is really necessary to > manipulate code as data the way it is necessary in lisp. With a few > exceptions, I have seldom felt a need for it whereas in lisp the use > of macros is something you do all the time. Auto-meta-programming is only part of the picture. Of course, when programming in Lisp, we use auto-meta-programming obliviously all the time, but there are also a lot of lisp programs written to implement DSL or to generate inferior languages. For these heterogenous meta- programming applications, Ruby can be used too. Here is for example how I generate C++ code from Ruby: (class MapType (def makeToStringExpression(fieldAccess , mandatory , inVector = false , encoding = nil) (if mandatory (e = fieldAccess) (ib = [["." , e , :begin]]) (ie = [["." , e , :end]]) else (e = [[ "." , fieldAccess , :getValuePtr]]) (ib = [["->" , e , :begin]]) (ie = [["->" , e , :end]]) end) (k = (@keyType . makeToStringExpression(["->" , :i , :first] , true , encoding))) (v = (@elementType . makeToStringExpression(["->" , :i , :second] , true , encoding))) (s = [:block , [:inline , "typedef " + (self . cxxPath) + " map_type;"] , (Cxx::Variable . new(:i , (Cxx::Type . new((self . cxxPath)+"::"+"const_iterator")) , ib)) , (Cxx::Variable . new(:e , (Cxx::Type . new((self . cxxPath)+"::"+"const_iterator")) , ie)) , [ "<<" , :s , " (map"] , [:for , [ nil , ["!=" , :i , :e],["post++",:i]] , [:block , ["<<", :s , " ("] , k , ["<<", :s , " . "] , v , ["<<", :s , ")"]]] , [ "<<" , :s , ")"]]) end) end) and how I would do it from Lisp: (defmethod make-to-string-expression ((self map-type) field-access mandatory &optional in-vector encoding) (let ((f (if mandatory field-access `(\. ,field-access get-value-ptr)))) `(block (typedef ,(cxx-path self) map-type) (variable (scope ,(cxx-path self) const-iterator) i (,(if mandatory '\. '->) ,f begin)) (variable (scope ,(cxx-path self) const-iterator) e (,(if mandatory '\. '->) ,f end)) (<< s "(map ") (for (nil (!= i e) (post++ i)) (block (<< s " (") ,(make-to-string-expression (key-type self) `(-> i first) t encoding) (<< s " . ") ,(make-to-string-expression (key-type self) `(-> i second) t encoding) (<< s ")"))) (<< s ")")))) (The generator written in Ruby cuts off the C++ syntax at the level of types and variable expressions, hence the inline and instanciations. In Lisp, since I could use auto-meta-programming I could easily and in less time implement the syntax for all the parts of C++, so there's no need to cross the language boundaries.) -- __Pascal Bourguignon__