Hi TC,

thanks for your proposal.

However, as I explained in another mail, I would definitely not change
the current behavior of 'list' or 'cons' (and most other functions in
picoLisp).


> I'm uncertain if '() is actually (NIL . NIL) so I'm not going to list
> the cons' examples.

No, these are different things. () is converted by the reader as a
reference to the internal symbol 'NIL'. (NIL . NIL), which is the same
as (NIL), is a cell containing references to NIL in the CAR and CDR
parts.

(cons) is my standard way to create a fresh cell.



> I know why this works this way. In pL's VM, every list is parsed until
> there's an empty CDR (retreiving CDR returns NIL). Since there are
             ^ call this "atomic CDR"

> functions that MUST take at least one argument; when they are called
> with no argument, they will try to read NIL's CDR, and therefore use NIL
> as arguments, since (cdr NIL) -> NIL

Correct.


> Here are a couple of solutions for this issue, you pick:
>   1. Make it error when (cdr NIL) (increases complexity and decreases 
> flexibility).
>   2. Make pL check on every step if the current argument is actually the last 
> CAR (naive and maybe slow).
>   3. Make pL check the amount of arguments provided and return NIL if they 
> are not enough for the function to do it's job. (slightly increases 
> complexity)
>   4. Bury the topic.

A good roundup :-)

Points (1) and (2) would actually be rather stupid and useless, but can
be seen in some Lisp and Scheme implementations.


The original design of picoLisp put a lot of effort into the handling of
NIL. While NIL is in other Lisps just a symbol, it has a dual nature in
picoLisp (see "doc/structures" and "doc64/structures"):

      NIL:  /
            |
            V
      +-----+-----+-----+-----+
      |'LIN'|  /  |  /  |  /  |
      +-----+--+--+-----+-----+

While it is a symbol physically (the pointer is at an multiple of the
cell size plus half a cell), accessing the pointer with CAR (offset
zero) and CDR (offset half a cell size) is legal and will always return
NIL again. This allows a very fast traversal of lists, without the need
for checking for end-of-list.

So (3) comes without any cost.



> Anyway, I just couldn't resist the temptation to try to implement
> solution nÂș 3, so I grabbed the sources, segfaulted the hell out of it

Great! :-)

> when I tried to avoid repeating code, and after a long while of ERTCL
> (edit, recompile, test, cuss, loop), I decided to leave it like that for
> now, and ask for a revision.

Well, first of all, a function that counts arguments before evaluating
them should be avoided like hell. This was the main reason for rewriting
picoLisp in assembly language (explained in "doc64/README"). And,
fortunately, it is also not necessary. Usually a simple

   atom (X CDR)

will tell you if there are any (or more) arguments.

Besides this, what you wrote looks really good!

> +### Internal function ###
> +(code 'argLen 2)
> +   push X
> +   push Y
> ...
> +      ld Y (X CDR)  # Next cell
> +      cmp Y X  # Circular?
> +      jz lengthT  # Yes
> ...
> +      add E (hex "10")  # Increment counter
> +   loop
> +   ld Y X  # Keep list head    <- This should be before the "Circular?" 
> check?
> +   ret

Cheers,
- Alex
-- 
UNSUBSCRIBE: mailto:picol...@software-lab.de?subject=unsubscribe

Reply via email to