Lisp's mysterious tuple problem
The author makes the claim that structures and CLOS classes are not widely used. The opposite is true.<p><pre><code>  CL-USER 202 &gt; (gp:make-graphics-state :thickness 2 :dashed t)</code></pre>
#S(GRAPHICS-PORTS:GRAPHICS-STATE :TRANSFORM (1 0 0 1 0 0)  ...)<p>Oh, wow, a graphics state for drawing is not a list, but a structure object.<p><pre><code>  CL-USER 204 &gt; (make-random-state)
  #S(RANDOM-STATE :J 44 :K 20 :SEED ...)
</code></pre>
Oh, wow, a random state is not a list, but a structure object.<p><pre><code>  CL-USER 205 &gt; (pathname &quot;&#x2F;foo&#x2F;bar&#x2F;baz.lisp&quot;)
  #P&quot;&#x2F;foo&#x2F;bar&#x2F;baz.lisp&quot;

  CL-USER 206 &gt; (describe *)

  #P&quot;&#x2F;foo&#x2F;bar&#x2F;baz.lisp&quot; is a PATHNAME
  HOST           NIL
  DEVICE         NIL
  DIRECTORY      (:ABSOLUTE &quot;foo&quot; &quot;bar&quot;)
  NAME           &quot;baz&quot;
  TYPE           &quot;lisp&quot;
  VERSION        NIL
</code></pre>
Oh, wow, a pathname is not a list or string, but a pathname object.<p>The Lisp I&#x27;m using has literally thousands of structure classes and CLOS classes defined. A Lisp Machine of the mid 80s had around 6000 classes defined.<p><pre><code>  CL-USER 158 &gt; (defclass vec3d ()
                  ((x :initarg :x) (y :initarg :y) (z :initarg :z)))
  #&lt;STANDARD-CLASS VEC3D 40201F4F8B&gt;

  CL-USER 159 &gt; (with-slots (x y z) (make-instance &#x27;vec3d :x 3 :y 4 :z -3)
                  (format t &quot;(~S,~S,~S)&quot; x y z))
  (3,4,-3)
</code></pre>
The only thing to understand is that Lisp code is usually not optimized for shortest code on the token level.<p>Though more compact versions of the DEFCLASS macro are being used sometimes. If an application needs a shorter notation, the programmer can always use macros and read-macros to introduce that.<p>The advantage of CLOS instances and structures over hashtables&#x2F;vectors&#x2F;lists is that they carry their class and that they use features like inheritance and method dispatch. The usual OO stuff.<p>Structures can have by-order-arguments and already print themselves readable:<p><pre><code>  CL-USER 162 &gt; (defstruct (svec3d (:constructor svec3d (x y z))) x y z)
  SVEC3D

  CL-USER 163 &gt; (svec3d 1 2 3)
  #S(SVEC3D :X 1 :Y 2 :Z 3)
</code></pre>
A structure can also have accessor functions without the structure name prefix:<p><pre><code>  CL-USER 168 &gt; (defstruct (svec3d
                            (:constructor svec3d (x y z))
                            (:conc-name))
                           x y z)
  SVEC3D

  CL-USER 169 &gt; (let ((p (svec3d 1 2 3)))
                  (format t &quot;(~S,~S,~S)&quot; (x p) (y p) (z p)))
  (1,2,3)
  NIL
</code></pre>
One can also provide multiple constructors and embed literal objects in code:<p><pre><code>  CL-USER 187 &gt; (defstruct (svec3d (:constructor svec3d (x y z))
                                   (:constructor make-svec3d)
                                   (:conc-name)) x y z)
  SVEC3D

  CL-USER 188 &gt; #S(SVEC3D :X 1 :Y 2 :Z 3)
  #S(SVEC3D :X 1 :Y 2 :Z 3)

  CL-USER 189 &gt; (let ((p #S(SVEC3D :X 1 :Y 2 :Z 3)))
                  (format t &quot;(~S,~S,~S)&quot; (x p) (y p) (z p)))
  (1,2,3)
  NIL
</code></pre>
Some implemetations also support the use of WITH-SLOTS with structures:<p><pre><code>  CL-USER 190 &gt; (with-slots (x y z) #S(SVEC3D :X 1 :Y 2 :Z 3)
                  (format t &quot;(~S,~S,~S)&quot; x y z))
  (1,2,3)
  NIL
</code></pre>
The tradition of Lisp usually is to give the programmer the choice of representation: adhoc lists&#x2F;vectors&#x2F;multiple values or structures (efficient records) or CLOS classes (flexible objects) or any kind of user defined stuff...<p>For any larger code and CLOS classes are usually the default choice for tuple data structures which don&#x27;t need the last bit of efficiency.