Hi,
I have written a couple of small macros that does some text output and
needs to indent. It kind of looks like the following :-
(defmacro with-indent (&rest args)
`(combine
(indent+) ,@args (indent-)))
(defmacro gen-block (block-type block-name &rest args)
`(combine
(gen-begin block-type block-name)
(with-indent ,@args)
(gen-end block-type)))
; indent+/- just alter a variable which is indent level. gen-begin/end
make "begin/end blah" strings.
On the surface of it, this works fine. I can get gen-block to make
begin/end statements for home made scripting languages (which is what
this is for) by doing
(gen-block "block" "test block"
(print "first line") (print "second line"))
...and getting
block "test block"
print "first line"
print "second line"
end block
However, if I do
(gen-block "block" "outer block" (gen-block "block" "inner block")
(print "hello"))
I get
block "outer block"
block "inner block" ; Everything is okay so far.
print "hello"
end block ; Here is the problem.
end block
The indent level gets set and passed on to the next macro expansion
and I thought perhaps someone here might know of a way of getting the
desired result which would allow for unlimited nesting without mucking
up the trailing indents.
I'm wanting to use macros because I'll be transforming the statements
passed in.
Any ideas appreciated (would generating a closure with it's own level
around each block help?)
Cheers
DC
Hi, dc
I used to do something similar, and had a similar error.
I thing this is not related to macros. Anyway, you might use
(macroexpand-1 'your-code) too see the macroexpanded code.
It looks like a error in a logic. E.g., sometimes you're swapping
generation of indentation and generation of a newline (this was in my
case). It is very easy to err this way.
d> Any ideas appreciated (would generating a closure with it's own level
d> around each block help?)
i guess your problem is that you're using variable *indent* in your macros.
do not do that -- use it only at run time, and it will be fine.
it is not a case where you need macros calling macros -- macros can
just do syntatic conversion for you, but you can do all computatations (such
as computing indent amount)
at runtime with ordinary functions.
On Nov 4, 12:24 am, dc <··············@gmail.com> wrote:
> Hi,
>
> I have written a couple of small macros that does some text output and
> needs to indent. It kind of looks like the following :-
>
> (defmacro with-indent (&rest args)
> `(combine
> (indent+) ,@args (indent-)))
>
> (defmacro gen-block (block-type block-name &rest args)
> `(combine
> (gen-begin block-type block-name)
> (with-indent ,@args)
> (gen-end block-type)))
>
> ; indent+/- just alter a variable which is indent level. gen-begin/end
> make "begin/end blah" strings.
>
> On the surface of it, this works fine. I can get gen-block to make
> begin/end statements for home made scripting languages (which is what
> this is for) by doing
>
> (gen-block "block" "test block"
> (print "first line") (print "second line"))
>
> ...and getting
>
> block "test block"
> print "first line"
> print "second line"
> end block
>
> However, if I do
>
> (gen-block "block" "outer block" (gen-block "block" "inner block")
> (print "hello"))
>
> I get
>
> block "outer block"
> block "inner block" ; Everything is okay so far.
> print "hello"
> end block ; Here is the problem.
> end block
>
> The indent level gets set and passed on to the next macro expansion
> and I thought perhaps someone here might know of a way of getting the
> desired result which would allow for unlimited nesting without mucking
> up the trailing indents.
Macros aren't needed. A single function
does it all.
Ruby:
def gen_block type, name, *stuff
[ "#{type} \"#{name}\"",
stuff.flatten.map{|x| " #{x}"},
"end #{type}" ].flatten
end
puts gen_block("block", "outer block",'print "hello"')
puts gen_block("block", "outer block",
gen_block("block","inner block",'print "hello"'))
--- output ---
block "outer block"
print "hello"
end block
block "outer block"
block "inner block"
print "hello"
end block
end block
William James <·········@yahoo.com> writes:
> On Nov 4, 12:24�am, dc <··············@gmail.com> wrote:
>> Hi,
>>
>> I have written a couple of small macros that does some text output and
>> needs to indent. It kind of looks like the following :-
>>
>> (defmacro with-indent (&rest args)
>> � `(combine
>> � � �(indent+) ,@args (indent-)))
>>
>> (defmacro gen-block (block-type block-name &rest args)
>> � `(combine
>> � � � (gen-begin block-type block-name)
>> � � � (with-indent ,@args)
>> � � � (gen-end block-type)))
>>
>> ; indent+/- just alter a variable which is indent level. gen-begin/end
>> make "begin/end blah" strings.
>>
>> On the surface of it, this works fine. I can get gen-block to make
>> begin/end statements for home made scripting languages (which is what
>> this is for) by doing
>>
>> (gen-block "block" "test block"
>> � �(print "first line") (print "second line"))
>>
>> ...and getting
>>
>> block "test block"
>> � print "first line"
>> � print "second line"
>> end block
>>
>> However, if I do
>>
>> (gen-block "block" "outer block" (gen-block "block" "inner block")
>> (print "hello"))
>>
>> I get
>>
>> block "outer block"
>> � block "inner block" � � ; Everything is okay so far.
>> � � print "hello"
>> � � end block � � � � � � � �; Here is the problem.
>> end block
>>
>> The indent level gets set and passed on to the next macro expansion
>> and I thought perhaps someone here might know of a way of getting the
>> desired result which would allow for unlimited nesting without mucking
>> up the trailing indents.
>
> Macros aren't needed. A single function
> does it all.
>
> Ruby:
>
> def gen_block type, name, *stuff
> [ "#{type} \"#{name}\"",
> stuff.flatten.map{|x| " #{x}"},
> "end #{type}" ].flatten
> end
>
> puts gen_block("block", "outer block",'print "hello"')
>
> puts gen_block("block", "outer block",
> gen_block("block","inner block",'print "hello"'))
>
> --- output ---
> block "outer block"
> print "hello"
> end block
> block "outer block"
> block "inner block"
> print "hello"
> end block
> end block
Hey, Einstein... you may not have noticed, but this is
comp.lang.lisp, so posting Ruby code is not likely to help the OP.
On Tue, 04 Nov 2008 22:02:25 +0100, Raymond Wiker wrote:
>> block "inner block"
>> print "hello"
>> end block
>> end block
>
> Hey, Einstein... you may not have noticed, but this is
> comp.lang.lisp, so posting Ruby code is not likely to help the OP.
Hey Heisenberg,
Most of us figured out how to filter him and his ilk out using our
newsreaders, so we would not see a single post from them. But some
genius always has to reply to these idiots.
Tamas
Raymond Wiker wrote:
> Hey, Einstein... you may not have noticed, but this is
> comp.lang.lisp, so posting Ruby code is not likely to help the OP.
You assume that William James is trying to help people. You're not the first
person to tell him to stop with the ruby code in comp.lang.lisp
On 2008-11-04, William James <·········@yahoo.com> wrote:
> On Nov 4, 12:24�am, dc <··············@gmail.com> wrote:
>> (gen-block "block" "outer block" (gen-block "block" "inner block")
>> (print "hello"))
>>
>> I get
>>
>> block "outer block"
>> � block "inner block" � � ; Everything is okay so far.
>> � � print "hello"
>> � � end block � � � � � � � �; Here is the problem.
>> end block
>>
>> The indent level gets set and passed on to the next macro expansion
>> and I thought perhaps someone here might know of a way of getting the
>> desired result which would allow for unlimited nesting without mucking
>> up the trailing indents.
>
> Macros aren't needed. A single function
> does it all.
>
> Ruby:
>
> def gen_block type, name, *stuff
> [ "#{type} \"#{name}\"",
> stuff.flatten.map{|x| " #{x}"},
> "end #{type}" ].flatten
> end
>
> puts gen_block("block", "outer block",'print "hello"')
But the input to the Lisp macro is this code:
(gen-block "block" "outer block" (print "hello"))
This transliterates to Ruby like this:
gen_block("block", "outer block", print("hello"))
Part of the problem is to take syntax like print("hello") expression and
destructure it by pulling out the print and "hello" atoms. But in your Ruby,
you have cheated: you have 'print "hello"' as a string literal.
Can you make it work using the Ruby expression?
Here are two test cases:
expression:
gen_block("block", "outer block", print("hello"))
output:
block "block"
print "hello"
end block
expression:
gen_block("block", "outer block",
gen_block("foo", "inner", return("hello")))
output:
block "outer block"
foo "inner"
return "hello"
end foo
end block
Teach us, Ruby master.