Sysop: | Amessyroom |
---|---|
Location: | Fayetteville, NC |
Users: | 28 |
Nodes: | 6 (0 / 6) |
Uptime: | 43:33:37 |
Calls: | 422 |
Calls today: | 1 |
Files: | 1,024 |
Messages: | 90,182 |
zara <johan@freecol.be> writes:
* zara <m2tt8wv3gm.fsf@freecol.be> :
Wrote on Fri, 14 Feb 2025 18:30:33 +0100:
You didn't run it, but it does not just compile in clisp (2019),
it works. SFY.
No it is still wrong and it will also fail with Clisp (if clisp does
ansi). it'll fail if you load another file with the same functionn
names.
I ran clisp on NetBSD 10.0 and changed "add" to 'add (See the
dictionary.lisp file below and run it if you please) :
Some points to consider:
1. âaddâ returns the entire dictionary every time an entry is added.
If you anticipate that the dictionary could become large, then this
could become an awkward return value. Consider having âaddâ return only the latest entry to the dictionary:
(add (value)
(let ((entry (list (length *dict) value)))
(setq *dict (append *dict entry))
entry))
2. If this change is made, then you might want to add a function to âdispatchâ that displays the contents of â*dictâ if some other code is
not behaving as you expect. So,
(show ()
*dict)
Of course, later you could modify this, if wanted, to have, say, a loop
that displays formatted entries or arguments to âshowâ that specify the number of entries to display or the start and end of a range that you
want, and so on.
With this change, you will need to add an entry for âshowâ to âdispatchâ.
3. The following expression shows two problems:
(print (funcall (funcall dictionary 'add) 255))
a. the (print ()) is not needed since the âaddâ function will return
a value, which is then redundantly printed.
(funcall (funcall dictionary 'add) 255)
b. This shows that âdispatchâ is expected to return a function
object, which it does for âaddâ and âget-with-indexâ messages.
But for any other (invalid) message, it does not return a function
object, which causes the outer (funcall <what âdispatchâ returns>)
to trigger the debugger with a message unrelated to your message:
"make-dictionary: Message not understood"
You can fix this by two routes:
i. Use Lispâs âerrorâ function, as suggested by previous posts.
This will still trigger the debugger, but your error message
will be displayed rather than a message by invalid argument
to âfuncallâ.
ii. Write another function, say âmistakeâ, that âdispatchâ can
return and the outer âfuncallâ can call
(mistake (arg)
(format nil "dispatch: Message not understood: ~S" arg))
Then a typo in an expression
(funcall (funcall dictionary 'ade) 255)
will return the message in âmistakeâ.
4. Does your dictionary only grow or do anticipate that some entries
might be removed, that is, do you want to add a âdelâ function that
corresponds to your âaddâ function? This will need to search the
dictionary for an entry, and splice together two lists, the list before
the entry and the list after it.
As Kaz Kylheku suggested earlier, Lisp provides the hash table type
with numerous operations defined. See the following URL in the
Common Lisp Hyperspec:
https://www.lispworks.com/documentation/HyperSpec/Body/18_.htm
5. If you still decide not to use a hash table, here is another version
of âget-with-indexâ that eliminates list indexing and useâs the
âloopâ macroâs destructuring:
(get-with-index (index)
(loop
for (key val) on *dict by #'cddr
when (= key index)
return val))
Here is a version of âmake-dictionaryâ that makes some of the changes, above, including the recommendation to use âlabelsâ instead of multiple âdefunsâ.
(defun make-dictionary ()
"Create a âdispatchâ function that can manipulate its dictionary."
(let ((*dict ()))
(labels ((add (value)
(let ((entry (list (length *dict) value)))
(setq *dict (append *dict entry))
entry))
(show ()
*dict)
(get-with-index (index)
(loop
for (key val) on *dict by #'cddr
when (= key index)
return val))
(dispatch (msg)
(case msg
(add #'add)
(get-with-index #'get-with-index)
(show #'show)
(T (error
"dispatch: Message not understood: ~S" msg)))))
#'dispatch)))