`trivial-coerce` primarily provides a `trivial-coerce:coerce` function intended as an extensible alternative to `cl:coerce`.
- Re-implemented using polymorphic-functions.extended-types use
(optimize (speed 3))with (< debug 3) to compile-time optimize for inline static dispatch.
- API is immature; wait for a few months or years until this library gets more thoroughly tested.
I suspect that unless there are requests, I will not work on optimizing for run-time performance.
In case someone has a better idea for
trivial-coerce- feel free to raise an issue, and in the worst case, if more than a handful think (or I get convinced) the other library better deserves the name, I'd be glad to rename this library to something else. (Therefore, use with package-local-nicknames.)
Common Lisp has a variety of non-uniform type-conversions. Some use
cl:coerce, others use
cl:string, and lots more. In some sense, the
cl:coerce function is information-preserving in that it prevents non-integers from being coerced into integers, or characters from being converted to and from integers. If you find these semantics useful, you might not find
trivial-coerce:coerce as useful.
OTOH, a case could be made that the prevalence of information non-preserving type conversions makes things easier for prototyping, enables better polymorphism, as well as makes things easier for new people.
I do not find generic-functions suitable for the purpose of coercion. For instance:
(in-package :generic-cl) (deftype int () 'integer) (defmethod coerce ((num real) (type (eql 'integer))) (floor num)) (coerce 2.5 'integer) ;=> works (coerce 2.5 'int) ;=> does not work (trivial-coerce:coerce 2.5 'int) ;=> works ;; Yet another example would concern the order of applicants in a OR or AND or MEMBER ;; compound-type-specifiers - and it surely feels useful to say: (and vector (not string))
I do not know of alternatives.
The main function is
(trivial-coerce:coerce object output-type-spec):
This converts OBJECT to type specified by OUTPUT-TYPE-SPEC.
The applicable coercion is guaranteed to take an object of (super)type of OBJECT and return an object of type= specified by OUTPUT-TYPE-SPEC. (See Role of Extended Types.)
Important functions and macros
Example usages of
define-coercion can be found in coercions.lisp.
Compile Time Optimizations
CL-USER> (defun to-type (a type) (coerce a type)) TO-TYPE CL-USER> (defun to-type (a type) (declare (optimize speed)) (coerce a type)) ; (Compiler) Macro of ; #<POLYMORPHIC-FUNCTIONS:POLYMORPHIC-FUNCTION COERCE (38)> ; is unable to optimize ; (COERCE A TYPE) ; because: ; ; Type of ; TYPE ; could not be determined WARNING: redefining COMMON-LISP-USER::TO-TYPE in DEFUN TO-TYPE CL-USER> (defun to-string (a) (declare (optimize speed)) (coerce a 'string)) ; (Compiler) Macro of ; #<POLYMORPHIC-FUNCTIONS:POLYMORPHIC-FUNCTION COERCE (38)> ; is unable to optimize ; (COERCE A 'STRING) ; because: ; ; Type of ; A ; could not be determined TO-STRING CL-USER> (defun to-string (a) (declare (optimize speed) (type number a)) (coerce a 'string)) WARNING: redefining COMMON-LISP-USER::TO-STRING in DEFUN TO-STRING CL-USER> (disassemble 'to-string) ; disassembly for TO-STRING ; Size: 17 bytes. Origin: #x5374A224 ; TO-STRING ; 24: B902000000 MOV ECX, 2 ; 29: FF7508 PUSH QWORD PTR [RBP+8] ; 2C: B8C2333650 MOV EAX, #x503633C2 ; #<FDEFN SB-INT:STRINGIFY-OBJECT> ; 31: FFE0 JMP RAX ; 33: CC10 INT3 16 ; Invalid argument count trap NIL
Role of Extended Types
(define-coercion (sequence :to list :from sequence) (cl:coerce sequence 'list)) macroexpands to:
(defpolymorph (coerce :inline t) ((sequence sequence) (#:output-type-spec1824 (type= list))) list (declare (ignorable sequence #:output-type-spec1824)) (common-lisp:coerce sequence 'list))
Thus, we use the extended type
(type= list) to denote all the type specifiers that are type= to
(typep '(and list) '(type= list)) holds (using
*If you are using extensible-compound-types, then the appropriate
type= would be
extensible-compound-types:type= instead of