I read an article about static typing the other day (https://bsamuels.net/2013/11/20/static-typing.html) that described an interesting concept called "type-rich programming", where you as a programmer define types that, to the machine, are simply aliases for existing types (such as integers or floats), but to you they describe the difference between different quantities that could be represented using those machine types (e.g., seconds and meters could both be represented by doubles, but you certainly wouldn't want to add them together).
I know that Common Lisp is a dynamically-typed language. However, I also know that some compilers (such as the one that I use, SBCL) will do some limited type checking if I use the
and check-type
. How can I create type aliases so that I can provide richer types to SBCL? Or, if not that, then how can I get something that looks sort of like type-rich programming in Common Lisp?
Common Lisp is a general-purpose programming language and thus has a large language standard including many built-in data types, functions, macros and other language elements, and an object system (Common Lisp Object System).
While it isn't as popular as C, Python or Perl, Lisp is still used for AI programming as well as several other functions. Lisp continues to be popular in higher education, as students learn Lisp programming tactics and extend this knowledge to the private sector after graduation.
Lisp is the second-oldest high-level programming language in the world which is invented by John McCarthy in the year 1958 at the Massachusetts Institute of Technology.
Lisp is a functional programming language with imperative features. By functional we mean that the overall style of the language is organized primarily around expressions and functions rather than statements and subroutines.
Common Lisp has DEFTYPE
for defining new types. For example:
(defun secondsp (s)
(<= 0 s 59))
(deftype seconds ()
'(and number (satisfies secondsp)))
(let ((s 0))
(declare (type seconds s))
(loop
repeat 60 ;should cause an error when S becomes 60
do (incf s)
do (write-char #\.)))
It doesn't prevent you from adding seconds and meters together though:
(deftype meters ()
'number)
(let ((s 30)
(m 15))
(declare (type seconds s)
(type meters m))
(+ s m))
;=> 45
You could create a function that uses CHECK-TYPE
or declarations to check that the value is a valid one for seconds:
;; with CHECK-TYPE and THE
(defun add-seconds (s1 s2)
(check-type s1 seconds)
(check-type s2 seconds)
(the seconds (+ s1 s2)))
;; With declarations
(declaim (ftype (function (seconds seconds) seconds) add-seconds-decl))
(defun add-seconds-decl (s1 s2)
(+ s1 s2))
But that will only check that the value is valid second. It doesn't care if you declared the variable to be meters since the function is only passed the value.
(let ((s1 30)
(s2 15)
(m 25))
(declare (type seconds s1 s2)
(type meters m))
(format t "~&S1 + S2 = ~a" (add-seconds-decl s1 s2))
(format t "~&S1 + M = ~a" (add-seconds-decl s1 m)))
;; S1 + S2 = 45
;; S1 + M = 55
If you want to enforce that seconds and meters are never added together, you should just use classes and objects.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With