Re: Variable number of arguments in SVG functions

2008-10-23 Thread Alexander Burger
On Wed, Oct 22, 2008 at 05:52:14PM +0100, Tomas Hlavaty wrote:
> Well, I think this version has one important limitation: if Prg has a
> recursive call(s) to foo, the deeper foo won't see any values set by
> the foo above, or will it?

Yes, that's right. 'run' takes care to skip the corresponding frames,
because otherwise it would violate its own principle of undoing the
local bindings of 'foo'.

This has the drawback, of course, that you cannot bind things locally.
This tradeoff has to be decided individually. Take 'scl' in "lib.l"

   (de scl (*Scl . "Prg")
  (run "Prg") )

Here we *want* to bind '*Scl' locally, this is the sole purpose of this
function. So we do not supply an env spec to 'run'. And here it also
does not harm, as '@' is not influenced.


> So if I want to write recursive  function, I cannot use (run ... 1).
> 
> So far, I have this:
> 
> ()
> (de  "Lst"
>(let ("At" @
>  "Tag" (pop '"Lst"))

OK.

But I would not waste stack frame space to bind '@' (as it is bound by
the call to ' already).


For my taste, I would stick with the solution that is used, for example,
at the end of 'style' in "lib/xhtml.l":

  (and (up 2 @))
  (run "Prg") ) )

It uses 'and' to cause the 'set'ting of '@' as a side effect.


BUT: I just see that this is wrong! I cannot use 'and' here, as it will
not set the value of '@' if 'up' evaluates to NIL.

I changed this now to

  (case (up 2 @))
  (run "Prg") ) )

because 'case' will always set '@'.


So I would propose this construct, as a general recommendation to handle
such functions. What do you think?


> I don't think it could possibly work without me being esotheric:-)

Let's hope :-)

Cheers,
- Alex
-- 
UNSUBSCRIBE: mailto:[EMAIL PROTECTED]


Re: Variable number of arguments in SVG functions

2008-10-23 Thread Alexander Burger
On Wed, Oct 22, 2008 at 05:23:40PM +0100, Tomas Hlavaty wrote:
> 
> > The hard-to-explain thing is, that here (up @ 2) is needed:
> >
> >(de foo "Prg"
> >   (when (car "Prg")
> >  (run (let @ (up @ 2) (cdr "Prg"))) ) )
> 
> (up @ 2) is not right, it sets @ to 2 which makes the example
> (and 2 (foo T (+ 1 @ 3))) pass.   If you try (and 4 (foo T (+ 1 @ 3)))
> it will not return the right value.  That's detail anyway, I'm with you now.

Oops, right! This worked only by chance :-)

The correct syntax to access the second level would be: (up 2 @)

But still I was writing nonsense, as going up two levels is not what we
need here.


> There seems to be difference between (let @ (up @) ...) and
> (let (@ (up @)) ...):

