Is it possible to traverse and modify the statements inside a Proc
after it has been created?
I'm playing with a small DSL for HTML, which should look like this.
html {
head { title {"Hello World"} }
body {
h1 { "hello"}
p {
"text body"
"more text"
}
}
}
If it is possible to recursively traverse through the statements in
each block, I could join the lines together with the + operator, and
the implementation would be fairly easy - just recursive calls that
return text. But it does not look like this is possible...
An alternative would be to create a new object for each node in the
HTML (eg body or h1), and let each method call inside this node assign
its content to an array there. Less functional style and more
overhead, but doable. But this requires either that I catch the
creation of new strings (no idea if that is possible) for them to be
added to the node as well, or that I introduce a new method to create
strings.
Any comments highly appreciated!
cheers,
Siemen
Generally - no. A proc is compiled code, it doesn't remember its own source
code. There are libraries that provide some deeper introspection tools -- like
the ParseTree / Ruby2Ruby libraries. Also, there are several DSLs very simllar
to what you're talking about already -- check out Markaby:
On Sun, Nov 15, 2009 at 6:32 PM, Kyle <kc...@yahoo.com> wrote:
> Generally - no. A proc is compiled code, it doesn't remember its own source
> code. There are libraries that provide some deeper introspection tools --
> like
> the ParseTree / Ruby2Ruby libraries. Also, there are several DSLs very
> simllar
> to what you're talking about already -- check out Markaby:
>
> http://markaby.rubyforge.org/
>
>
Thanks! The two introspection libs look really interesting.
I know that there are plenty of templating tools available. But I'm just
playing around with DSLs and chose HTML because it is such a well-known
domain with familiar problems.
For this little exercise, I'll go with the solution with the extra method
for text and objects for each node that I sketched because it has no
external dependencies..
cheers,
Siemen
> Generally - no. A proc is compiled code, it doesn't remember its own source
> code. There are libraries that provide some deeper introspection tools -- like
> the ParseTree / Ruby2Ruby libraries. Also, there are several DSLs very simllar
> to what you're talking about already -- check out Markaby:
>
> http://markaby.rubyforge.org/
agreed... except don't look at markaby. It is overly complicated and overly clevar (and slow as a result). Look at Ara's tagz. Excellent implementation.
Markaby is also Ruby 1.8 only, though I can't figure out why. Some of
the clevarness kind of fails to be portable.
Regards,
Florian
> Thanks! The two introspection libs look really interesting.
>
> I know that there are plenty of templating tools available. But I'm just
> playing around with DSLs and chose HTML because it is such a well-known
> domain with familiar problems.
The point wasn't (necessarily) to use them, but to study them. You simply don't need to traverse the proc to do what you want to do.
Example (one of several variants):
> class PseudoLisp
> def self.convert &b
> self.new.instance_eval(&b)
> end
>
> def method_missing(msg, *args, &b)
> if args.empty? then
> puts "(#{msg})"
> else
> puts "(#{msg} #{args.join(' ')})"
> end
> end
> end
>
> PseudoLisp.convert do
> happy
> sad 42
> end
#=> (happy)
#=> (sad 42)
On Mon, Nov 16, 2009 at 1:50 AM, Ryan Davis <ryand...@zenspider.com>wrote:
>
> On Nov 15, 2009, at 12:01 , Siemen Baader wrote:
>
> > Thanks! The two introspection libs look really interesting.
> >
> > I know that there are plenty of templating tools available. But I'm just
> > playing around with DSLs and chose HTML because it is such a well-known
> > domain with familiar problems.
>
> The point wasn't (necessarily) to use them, but to study them. You simply
> don't need to traverse the proc to do what you want to do.
>
Yes, I will definitely have a look at them!
> class PseudoLisp
> def self.convert &b
> self.new.instance_eval(&b)
> end
>
> def method_missing(msg, *args, &b)
> if args.empty? then
> puts "(#{msg})"
> else
> puts "(#{msg} #{args.join(' ')})"
> end
> end
> end
>
> PseudoLisp.convert do
> happy
> "string created"
> sad 42
> end
#=> (happy)
#=> (sad 42)
Thanks a lot for the example!
There is one caveat with it - I also need to catch the creation of strings.
Of course I can work around this by using a method call to construct text
(eg text "text body"). Hm.. maybe I can also hook into something with
ObjectSpace or String.new; I have to check that out when I come back to my
dev machine...
-- Siemen
>
PS. It looks like I'm always double posting for some reason, my apologies,
List.. I'll hope it is fixed now..
Are you posting form Google mail? For some reason that I don't
understand, my posts always look double posted to me, but are only
actually posted the once.
--
Paul Smith
http://www.nomadicfun.co.uk
Two string literals on the same line are concatenated - so in the above
example you could get away with a simple pre-processor that joins the
lines together in the right places.
>> "foo" "bar"
=> "foobar"
>>
However this won't work for
str1
str2
If this is what you want - i.e. each expression appearing on a line of
its own has its value sent to the output string - then probably native
Ruby is not the right tool. HAML, ERB and Cucumber are examples of DSLs
where a non-Ruby syntax fits better.
--
Posted via http://www.ruby-forum.com/.
On Mon, Nov 16, 2009 at 1:19 PM, Paul Smith <pa...@pollyandpaul.co.uk> wrote:
> >
>
> Are you posting form Google mail? For some reason that I don't
> understand, my posts always look double posted to me, but are only
> actually posted the once.
>
Yes I am, and it still looks like they are double-posted. Yours do not to
me. Sounds reasonable, there is probably something weird going on with its
conversation view algorithm..
Yes. Again, this is more an exercise to see what can be done with an inline
DSL, so I'll just stick with what I got.
It would have been quite easy with Lisp though, as I would have access to
each line and join them .. But apart from that, I'm not fluent with Lisp :)