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:[email protected]?subject=unsubscribe