Beyond the &ANSI; Standard</> <para>Besides &ANSI;, we have other stuff..</para> <sect1 id="non-conformance"><title>Non-Conformance with the &ANSI; Standard</> <para>&SBCL; is derived from code which was written before the &ANSI; standard, and some incompatibilities remain.</para> <para>The &ANSI; standard defines constructs like <function>defstruct</>, <function>defun</>, and <function>declaim</> so that they can be implemented as macros which expand into ordinary code wrapped in <function>eval-when</> forms. However, the pre-&ANSI; &CMUCL; implementation handled these (and some related functions like <function>proclaim</>) as special cases in the compiler, with subtly (or sometimes not-so-subtly) different semantics. Much of this weirdness has been removed in the years since the &ANSI; standard was released, but bits and pieces remain, so that e.g., as of &SBCL; 0.6.3 compiling the function <programlisting>(defun foo () (defstruct bar))</> will cause the class <type>BAR</> to be defined, even when the function is not executed. These remaining nonconforming behaviors are considered bugs, and clean patches will be gratefully accepted, but as long as they don't cause as many problems in practice as other known issues, they tend not to be actively fixed.</para> <para>More than any other &Lisp; system I am aware of, &SBCL; (and its parent &CMUCL;) store and use a lot of compile-time static type information. By and large they conform to the standard in doing so, but in one regard they do not — they consider <function>defun</>s to, in effect, implicitly <function>proclaim</> type information about the signature of the function being defined. Thus, if you compile and load <programlisting>(defun foo-p (x) (error "stub, foo-p ~s isn't implemented yet!" x)) (defun foolike-p (x) (or (foo-p x) (foo-p (car x))))</programlisting> everything will appear to work correctly, but if you subsequently redefine <function>foo-p</> <programlisting>(defun foo-p (x) (or (null x) (symbolp (car x))))</> and call <programlisting>(foolike-p nil)</> you will not get the correct result, but an error, <screen>debugger invoked on SB-DEBUG::*DEBUG-CONDITION* of type SB-KERNEL:SIMPLE-CONTROL-ERROR: A function with declared result type NIL returned: FOO-P</screen> because when &SBCL; compiled <function>foolike-p</>, &SBCL; thought it knew that <function>foo-p</> would never return. More insidious problems are quite possible when &SBCL; thinks it can optimize away e.g. particular branches of a <function>case</> because of what it's proved to itself about the function's return type. This will probably be fixed in the foreseeable future, either with a quick fix, or ideally in conjunction with some related fixes to generalize the principle that declarations are assertions (see below). But for now it remains a gross violation of the &ANSI; spec (and reasonable user expectations).</para> <para>The &CMUCL; <function>defstruct</> implementation treated structure accessors and other <function>defstruct</>-related functions (e.g. predicates) as having some special properties, not quite like ordinary functions. This specialness has been reduced in &SBCL;, but some still remains. In particular, redefining a structure accessor function may magically cause the entire structure class to be deleted. This, too, will probably be fixed in the foreseeable future.</para> <para>The CLOS implementation used in &SBCL; is based on the <application>Portable Common Loops</> (PCL) reference implementation from Xerox. Unfortunately, PCL seems never to have quite conformed to the final CLOS specification. Moreover, despite the "Portable" in its name, it wasn't quite portable. Various implementation-specific hacks were made to make it run on &CMUCL;, and then more hacks were added to make it less inefficient. The result is a system with mostly tolerable performance which mostly conforms to the standard, but which has a few remaining weirdnesses which seem to be hard to fix. The most important remaining weirdness is that the <type>CL:CLASS</> class is not the same as the <type>SB-PCL:CLASS</> type used internally in PCL; and there are several other symbols maintained in parallel (e.g. <type>SB-PCL:FIND-CLASS</> vs. <type>CL:FIND-CLASS</>). So far, any problems this has caused have had workarounds involving consistently using the SB-PCL versions or the CL versions of the class hierarchy. This is admittedly ugly, but it may not be fixed in the foreseeable future, since the required cleanup looks nontrivial, and we don't have anyone sufficiently motivated to do it.</para> </sect1> <sect1 id="idiosyncrasies"><title>Idiosyncrasies</> <para>Declarations are generally treated as assertions. This general principle, and its implications, and the bugs which still keep the compiler from quite satisfying this principle, are discussed in the <link linkend="compiler">chapter on the compiler</link>.</para> <note><para>It's not an idiosyncrasy yet, since we haven't done it, but someday soon &SBCL; may become a compiler-only implementation. That is, essentially, <function>eval</> will be defined to create a lambda expression, call <function>compile</> on the lambda expression to create a compiled function, and then <function>funcall</> the resulting function. This would allow a variety of simplifications in the implementation, while introducing some other complexities. It remains to be seen when it will be possible to try this, or whether it will work well when it's tried, but it looks appealing right now.</para></note> </sect1> <sect1 id="extensions"><title>Extensions</> <para>&SBCL; is derived from &CMUCL;, which implements many extensions to the &ANSI; standard. &SBCL; doesn't support as many extensions as &CMUCL;, but it still has quite a few.</para> <sect2><title>Things Which Might Be in the Next &ANSI; Standard</> <para>&SBCL; provides extensive support for calling external C code, described <link linkend="ffi">in its own chapter</link>.</para> <para>&SBCL; provides additional garbage collection functionality not specified by &ANSI;. Weak pointers allow references to objects to be maintained without keeping them from being GCed. And "finalization" hooks are available to cause code to be executed when an object is GCed.</para> <!-- FIXME: Actually documenting these would be good.:-| --> <para>&SBCL; does not currently provide Gray streams, but may do so in the near future. (It has unmaintained code inherited from &CMUCL; to do so.) <!-- FIXME: Add citation to Gray streams.--> </para> </sect2> <sect2><title>Support for Unix</> <para>The UNIX command line can be read from the variable <varname>sb-ext:*posix-argv*</>. The UNIX environment can be queried with the <function>sb-ext:posix-getenv</> function.</para> <para>The &SBCL; system can be terminated with <function>sb-ext:quit</>, optionally returning a specified numeric value to the calling Unix process. The normal Unix idiom of terminating on end of file on input is also supported.</para> </sect2> <sect2><title>Tools to Help Developers &SBCL; provides a profiler and other extensions to the &ANSI; trace facility. See the online function documentation for trace for more information. The debugger supports a number of options. Its documentation is accessed by typing help at the debugger prompt. Documentation for inspect is accessed by typing help at the inspect prompt. Interface to Low-Level &SBCL; Implementation &SBCL; has the ability to save its state as a file for later execution. This functionality is important for its bootstrapping process, and is also provided as an extension to the user See the documentation for sb-ext:save-lisp-and-die for more information. &SBCL; has inherited from &CMUCL; various hooks to allow the user to tweak and monitor the garbage collection process. These are somewhat stale code, and their interface might need to be cleaned up. If you have urgent need of them, look at the code in src/code/gc.lisp and bring it up on the developers' mailing list. &SBCL; has various hooks inherited from &CMUCL;, like sb-ext:float-denormalized-p, to allow a program to take advantage of &IEEE; floating point arithmetic properties which aren't conveniently or efficiently expressible using the &ANSI; standard. These look good, and their interface looks good, but &IEEE; support is slightly broken due to a stupid decision to remove some support for infinities (because it wasn't in the &ANSI; spec and it didn't occur to me that it was in the &IEEE; spec). If you need this stuff, take a look at the ecode and bring it up on the developers' mailing list. Efficiency Hacks The sb-ext:purify function causes &SBCL; first to collect all garbage, then to mark all uncollected objects as permanent, never again attempting to collect them as garbage. (This can cause a large increase in efficiency when using a primitive garbage collector, but is less important with modern generational garbage collectors.) The sb-ext:truly-the operator does what the cl:the operator does in a more conventional implementation of &CommonLisp;, declaring the type of its argument without any runtime checks. (Ordinarily in &SBCL;, any type declaration is treated as an assertion and checked at runtime.) The sb-ext:freeze-type declaration declares that a type will never change, which can make type testing (typep, etc.) more efficient for structure types. The sb-ext:constant-function declaration specifies that a function will always return the same value for the same arguments. This is appropriate for functions like sqrt. It is not appropriate for functions like aref, which can change their return values when the underlying data are changed.