3 ms·
> I don't know, and who cares. A Lisp programmer has to care, if he wants to write Lisp code. > I seem to be vaguely convinced for some reason that there may
by lispm 10y ago
> I don't know, and who cares.
A Lisp programmer has to care, if he wants to write Lisp code.
> I seem to be vaguely convinced for some reason that there may be exactly one docstring, and that, if present, it must be the first item in the body
That's wrong.
> I won't bother looking at the spec to see what the exact rules are
Which confirms what I'm saying: even for seemingly trivial DEFUNs the syntax is not obvious.
> Be they mistakes, they are still well-formed surface syntax and are readable.
But the reader does not implement Lisp syntax. The reader just implements s-expression syntax. If the reader can read the form, then it is a valid s-expression. But not necessarily valid Lisp.
(defun foo (a) a) ; valid s-expression, valid Lisp
(defun (foo) a a) ; valid s-expression, not valid Lisp
(defun (bar foo) (a) a) ; valid s-expression, not valid Lisp
(defun (setf foo) (a) a) ; valid s-expression, valid Lisp syntax
(defun foo (&key a &optional b) (list a b)) ; not valid Lisp
(defun foo ($key a &optional b) (list a b)) ; valid Lisp
The Lisp interpreter/compiler and the macros implement Lisp syntax. Not the reader.
> it's likely not an impediment to anyone else.
That you don't know the syntax of DEFUN confirms what I'm saying: the syntax is non-obvious.
Explain this:
* (defun foo (a b)
(declare (fixnum a))
"foo"
"bar"
(+ a b))
debugger invoked on a SIMPLE-ERROR: duplicate doc string "bar"
Type HELP for debugger help, or (SB-EXT:EXIT) to exit from SBCL.
restarts (invokable by number or by possibly-abbreviated name):
0: [ABORT] Exit debugger, returning to top level.
(SB-INT:PARSE-BODY ((DECLARE (FIXNUM A)) "foo" "bar" (+ A B)) T NIL)
0]
- kazinator 10y ago> That you don't know the syntax of DEFUN confirms what I'm saying. Yes, it rather confirms that you can go far in Lisp without memorizing stuff like this!!! If I don't have to know, few people do. You can bet your ass that if I had to implement an ANSI-CL conforming defun/lambda I'd get it right, of course. I don't have some "requirements don't matter" attitude; but not all requirements matter all the time to all people. I'd like to add, though, this: you can't be safe in ignorance in Common Lisp. Things you don't know can hurt you. Less than in some other languages, but they are there. You probably won't be hurt by not knowing all the possibilities for combining docstrings and declares. But if you're ignorant of some things, you may get burned. Undefined behavior situations like modifying literal tree structure, or writing a program that parses untrusted Lisp data, not knowing about the #. syntax and * read-eval* . I'm not advocating unsafe ignorance. Not knowing the full flexibility of some syntax is generally safe, though. > Explain this: Which aspect of that error scenario isn't self-explanatory; what is left to explain? From that one error, the listener has just taught us several important facts about the syntax which it accepts (which may be a superset of ANSI CL for all we know). It shows us that it accepts a docstring after a declare just fine, but that there must be at most one docstring. (At least, when the two are in that order, if we are to be strict in our guessing.) So without looking at a shred of documentation outside of that error message, I'm already better informed. The interactive nature of Lisp teaches! (Especially if the implementation is tight on error checking and has good diagnostics.) What's left unsettled from that error situation is whether or not there may be multiple declares, since that case isn't being probed.
- lispm 10y ago> Yes, it rather confirms that you can go far in Lisp without memorizing stuff like this!!! That you don't know the relatively trivial syntax of DEFUN, shows that it is already non-obvious and you have to look it up. You have failed to explain the syntax of DEFUN and you can't distinguish valid from invalid forms. I would never trust a code review done by you. > You can bet your ass that if I had to implement an ANSI-CL conforming defun/lambda I'd get it right, of course. Maybe. Maybe not. > Which aspect of that error scenario isn't self-explanatory; what is left to explain? Is that valid or not, given the syntax of Common Lisp? Does SBCL implement the syntax correctly or does it reject valid programs? The syntax of DEFUN is: defun function-name lambda-list [[declaration* | documentation]] form* Which says: any number of declarations and at most one documentation, in any order. (defun foo (a b) (declare (fixnum a)) ; declaration "foo" ; documentation "bar" ; form (+ a b)) Which indicates that SBCL rejects a valid program. I would not trust you to get it right as an implementor, given that you haven't even tried to verify it and that you are ignorant to Lisp syntax. I would not trust my own implementation without trying to come up with an extensive syntax test suite. Similar: (defun foo () "a") ; sbcl valid (defun foo () "a" "b") ; sbcl valid (defun foo () "a" "b" "c") ; sbcl rejects
- kazinator 10y ago> I would never trust a code review done by you. Why not? A code review has topics. It could be to enforce a coding convention. Firstly, I would not pass code that uses multiple docstrings or a funny order for docstrings and declares or multiple declares; a coding convention should forbid such pointless shenanigans, whether or not they are ANSI conforming. If the topic of the review was to determine whether the code is ANSI CL conforming, then I wouldn't just feed it to the listener of SBCL or any other implementation. Obviously, implementations can be nonconforming. They can accept, without diagnostic, inputs that require a diagnostic, as well as inputs that are nonportable or entirely undefined. You can't determine conformance of the code, or of the implementation, or both, without reading and interpreting the applicable standard, obviously. (You didn't have to labor this far if you just wanted me to say that.) > Does SBCL implement the syntax correctly or does it reject valid programs? Even if we determine that SBCL is rejecting valid programs, that version of SBCL will forever continue to do so. We have to change to a working construct to get the code working. Once we do that, the status of the nonworking construct that we replaced with a working one is rather moot. We have found all instances of that construct and replaced it, after which it no longer occurs in our code. We may submit a bug report against SBCL. Since we fixed the code not to interact with the bug/noncompliance, we don't care when, if ever, SBCL issues a fix. The nonworking construct could have been avoided in the first place by sticking to the simplified "canonical" syntax: (defun args [ docstring ] [ (declare ...) ] {form}*) You can program defun-s for the rest of your Lisp programming life this way and never know the full syntax. You're also vanishingly unlikely to run into an implementation which doesn't accept the variations on this canonical syntax. Deviations from this form can be rewritten into this form. The exception might be machine-generated deviations. Like multiple declares or docstrings that are piled on by some macrology: if you want their output to be canonicalized, you have to insert some processing pass to do that normalization. That is annoying, and so we will feel better if we can blame it on a nonconformance in the implementation, even if we still have to do this work. > (defun foo () "a" "b" "c") ; sbcl rejects That's somewhat nasty; yet, there is no reason to write this kind of defun by hand. "a" is obviously a docstring, and "c" the return value. But "b" is superfluous in the sense that it has no effect. If "b" contains documentation, it should be merged into "a" to produce the canonical form (defun foo () "ab" "c"): "ab" is the doc, "c" the returned object. If that doesn't work, then I care; that is uproarious. I might be interested in knowing whether the above "a" "b" "c" is in fact invalid ANSI CL, if I'm more invested in that rejected form; like I have some macrology that produces it (so fixing the situation requires more work than just hunting down a couple of bad defuns). That macrology could be reused in other projects and so on. Still, the fact that SBCL rejects it means that I can't have it if we are targetting SBCL. A workaround for SBCL (if that's what it is) might as well be applied all across the board. So is it ANSI CL or not? The syntax is: defun function-name lambda-list [[declaration* | documentation]] form* This [[]] notation is a special "splicing" extension of the BNF syntax which here indicates that there may be at most one docstring and any number of declarations, and these may appear in any order (so that a docstring can come between declares).