Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Type-rich programming in Common Lisp?

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?

like image 254
fouric Avatar asked Apr 04 '16 01:04

fouric


People also ask

What is a Common Lisp in programming language?

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).

Is Common Lisp still used?

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.

Is lisp a high level language?

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.

Is Lisp functional programming?

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.


1 Answers

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.

like image 89
jkiiski Avatar answered Oct 31 '22 00:10

jkiiski