3 ms·
> 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 t
by 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).
- kazinator 10y agoHi lispm. I investigated this more deeply and I'm afraid I cannot conclude that SBCL is wrong. The root of the problem is this splicing [[ ]] extended BNF notational concoction, in whose description we find this: ... For example, the expression (x [[A | B* | C]] y) means that at most one A, any number of B's, and at most one C can occur in any order. It is a description of any of these: (x y) (x B A C y) (x A B B B B B C y) (x C B A B B B y) but not any of these: (x B B A A C C y) (x C B C y) In the first case, both A and C appear too often, and in the second case C appears too often. In the case of defun, we can identify C with documentation and y with forms. But documentation is a kind of form. According to the above, if we are given documentation documentation form, it doesn't match: documentation appears "too often". That appears to rule out "foo" "bar" as ill-formed, if "bar" is interpreted as documentation rather than form. This is woefully badly specified; it is not clear how to unambiguously determine the extent of the symbols matched by a given [[ ]] notation. There needs to be a clearly stated requirement that [[ ]], independently of what follows it, denotes (say) the longest possible sequence of symbols which is consistent with its constraints. The material which follows [[ ]] must then match against the remaining symbols in the form. Then it will be clear that given "foo" "bar", the "bar" string isn't part of the [[ declare(star) | documentation ]] spec, because the longest match ends with "foo" (if no declares follow). Maybe it does. I'm afraid I cannot make head or tail out of the sentence "such that if n /=m and 1<=n,m<=j, then either Oin/=Oim or Oin = Oim = Qk, where for some 1<=k <=n, Ok is of the form Qk {star} . Furthermore, for each Oin that is of the form {Qk}1 , that element is required to appear somewhere in the list to be spliced. " Perhaps that rescues it somehow.