Hi Tomas,

> what is the best way to write the cls macro in the following example?

I think your solution is very good!

The problem is that there are no evaluating version of the functions
'class' and 'dm'. That's why you have to resort to a macro in the first
place. And a macro is always an inferior solution, IMHO.

Thus, one possible way could be to write evaluating versions of 'class'
and 'dm'.

Another possibility (and the one I would prefer here) is to avoid these
functions altogether, and implement the necessary operations directly:

   (de cls Lst
      (let (Cls (pop 'Lst)  Vars (mapcar '((F) (uppc (car F))) Lst))
         (def (setq *Class Cls)
               (cons T Vars
                  (cons 'default (mapcan '((V L) (list V (cadr L))) Vars Lst))
                  (mapcar '((V L) (list '=: (car L) V)) Vars Lst) )
               (cons (def 'move> meth) Vars
                  (mapcar '((V F) (list 'inc (list ':: (car F)) V)) Vars Lst) )
               (list (def 'pput> meth) NIL
                  (cons 'prin "("
                     (list ': (caar Lst))
                     (mapcan '((F) (list "," (list ': (car F)))) (cdr Lst)) )
                  '(prin ")") ) ) ) ) ) ) )

However, this is even less readable ;-)

It takes advantage of the fact that picoLisp's internal structures are
sufficiently simple, and are rather easily manipulated.

> Also, why is intern needed in those places?  Could/should not these be
> transient symbols which I guess are not interned and still be used as
> variables?

Very true. Transient symbols would even be better here, because they
point out the locality of those variables. But because they are not
interned, you have to make sure that they are unique (and not created
newly upon each call to 'uppc').

My example of 'cls' above does this. It keeps all generated transient
symbols in the list 'Vars', and inserts them whenever necessary.

BUT: In general, I believe that such a static code generation is not the
"picoLisp way".

It always depends on what is needed by the end of the day, but a dynamic
solution is usually more flexible, and expresses explicitly what the
program is supposed to do.

I would probably do it this way:

   (class +xDeePoint)
   # coordinates

   (dm T @
      (=: coordinates
            '((Init Arg)
               (put This (car Init) (or Arg (cadr Init)))
               (car Init) )
            (var: init)
            Args ) ) )

   (dm move> @
         '((Var) (inc (prop This Var) (next)))
         (: coordinates) ) )

   (dm pput> ()
         (glue ","
               '((Var) (get This Var))
               (: coordinates) ) )

         ")" ) )

   (class +TwoDeePoint +xDeePoint)
   (var init (x 1) (y 2))

   (class +ThreeDeePoint +xDeePoint)
   (var init (x 3) (y 4) (z 5))

> picolisp.  I found that functions macro or make deal with this or I
> could just build a list and call eval.  However, this does not seem
> elegant enough to me.  What is the reason picolist does not have
> similar backquote and comma?

Partly historical reasons. PicoLisp evolved in the mid-1980s before I
ever heard about Common Lisp ;-)

The other reason is that it is not so practical in an environment where
macros do not have that importance. Directly building lists with 'make'
is also more general and powerful, I think. Might be a philosophical
issue, though: Backquote expressions are static, while I prefer a
dynamic build-up of structures. Similar arguments apply to the 'match'
function versus regular expressions (with 'match' you implement a
dynamic procedure, while a regexp tries to match it all at once with a
single static expression).

What comes nearest to a backquote expression is probably the 'fill'
function. While a backquote mechanism would be hard-coded into the
language, functions similar 'fill' can be written as needed.

> Is there a better way of writing the third line (without eval) of the
> following?
> (de eList (Plural Dlg)
>    (<h3> NIL Plural)
>    (eval (list 'form 'dialog Dlg)))

I would write

   (de eList (Plural Dlg)
      (<h3> NIL Plural)
      (form 'dialog (eval Dlg)) )

BTW, there must be a quote before "(nm" in

> (eList "Users" '(choDlg T ,"Users" '(nm +User)))

> I struggle with calling form the right way as it does not evaluate
> its rest/cdr argument which I want to pass in as a "quoted" list.

In fact, it does evaluate (I would call it: execute) its arguments.

- Alex

Reply via email to