Yes. (let @ (up @) ..) and (let (@ (up @)) ..) are the same (i.e. only
'@' is bound in that frame), but if there is another symbol bound, it is
different:

   (let (@ (up @)  Dummy 7)

This gives a stack frame

   +--+
   | Old value of '@' |
   +--+
   | '@'  |
   +--+
   | Old value of 'Dummy' |
   +--+
   | 'Dummy'  | <- Frame
   +--+

'up', 'eval' and 'run' look at the *first* symbol in the frame. If it is
'@', it assumes that it is the bindings of function arguments, otherwise
'let' etc.

Now, unfortunately, a 'let' with a single '@' will produce such a frame.


The is based on the assumption that it normally it makes no sense to
bind '@' locally, as this is a very volatile value, and bound in each
function invocation anyway.

Cheers,
- Alex
-- 
UNSUBSCRIBE: mailto:[EMAIL PROTECTED]


Re: Variable number of arguments in SVG functions

2008-10-22 Thread Tomas Hlavaty
Hi Alex and Jon,

>> Indenting is impossible to do well I think because the function does
>> not know what is going to happen in the body (the 'xml' function knows
>
> I think so, too. This is also the reason why the functions in
> "lib/xhtml.l" don't do any efforts to indent. And with this 
> function we go a little in the direction of HTML (as Jon also mentioned
> in his initial post).

So it is possible.  The file implementing  function is attached.
I might improve formatting/indenting in the original 'xml' function
later.

I welcome any comments on the code.

> Ah, I was not aware that this is also legal in XML.

I double checked and it is legal, see http://www.w3.org/TR/REC-xml/#syntax

   ...they MUST be escaped using either numeric character references
   or the strings "&" and "<" respectively. The right angle
   bracket...

* Usage of the attached code

The "top-level"  call can be:

( T => returns list suitable as input for 'xml' function
( NIL -3 T => writes to NIL (stdout) with 3 tabs indenting and xml decl
( "/tmp/a" 3 => writes to "/tmp/a" with 3 spaces indenting
( => writes to NIL (stdout) with no indenting

(and 4 ( NIL -3 T
   ( hoy id 123 class 'yes att "Xml" at @
  ( inner1)
  ( text id 123 dx (+ 3 4) dy (* 3 4)
 xx "you & me"
 yy ""
 (xmlPrin "No font & color arguments yet") )
  ( inner2 fun "abc"
 (xmlPrin "Hi 1 asfdlkasjhfdshad")
 ( line x 0 y 0 dx 100 dy 100
(xmlPrin "thick" @))
 (xmlPrin "Hi 2") )
  ( inner3
 ( inner3a
( inner3a1) ) )
  ( inner4 fun "abc") ) ) )

will print




No font & color 
arguments yet
Hi 1 asfdlkasjhfdshadthick4Hi 2








Thanks,

Tomas

(de "xmlL" "Lst"
   (let "Att" @
  (push '"Xml"
 (make
(link (pop '"Lst"))
(let "Att" (make
  (while (and "Lst" (atom (car "Lst")))
 (link (cons (pop '"Lst")
 (eval (pop '"Lst") 1))) ) )
   (let "Xml" NIL
  (let @ "At"
 (run "Lst") )
  (ifn "Xml"
 (when "Att"
(link "Att") )
 (link "Att")
 (chain (flip "Xml")) ) ) ) ) ) ) )

(de "xmlO" "Lst"
   (let ("Att" @
 "Tag" (pop '"Lst") )
  (when "Nl"
 (prinl)
 (when "Pre"
(prin "Pre") ))
  (prin "<" "Tag")
  (while (and "Lst" (atom (car "Lst")))
 (prin " " (pop '"Lst") "=\"")
 (escXml (eval (pop '"Lst") 1))
 (prin "\"") )
  (ifn "Lst"
 (prin "/>")
 (prin ">")
 (use "Nlx"
(let (@ "At"
  "Nl" "N"
  "Pre" (cons "Pre" "Nn"))
   (run "Lst")
   (setq "Nlx" "Nl") )
(when "Nlx"
   (prinl)
   (when "Pre"
  (prin "Pre") )) )
 (prin "") ) ) )

(de  "Lst"
   (let ("At" @
 "Out" (when (and "Lst" (atom (car "Lst")))
  (eval (pop '"Lst") 1) ))
  (if (=T "Out")
 (let ("Xml" NIL
"xmlL"
   xmlPrin '(@ (push '"Xml" (pass pack))) )
(let @ "At"
   (run "Lst") )
(car (flip "Xml")) )
 (let ("N" (when (and "Lst" (atom (car "Lst")))
(eval (pop '"Lst") 1) )
   "Decl" (when (and "Lst" (atom (car "Lst")))
 (eval (pop '"Lst") 1) )
   "Nn" NIL
   "Nl" NIL
   "Pre" NIL
"xmlO"
   xmlPrin '(@ (off "Nl") (mapc escXml (rest))) )
(when "N"
   (do (abs "N")
  (push '"Nn" (if (lt0 "N") "^I" " "))) )
(out "Out"
   (when "Decl"
  (xml? T) )
   (let @ "At"
  (run "Lst") ) ) ) ) ) )

(de escXml (X)
   (for C (chop X)
  (prin (case C
   ("\"" """)
   ("&" "&")
   ("<" "<")
   (">" ">")
   (T C) ) ) ) )


Re: Variable number of arguments in SVG functions

2008-10-22 Thread Tomas Hlavaty
> Up until now, the simplest (and recommended, I think) version was:
>
>(de foo Prg
>   (when (car Prg)
>  (run (cdr Prg) 1) ) )

Well, I think this version has one important limitation: if Prg has a
recursive call(s) to foo, the deeper foo won't see any values set by
the foo above, or will it?

: (de foo Prg
   (when (car Prg)
  (print Foo)
  (let Foo (pack Foo "%")
 (run (cdr Prg) 1) ) ) )
-> foo
: (foo T (foo T (foo T)) (foo T))
NILNILNILNIL-> NIL
: (de foo Prg
   (when (car Prg)
  (print Foo)
  (let Foo (pack Foo "%")
 (run (cdr Prg)) ) ) )
# foo redefined
-> foo
: (foo T (foo T (foo T)) (foo T))
NIL"%""%%""%"-> NIL
: (de foo "Prg"
   (when (car "Prg")
  (print "Foo")
  (let "Foo" (pack "Foo" "%")
 (run (cdr "Prg")) ) ) )
-> foo
: (foo T (foo T (foo T)) (foo T))
"Foo""Foo%""Foo%%""Foo%"-> NIL
: 

So if I want to write recursive  function, I cannot use (run ... 1).

So far, I have this:

()
(de  "Lst"
   (let ("At" @
 "Tag" (pop '"Lst"))
  (if "Tag"
 (queue '"Xml"
(make
   (link "Tag")
   (let "Att"
  (make
 (while (and "Lst" (atom (car "Lst")))
(link (cons (pop '"Lst") (eval (pop '"Lst") 1))) ) )
  (let "Xml" NIL
 (let @ "At"
(run "Lst") )
 (ifn "Xml"
(when "Att"
   (link "Att") )
(link "Att")
(chain "Xml") ) ) ) ) )
 (let ("Xml" NIL
   "Out" (when (and "Lst" (atom (car "Lst")))
  (eval (pop '"Lst") 1) )
   xmlPrin '(@ (queue '"Xml" (pass pack))) )
(let @ "At"
   (run "Lst") )
(if (=T "Out")
   (car "Xml")
   (out "Out"
  (xml (car "Xml")) ) ) ) ) ) )
()

This works well:

: (load '@lib/xml.l)
-> attr
: (and 4 ( NIL ( elt att @ (xmlPrin "hi"
hi
-> ">"
: 

I don't think it could possibly work without me being esotheric:-)

Thank you,

Tomas
-- 
UNSUBSCRIBE: mailto:[EMAIL PROTECTED]


Re: Variable number of arguments in SVG functions

2008-10-22 Thread Tomas Hlavaty
> For one thing, the quote in the call of 'up' is too much. But this
> is not the main problem.

Sorry, my mistake.

> The hard-to-explain thing is, that here (up @ 2) is needed:
>
>(de foo "Prg"
>   (when (car "Prg")
>  (run (let @ (up @ 2) (cdr "Prg"))) ) )

(up @ 2) is not right, it sets @ to 2 which makes the example
(and 2 (foo T (+ 1 @ 3))) pass.   If you try (and 4 (foo T (+ 1 @ 3)))
it will not return the right value.  That's detail anyway, I'm with you now.

> Basically you were right to access '@' one level up.
>
> But the implementation of 'up', 'eval' and 'run' is such that it looks
> for binding frames that have '@' bound as their first symbol. The reason
> is that we want to skip intermediate frames (with 'let', 'use', 'for'
> etc.). Usually, only the binding frame for functional arguments start
> with '@'. But you managed to create such a frame!
>
> You can verify this by testing
>
>(de foo "Prg"
>   (when (car "Prg")
>  (let (@ (up @)  Dummy 7)
> (run (cdr "Prg"))) ) )
>
> Now '@' is not the first bound symbol in the frame (when seen from the
> lower parts of the stack), but 'Dummy'. So (up @) works.

Uff, I see the trick.

There seems to be difference between (let @ (up @) ...) and
(let (@ (up @)) ...):

(de foo "Prg"
   (when (car "Prg")
  (let @ (up @)
 (run (cdr "Prg"))) ) )

: (and 4 (foo T (+ 1 @ 3)))
!? (+ 1 @ 3)
T -- Number expected
? 

(de foo "Prg"
   (when (car "Prg")
  (let (@ (up @))
 (run (cdr "Prg"))) ) )

: (and 4 (foo T (+ 1 @ 3)))
-> 8

..so I do not need Dummy.

Thanks for explanation.

Tomas
-- 
UNSUBSCRIBE: mailto:[EMAIL PROTECTED]


Re: Variable number of arguments in SVG functions

2008-10-22 Thread Alexander Burger
On Wed, Oct 22, 2008 at 04:47:36PM +0100, Tomas Hlavaty wrote:
> (de foo "Prg"
>(let "At" (up @)
>   (when (car "Prg")
>  (let @ "At"
> (run (cdr "Prg"))
> 
> : (and 2 (foo T (+ 1 @ 3)))
> -> 6

Yep. In that case, you can even omit the 'up', as '@' is not modified
yet. And the 'let's are not needed (just 'setq') because '@' will be
internally restored anyway when 'foo' terminates.

   (de foo "Prg"
  (setq "At" @)
  (when (car "Prg")
 (setq @ "At")
 (run (cdr "Prg")) ) )

But I think we are getting esotherical ;-)


Up until now, the simplest (and recommended, I think) version was:

   (de foo Prg
  (when (car Prg)
 (run (cdr Prg) 1) ) )

Cheers,
- Alex
-- 
UNSUBSCRIBE: mailto:[EMAIL PROTECTED]


Re: Variable number of arguments in SVG functions

2008-10-22 Thread Alexander Burger
On Wed, Oct 22, 2008 at 03:37:10PM +0100, Tomas Hlavaty wrote:
> (de foo "Prg"
>(when (car "Prg")
>   (run (let @ (up '@) (cdr "Prg")) ) ) )
> 
> Why this does not work?

Well, this is a hairy one ;-)


For one thing, the quote in the call of 'up' is too much. But this is
not the main problem.


The hard-to-explain thing is, that here (up @ 2) is needed:

   (de foo "Prg"
  (when (car "Prg")
 (run (let @ (up @ 2) (cdr "Prg"))) ) )

Basically you were right to access '@' one level up.

But the implementation of 'up', 'eval' and 'run' is such that it looks
for binding frames that have '@' bound as their first symbol. The reason
is that we want to skip intermediate frames (with 'let', 'use', 'for'
etc.). Usually, only the binding frame for functional arguments start
with '@'. But you managed to create such a frame!

You can verify this by testing

   (de foo "Prg"
  (when (car "Prg")
 (let (@ (up @)  Dummy 7)
(run (cdr "Prg"))) ) )

Now '@' is not the first bound symbol in the frame (when seen from the
lower parts of the stack), but 'Dummy'. So (up @) works.


Perhaps I should think of another mechanism in PicoLisp-3

Cheers,
- Alex
-- 
UNSUBSCRIBE: mailto:[EMAIL PROTECTED]


Re: Variable number of arguments in SVG functions

2008-10-22 Thread Tomas Hlavaty
> If you use transient symbols
>
>(de foo "Prg"
>   (when (car "Prg")
>  (run (cdr "Prg")) ) )
>
> then it basically works
>
>: (foo T (+ 1 2 3))
>-> 6
>: (foo NIL (+ 1 2 3))
>-> NIL
>
> BUT if you want to use '@'
>
>:  (and 2 (foo T (+ 1 @ 3)))
>!? (+ 1 @ 3)
>T -- Number expected
>?

This can be fixed:

(de foo "Prg"
   (let "At" (up @)
  (when (car "Prg")
 (let @ "At"
(run (cdr "Prg"))

: (and 2 (foo T (+ 1 @ 3)))
-> 6

Not sure why this does not work though:

(de foo "Prg"
   (when (car "Prg")
  (let @ (up @)
 (run (cdr "Prg")

: (and 2 (foo T (+ 1 @ 3)))
!? (+ 1 @ 3)
T -- Number expected
? 

even though:

(de foo "Prg"
   (when (car "Prg")
  (up @)))

: (and 2 (foo T (+ 1 @ 3)))
-> 2

works as I expect.

Cheers,

Tomas
-- 
UNSUBSCRIBE: mailto:[EMAIL PROTECTED]


Re: Variable number of arguments in SVG functions

2008-10-22 Thread Tomas Hlavaty
>> it would be possible to do indenting if the body prg was not run in
>> the parent environment.  Then we could pass some indenting state to
>> the recursive calls of  and indent accordingly.
>
> Should be possible. If we had
>
>(de  (Level . Lst)
>   (default Level 0)
>
> Then we could do
>
>   (spaces (* 3 Level))
>   (run Lst 1)
>
> I'm not sure. At least this is a basic idea ;-)

With this solution programmers would have to specify the Level
"manually":-(

Tomas
-- 
UNSUBSCRIBE: mailto:[EMAIL PROTECTED]


Re: Variable number of arguments in SVG functions

2008-10-22 Thread Tomas Hlavaty
> The disadvantage of gensym'd symbols is that the code is more difficult
> to understand when pretty printed, and cannot be written to some file
> and retrieved later.

True.

> The PicoLisp solution of transient symbols has an identical effect
> (especially if you surround the function definition(s) with ()).

I see!

> Though the usage of transient symbols (like gensym'd symbols) nicely
> protects from symbol capture, there is one nasty detail: Symbols that we
> *want* to be evaluated in the outer environment, most notably '@'.

Thanks for explanation.

Is @ the only problem?  How serious problem/inconvenience do you
consider it?

Would not it be possible somehow to rebind it again with some trick
along the lines of:

(de foo "Prg"
   (when (car "Prg")
  (run (let @ (up '@) (cdr "Prg")) ) ) )

Why this does not work?

Thank you,

Tomas
-- 
UNSUBSCRIBE: mailto:[EMAIL PROTECTED]


Re: Variable number of arguments in SVG functions

2008-10-22 Thread Alexander Burger
Hi Tomas,

> it would be possible to do indenting if the body prg was not run in
> the parent environment.  Then we could pass some indenting state to
> the recursive calls of  and indent accordingly.

Should be possible. If we had

   (de  (Level . Lst)
  (default Level 0)

Then we could do

  (spaces (* 3 Level))
  (run Lst 1)

I'm not sure. At least this is a basic idea ;-)


> Probably, I am not sure what the other escaping in ht:Prin does, is it
> just utf-8 related escaping?  I think it is better to output utf-8
> characters directly without escaping.

Yes, ht:Prin does not touch utf-8 chars. On the other hand, it is
probably a bit too much tailored for HTML, as it specifically ignores
certain tags like  or  (see the table at the beginning of
"src/ht.c") to allow markups in the text. Besides this, it only cares
about "<", ">", "&", "\"" and the Euro sign. Well, that's a little
ad-hoc :-(

Cheers,
- Alex
-- 
UNSUBSCRIBE: mailto:[EMAIL PROTECTED]


Re: Variable number of arguments in SVG functions

2008-10-22 Thread Tomas Hlavaty
Hi Alex,

>> Indenting is impossible to do well I think because the function does
>> not know what is going to happen in the body (the 'xml' function knows
>
> I think so, too. This is also the reason why the functions in
> "lib/xhtml.l" don't do any efforts to indent. And with this 
> function we go a little in the direction of HTML (as Jon also mentioned
> in his initial post).

it would be possible to do indenting if the body prg was not run in
the parent environment.  Then we could pass some indenting state to
the recursive calls of  and indent accordingly.

That's why I came with the w/gensym but if transient symbols do that
better, I'll try to use them.  I have to get my head around using them
first though:-)

> But then we don't need 'excXml' at all, and can simply use 'ht:Prin',
> don't we?

Probably, I am not sure what the other escaping in ht:Prin does, is it
just utf-8 related escaping?  I think it is better to output utf-8
characters directly without escaping.

Cheers,

Tomas
-- 
UNSUBSCRIBE: mailto:[EMAIL PROTECTED]


Re: Variable number of arguments in SVG functions

2008-10-22 Thread Alexander Burger
On Wed, Oct 22, 2008 at 01:22:50PM +0100, Tomas Hlavaty wrote:
> The trick with run/eval in parent environment is used quite often in
> picoLisp to avoid variable binding clashes.  I was wandering whether
> it would not be better sometimes to do something like Common Lispers
> do with gensyms which would avoid clashes by using fresh symbols:

The disadvantage of gensym'd symbols is that the code is more difficult
to understand when pretty printed, and cannot be written to some file
and retrieved later.

The PicoLisp solution of transient symbols has an identical effect
(especially if you surround the function definition(s) with ()).


Interesting is perhaps the reason why the environment argument to 'run'
and 'eval' was invented in the first place.

Though the usage of transient symbols (like gensym'd symbols) nicely
protects from symbol capture, there is one nasty detail: Symbols that we
*want* to be evaluated in the outer environment, most notably '@'.

If you use transient symbols

   (de foo "Prg"
  (when (car "Prg")
 (run (cdr "Prg")) ) )

then it basically works

   : (foo T (+ 1 2 3))
   -> 6
   : (foo NIL (+ 1 2 3))
   -> NIL

BUT if you want to use '@'

   :  (and 2 (foo T (+ 1 @ 3)))
   !? (+ 1 @ 3)
   T -- Number expected
   ?


Trying instead

   (de foo Prg
  (when (car Prg)
 (run (cdr Prg) 1) ) )

gives

   : (and 2 (foo T (+ 1 @ 3)))
   -> 6

voila!

Cheers,
- Alex
-- 
UNSUBSCRIBE: mailto:[EMAIL PROTECTED]


Re: Variable number of arguments in SVG functions

2008-10-22 Thread Alexander Burger
On Wed, Oct 22, 2008 at 10:43:32AM +0100, Tomas Hlavaty wrote:
> The body should be printed using ht:Prin to get good escaping.

Sorry, didn't read this before my previous post ...


> Actually, the more I think about it the less I like it.  It just
> introduces some questions with application specific answers only.
> Maybe it should not be in the picoLisp distribution after all?

Yes, that's the difficult point. And the reason why I thought you are
the right person to decide this, as you seem to have the greatest amount
of practical knowledge and experience with XML ;-)


> The only problem with this code is that the body is not run in the
> parent environment, which I don't know how to fix or what problems it
> could cause.

I think it should be ok, as long as '1' is passed to 'eval' and 'run'.
These evironment lookups will nest.


> Alex, is it more efficient to use push together with reverse or is
> queue fine?

This might depend on the length of the result. 'queue' has the advantage
that the result is ready at any time. Otherwise, I would either use
'make' and 'link', or perhaps 'fifo'?

Cheers,
- Alex
-- 
UNSUBSCRIBE: mailto:[EMAIL PROTECTED]


Re: Variable number of arguments in SVG functions

2008-10-22 Thread Alexander Burger
Hi Tomas,

thanks for the analysis!


> Indenting is impossible to do well I think because the function does
> not know what is going to happen in the body (the 'xml' function knows

I think so, too. This is also the reason why the functions in
"lib/xhtml.l" don't do any efforts to indent. And with this 
function we go a little in the direction of HTML (as Jon also mentioned
in his initial post).


> Also, I don't really like the output of 'escXml', it would be more
> human friendly to output & etc instead of numbers:
> 
> (de escXml (X)
>(for C (chop X)
>   (case C
>  ("\"" (prin """))
>  ("&" (prin "&"))
>  ("<" (prin "<"))
>  (">" (prin ">"))
>  (T (prin C)) ) ) )

Ah, I was not aware that this is also legal in XML.

But then we don't need 'excXml' at all, and can simply use 'ht:Prin',
don't we?

Cheers,
- Alex
-- 
UNSUBSCRIBE: mailto:[EMAIL PROTECTED]


Re: Variable number of arguments in SVG functions

2008-10-22 Thread Tomas Hlavaty
> The only problem with this code is that the body is not run in the
> parent environment, which I don't know how to fix or what problems it
> could cause.

The trick with run/eval in parent environment is used quite often in
picoLisp to avoid variable binding clashes.  I was wandering whether
it would not be better sometimes to do something like Common Lispers
do with gensyms which would avoid clashes by using fresh symbols:

(def 'w/gensym
   (let A (new)
  (fill '(A (bind (mapcar '((X) (cons X (new))) (car A))
   (fill (cdr A) (car A)) ) )
 'A) ) )

#(w/gensym (X) . X) => $519668770
#(w/gensym (X) . (+ X 1)) => (+ $519668786 1)
#(w/gensym (X) (+ X 1)) => ((+ $519669514 1))
#(w/gensym (A) (de plus Lst (+ A B))) => ((de plus Lst (+ $519735190 B)))

'w/gensym' is like 'fill' but it uses new symbols for replacement.

(de deu A
   (run
  (let (@N (pop 'A) @A (pop 'A) @S (pop 'A) @B A)
 (macro (w/gensym @S (de @N @A . @B))) ) ) )

#(deu plus Lst (A) (+ A B)) => (de plus Lst (+ $519735363 B) )
#(deu plus (A B) (A) (+ A B)) => (de plus ($519735405 B) (+ $519735405 B) )

'deu' is like 'de' accepting a list of symbols which are unique for
that function.

The only drawback is that using fresh symbols makes debugging harder.

The final  function could look like this:

(deu  Lst (Lst Tag Xml Att)
   (let Tag (pop 'Lst)
  (if Tag
 (queue 'Xml
(make
   (link Tag)
   (let Att
  (make
 (while (and Lst (atom (car Lst)))
(link (cons (pop 'Lst) (eval (pop 'Lst) 1))) ) )
  (let Xml NIL
 (run Lst)
 (ifn Xml
(when Att
   (link Att) )
(link Att)
(chain Xml) ) ) ) ) )
 (let (Xml NIL
   Out (when (and Lst (atom (car Lst)))
  (eval (pop 'Lst) 1) )
   xmlPrin '(@ (queue 'Xml (pass pack))) )
(run Lst)
(if (=T Out)
   (car Xml)
   (out Out
  (xml (car Xml)) ) ) ) ) ) )

and could be called as:

( NIL
   ( hoy id 123 class 'yes
  ( inner1)
  ( text id 123 dx (+ 3 4) dy (* 3 4)
 xx "you & me"
 yy ""
 (xmlPrin "No font & color arguments yet") )
  ( inner2 fun "abc"
 (xmlPrin "Hi 1 asfdlkasjhfdshad")
 ( line x 0 y 0 dx 100 dy 100
(xmlPrin "thick"))
 (xmlPrin "Hi 2") )
  ( inner3 fun "abc") ) )

( NIL "/tmp/aa"
   ( hoy id 123 class 'yes
  ...

( NIL T
   ( hoy id 123 class 'yes
  ...

Cheers,

Tomas
-- 
UNSUBSCRIBE: mailto:[EMAIL PROTECTED]


Re: Variable number of arguments in SVG functions

2008-10-22 Thread Tomas Hlavaty
The escXml function could be like this:

(de escXml (X)
   (for C (chop X)
  (prin (case C
   ("\"" """)
   ("&" "&")
   ("<" "<")
   (">" ">")
   (T C) ) ) ) )

> It is probably best to automatically escape attributes but leave the
> user to escape body (as attributes will be usually a value while body
> will come via prin or something).

The body should be printed using ht:Prin to get good escaping.

>>> Since this is "pure" XML, it would seem natural to find a function like 
>>> this  in lib/xml.l. I haven't studied the functions in that file 
>>
>> Tomas also suggested this. I think it is a good idea. I would like to

Actually, the more I think about it the less I like it.  It just
introduces some questions with application specific answers only.
Maybe it should not be in the picoLisp distribution after all?

Or, what about reusing the 'xml' function instead of duplicating it:

(de  Lst
   (let Tag (pop 'Lst)
  (if Tag
 (queue '*Xml
(make
   (link Tag)
   (let A
  (make
 (while (and Lst (atom (car Lst)))
(link (cons (pop 'Lst) (eval (pop 'Lst) 1))) ) )
  (let *Xml NIL
 (run Lst)
 (ifn *Xml
(when A
   (link A) )
(link A)
(chain *Xml) ) ) ) ) )
 (let *Xml NIL
(run Lst)
(xml (car *Xml) ) ) ) ) )
 
(de xmlPrin @
   (queue '*Xml (pass pack)) )

( NIL
   ( hoy id 123 class 'yes
  ( inner1)
  ( text id 123 dx (+ 3 4) dy (* 3 4)
 xx "you & me"
 yy ""
 (xmlPrin "No font & color arguments yet") )
  ( inner2 fun "abc"
 (xmlPrin "Hi 1 asfdlkasjhfdshad")
 ( line x 0 y 0 dx 100 dy 100
(xmlPrin "thick"))
 (xmlPrin "Hi 2") )
  ( inner3 fun "abc") ) )

The only problem with this code is that the body is not run in the
parent environment, which I don't know how to fix or what problems it
could cause.

Alex, is it more efficient to use push together with reverse or is
queue fine?

Thanks,

Tomas
-- 
UNSUBSCRIBE: mailto:[EMAIL PROTECTED]


Re: Variable number of arguments in SVG functions

2008-10-22 Thread Tomas Hlavaty
Hi Jon and Alex,

>> Since this is "pure" XML, it would seem natural to find a function like 
>> this  in lib/xml.l. I haven't studied the functions in that file 
>
> Tomas also suggested this. I think it is a good idea. I would like to
> let Tomas make the final decision and/or design.

I take it as punishment for suggesting that;-)

The function you have now looks good except two things:

- no escaping: it is up to the user to escape attribute and body text

- no indenting/formatting: it would be nice to have output formatted
  as the 'xml' function

I was thinking how to best fix these two things and came to the
following which is almost the same code as you have:

(de  Lst
   (let Tag (pop 'Lst)
  (prin "<" Tag)
  (while (and Lst (atom (car Lst)))
 (prin " " (pop 'Lst) "=\"")
 (escXml (eval (pop 'Lst) 1))
 (prin "\"") )
  (ifn Lst
 (prin "/>")
 (prin ">")
 (run Lst 1)
 (prin "") ) ) )

It is probably best to automatically escape attributes but leave the
user to escape body (as attributes will be usually a value while body
will come via prin or something).

Indenting is impossible to do well I think because the function does
not know what is going to happen in the body (the 'xml' function knows
that) and it is impossible to pass anything to the body as the body is
evaluated in the parent environment.

Not sure whether to remove prinl Jon had there, in general, an XML
schema could specify that white space in an XML element is significant
so the new line would not be desirable.  Probably depends how we plan
to use it.  For now I prefer it without prinl.

Here is a sample output:

: ( hoy id 123
   ( inner1)
   ( text id 123 dx (+ 3 4) dy (* 3 4)
  xx "you & me"
  yy ""
  (prin "No font and color arguments yet") )
   ( inner2 fun "abc"
  (prin "Hi 1 asfdlkasjhfdshad")
  ( line x 0 y 0 dx 100 dy 100
 (prin "thick"))
  (prin "Hi 2") )
   ( inner3 fun "abc") )
No font and color 
arguments yetHi 1 asfdlkasjhfdshadthickHi 2-> ">"

The CDATA in attribute does now work well but that is not an issue I
think.  It could be implemented using some kind of convention for
attributes, e.g. (T . "hi") => "" but that is overkill.

To get nicely formated XML, I would use xmllint:

: (let F (tmp "out.xml")
   (out F
  ( hoy id 123
 ( inner1)
 ( text id 123 dx (+ 3 4) dy (* 3 4)
xx "you & me"
yy ""
(prin "No font and color arguments yet") )
 ( inner2 fun "abc"
(prin "Hi 1 asfdlkasjhfdshad")
( line x 0 y 0 dx 100 dy 100
   (prin "thick"))
(prin "Hi 2") )
 ( inner3 fun "abc")) )
   (call "xmllint" "--format" F) )


  
  No font and color arguments yet
  Hi 1 asfdlkasjhfdshadthickHi 2
  

-> T

Or, use the superior 'xml' function to achieve nicely indented XML.

Also, I don't really like the output of 'escXml', it would be more
human friendly to output & etc instead of numbers:

(de escXml (X)
   (for C (chop X)
  (case C
 ("\"" (prin """))
 ("&" (prin "&"))
 ("<" (prin "<"))
 (">" (prin ">"))
 (T (prin C)) ) ) )

What do you think?

Cheers,

Tomas
-- 
UNSUBSCRIBE: mailto:[EMAIL PROTECTED]


Re: Variable number of arguments in SVG functions

2008-10-21 Thread Jon Kleiser

Hi Alex,


Hi Jon,


 The test "(if (car Lst) ..." determines whether the current element is a
 container ("hoy") or not ("inner").


Is the 'car' necessary? Otherwise a simple test of 'Lst' would suffice.


No, it seems to work quite well without the 'car'. ;-)


BTW, I always feel that a 'prog' is a kind of kludge, and avoid it
if possible by inverting the 'if'. Then the following would also do:

   (ifn Lst
  (prinl " />")
  (prin ">")
  (run Lst 1)
  (prinl "") ) ) ) )

But perhaps this is a matter of taste.


That inversion is OK with me.

/Jon


 > Since this is "pure" XML, it would seem natural to find a function like

 this  in lib/xml.l. I haven't studied the functions in that file


Tomas also suggested this. I think it is a good idea. I would like to
let Tomas make the final decision and/or design.

Cheers,
- Alex

--
UNSUBSCRIBE: mailto:[EMAIL PROTECTED]


Re: Variable number of arguments in SVG functions

2008-10-21 Thread Alexander Burger
Hi Jon,

> The test "(if (car Lst) ..." determines whether the current element is a 
> container ("hoy") or not ("inner").

Is the 'car' necessary? Otherwise a simple test of 'Lst' would suffice.

BTW, I always feel that a 'prog' is a kind of kludge, and avoid it
if possible by inverting the 'if'. Then the following would also do:

   (ifn Lst
  (prinl " />")
  (prin ">")
  (run Lst 1)
  (prinl "") ) ) ) )

But perhaps this is a matter of taste.


> Since this is "pure" XML, it would seem natural to find a function like 
> this  in lib/xml.l. I haven't studied the functions in that file 

Tomas also suggested this. I think it is a good idea. I would like to
let Tomas make the final decision and/or design.

Cheers,
- Alex
-- 
UNSUBSCRIBE: mailto:[EMAIL PROTECTED]


Re: Variable number of arguments in SVG functions

2008-10-21 Thread Alexander Burger
Hi Tomas,

> maybe it could become part of lib/xml.l?  I would use it as it looks
> more convenient than building list for 'xml' function in some cases.

I'm not sure. It might be convenient, but it makes 'xml' asymmetrical.
Are you thinking of a separate '' function? It should be tried in
practical use.

Cheers,
- Alex
-- 
UNSUBSCRIBE: mailto:[EMAIL PROTECTED]


Re: Variable number of arguments in SVG functions

2008-10-21 Thread Jon Kleiser

On Mon, Oct 20, 2008 at 04:21:31PM +0100, Tomas Hlavaty wrote:

 That's nice.  It could even be:

 (de  Prg
(prin "<" (pop 'Prg))
(while (atom (car Prg))
   (prin " " (pop 'Prg) "=\"" (eval (pop 'Prg) 1) "\"") )
(prin ">")
(run Prg)   # the text, or other elements
(prinl "") )

 ( text id 123  dx (+ 3 4)  dy (* 3 4)
(prin "No font and color arguments yet") ) 


Yes, that's even better.


In addition, to make it more robust, we should

1. Check for an empty body (avoid an infinite loop):

  (while (and Prg (atom (car Prg)))

2. Run the body in the binding environment of the caller:

  (run Prg 1)


Cheers,
- Alex


Thanks Alex and Tomas! I really liked your ideas. Here's my current version:

(de  Lst
(let Tag (pop 'Lst)
(prin "<" Tag)
(while (and Lst (atom (car Lst)))
(prin " " (pop 'Lst) "=\"" (eval (pop 'Lst) 1) "\"") )
(if (car Lst)
(prog
(prin ">")
(run Lst 1)
(prinl "") )
(prinl " />") ) ) )

And it works like this:

: ( hoy id 123 ( inner fun "abc"))


-> ">"

The test "(if (car Lst) ..." determines whether the current element 
is a container ("hoy") or not ("inner").


Since this is "pure" XML, it would seem natural to find a function 
like this  in lib/xml.l. I haven't studied the functions in that 
file yet, but there's one called "xml" that is said to 
"Generate/Parse XML data". It could be interesting to know what that 
one does that's different from the new .


/Jon
--
UNSUBSCRIBE: mailto:[EMAIL PROTECTED]


Re: Variable number of arguments in SVG functions

2008-10-20 Thread Tomas Hlavaty
Hi Alex,

maybe it could become part of lib/xml.l?  I would use it as it looks
more convenient than building list for 'xml' function in some cases.

Thanks,

Tomas
-- 
UNSUBSCRIBE: mailto:[EMAIL PROTECTED]


Re: Variable number of arguments in SVG functions

2008-10-20 Thread Alexander Burger
On Mon, Oct 20, 2008 at 04:21:31PM +0100, Tomas Hlavaty wrote:
> That's nice.  It could even be:
> 
> (de  Prg
>(prin "<" (pop 'Prg))
>(while (atom (car Prg))
>   (prin " " (pop 'Prg) "=\"" (eval (pop 'Prg) 1) "\"") )
>(prin ">")
>(run Prg)   # the text, or other elements
>(prinl "") )
> 
> ( text id 123  dx (+ 3 4)  dy (* 3 4) 
>(prin "No font and color arguments yet") )  

Yes, that's even better.


In addition, to make it more robust, we should

1. Check for an empty body (avoid an infinite loop):

  (while (and Prg (atom (car Prg)))

2. Run the body in the binding environment of the caller:

  (run Prg 1)


Cheers,
- Alex
-- 
UNSUBSCRIBE: mailto:[EMAIL PROTECTED]


Re: Variable number of arguments in SVG functions

2008-10-20 Thread Tomas Hlavaty
> How about the following?
>
>(de  Prg
>   (prin "   (while (atom (car Prg))
>  (prin " " (pop 'Prg) "=\"" (eval (pop 'Prg) 1) "\"") )
>   (prin ">")
>   (run Prg)   # the text, or other elements
>   (prinl "") )
>
> Then you could write
>
>: (  id 123  dx (+ 3 4)  dy (* 3 4) 
>   (prin "No font and color arguments yet") )  
>No font and color arguments yet

That's nice.  It could even be:

(de  Prg
   (prin "<" (pop 'Prg))
   (while (atom (car Prg))
  (prin " " (pop 'Prg) "=\"" (eval (pop 'Prg) 1) "\"") )
   (prin ">")
   (run Prg)   # the text, or other elements
   (prinl "") )

( text id 123  dx (+ 3 4)  dy (* 3 4) 
   (prin "No font and color arguments yet") )  

:-)

Tomas
-- 
UNSUBSCRIBE: mailto:[EMAIL PROTECTED]


Re: Variable number of arguments in SVG functions

2008-10-20 Thread Alexander Burger
Hi Jon,

> then the calls would very often have a lot of NIL arguments, which looks 
> rather ugly. Should I switch to property lists? Any suggestions?

How about the following?

   (de  Prg
  (prin "")
  (run Prg)   # the text, or other elements
  (prinl "") )

Then you could write

   : (  id 123  dx (+ 3 4)  dy (* 3 4) 
  (prin "No font and color arguments yet") )  
   No font and color arguments yet

Cheers,
- Alex
-- 
UNSUBSCRIBE: mailto:[EMAIL PROTECTED]


Variable number of arguments in SVG functions

2008-10-20 Thread Jon Kleiser

Hi,

I've started some work on doing SVG graphics from Pico Lisp, and I've 
written a few functions that produce SVG elements. I try to do this 
more or less in the same way the HTML elements are done in 
lib/xhtml.l. Some SVG elements have just a small number of 
attributes, but others, like 'text', may have quite a few optional 
attributes. In my current  function I have not yet taken care 
of the "presentation attributes". It looks like this:


(de  (Id X Y Dx Dy Rotate TextLength LengthAdjust . Prg)
(prin "")
(run Prg)   # the text, or other elements
(prinl "") )

A simple call to this function may look like this:

( NIL "10%" "50%" NIL NIL NIL NIL NIL
(prin "No font and color arguments yet") )

If I should go on adding more presentation arguments for this 
function, then the calls would very often have a lot of NIL 
arguments, which looks rather ugly. Should I switch to property 
lists? Any suggestions?


Here are some useful SVG pages:




/Jon
--
UNSUBSCRIBE: mailto:[EMAIL PROTECTED]