coatl / rubymacros

RubyMacros is a lisp-like macro pre-processor for Ruby. More than just a purely textual substitution scheme, RubyMacros can manipulate and morph Ruby parse trees (in the form of RedParse Nodes) at parse time in just about any way you see fit.
http://rubyforge.org/projects/rubymacros
GNU Lesser General Public License v2.1
61 stars 2 forks source link

LINQ for Ruby? #1

Open trans opened 14 years ago

trans commented 14 years ago

Hey, I just had an interesting idea today. I wonder if RubyMacros could be used to create a LINQ like syntax set for Ruby. One could handle embedded XML/HTML, another perhaps for SQL. eg.

class Foo < Controller
  def index
    <html>
    <body>
      <h1>XML in Ruby Coolness!</h1>
    </body>
    </html>
  end
end

That would be way cool. Maybe even a "killer app" for RubyMacros.

coatl commented 14 years ago

I might have heard of linq before, but I must confess that I've never paid it any attention. My first reaction to the snippet you post above is that it would take a lot of lexer hackery to make it work. Maybe if I had the equivalent of lisp's read macros (==lexer time macros) it could be done. (What are the semantics you expect of that snippet, anyway? What would be the equivalent in normal ruby code?)

So, I've taken 5 minutes to try to understand linq, which, given its complexity, is not enough for me to really get it. The wikipedia page ( http://en.wikipedia.org/wiki/Language_Integrated_Query ) was sorta helpful. I think the SQL-like queries in plain ruby might be more approachable.... perhaps not using exactly that syntax (specifically, 'in' is a keyword, making it hard to work with, but otherwise it might be done).

I'm looking at the first example on that wp page, about halfway down. In ruby I would write it like this, using Reg pattern matchers.

someValue = 5 results = SomeCollection.grep(-{:SomeProperty=>0...someValue*2}).map{|x| [x.SomeProperty, x.OtherProperty] }

for result in results puts result end

Normal ruby, no syntax extensions or macros needed. And, it's shorter and sweeter than the C# original, even with special extensions. On the other hand, this will only query normal ruby objects; it won't magically turn itself into sql for you, as linq appears(?) to do.

I think this is a good idea, but I need a better definition of the problem to be solved before I can understand if/how it might be implemented. If you can provide some examples of what you want the syntax to be and what the equivalents in normal ruby are, that would help me.

This seems very similar to the loop macro in common lisp, which is something I've long wanted to understand well enough to be able to implement. (See http://www.unixuser.org/~euske/doc/cl/loop.html if you're not familiar...)

coatl commented 14 years ago

urk, formatting of that example was messed up. lemme try again:

someValue = 5 results = SomeCollection.grep(-{:SomeProperty=>0...someValue*2}).map{|x|

       [x.SomeProperty, x.OtherProperty]

}

for result in results puts result end

coatl commented 14 years ago

bleah, still snafu. I think you get the idea, tho.

ghost commented 14 years ago

Sorry, I made a mistake. I'm confusing two different things. LINQ is the query syntax, but I meant XML Literals ( http://msdn.microsoft.com/en-us/library/bb384629.aspx ).

btw, did you know that you can "edit" github comments ;-)

coatl commented 14 years ago

To do that properly would require a full-on xml parser. There's an added ambiguity over whether < is the start of an xml tag or the less-than operator, but that can be dealt with easily enough in the usual way. And xml is considerably easier to parse than, say, ruby. (This is really a rubylexer thang, not anything to do with rubymacros per se. But who cares.) I'm really not sure what to do about the xml escape thingies (the <%=....%> constructs.... whatever the right name for those is). That probably makes it all 5x as complicated. With luck, maybe I could call out to an existing xml parser... I'd have to ponder that.

OTOH, I could probably whip up something quick and dirty which finds the end of the xml based on indentation. That would mean that everything inside the xml fragment has to be indented more than the initial tag. Depending on what you want this for, that may or may not be useful.

I see the edit link in the comment header, now that you mention it. I guess that would have worked....