The newcomer to Lisp might not have seen the special operator the before. This special operator allows the programmer to inform the compiler of the type returned by a form, in the event that the compiler cannot deduce it from context. Note that this is not the same as a C or C++ static cast, the does not modify a type, and does not necessarily perform type checking (behaviour is undefined if you present it an object that is incompatible with the type declared by the), it merely tells the compiler what it should expect to get back from a form. Compare this with the declare special operator, which can be used to tell the compiler what the types are of parameters passed to a function.
To demonstrate, I’ve written a function, remote-function, that simply returns the number 20. I then have some code that uses this function, which I’m compiling for speed. The compiler doesn’t know what remote-function does, and I could always change the function after compilation, so it can’t optimize fully without the the special operator. The resulting disassembly listings show the difference. In the first case, without the, the addition operator is a function call to generic-+, whereas in the second case the addition is made using straight integer arithmetic, with no function setup and call.
Without the special operator compiler hint:
(declaim (optimize (debug 0) (safety 0) (speed 3))) (defun my-adder () (+ 5 (remote-function)))
CL-USER> (disassemble 'my-adder) ; disassembly for MY-ADDER ; Size: 51 bytes ; 033CEADF: 488D5424F0 LEA RDX, [RSP-16] ; no-arg-parsing entry point ; AE4: 4883EC18 SUB RSP, 24 ; AE8: 488B05A9FFFFFF MOV RAX, [RIP-87] ; #<FDEFINITION object for REMOTE-FUNCTION> ; AEF: 31C9 XOR ECX, ECX ; AF1: 48892A MOV [RDX], RBP ; AF4: 488BEA MOV RBP, RDX ; AF7: FF5009 CALL QWORD PTR [RAX+9] ; AFA: 480F42E3 CMOVB RSP, RBX ; AFE: BF0A000000 MOV EDI, 10 ; B03: 41BBF0010020 MOV R11D, 536871408 ; GENERIC-+ ; B09: 41FFD3 CALL R11 ; B0C: 488BE5 MOV RSP, RBP ; B0F: F8 CLC ; B10: 5D POP RBP ; B11: C3 RET NIL
With the special operator compiler hint:
(declaim (optimize (debug 0) (safety 0) (speed 3))) (defun my-adder () (+ 5 (the (integer 0 65535) (remote-function))))
CL-USER> (disassemble 'my-adder) ; disassembly for MY-ADDER ; Size: 41 bytes ; 0379FF5F: 488D5424F0 LEA RDX, [RSP-16] ; no-arg-parsing entry point ; 64: 4883EC18 SUB RSP, 24 ; 68: 488B05A9FFFFFF MOV RAX, [RIP-87] ; #<FDEFINITION object for REMOTE-FUNCTION> ; 6F: 31C9 XOR ECX, ECX ; 71: 48892A MOV [RDX], RBP ; 74: 488BEA MOV RBP, RDX ; 77: FF5009 CALL QWORD PTR [RAX+9] ; 7A: 480F42E3 CMOVB RSP, RBX ; 7E: 4883C20A ADD RDX, 10 ; 82: 488BE5 MOV RSP, RBP ; 85: F8 CLC ; 86: 5D POP RBP ; 87: C3 RET NIL