【问题标题】:Type-rich programming in Common Lisp?Common Lisp 中的类型丰富的编程?
【发布时间】:2016-04-04 01:27:27
【问题描述】:

前几天我读到一篇关于静态类型的文章 (https://bsamuels.net/2013/11/20/static-typing.html),它描述了一个有趣的概念,称为“类型丰富的编程”,作为程序员,您在其中定义类型,对于机器来说,这些类型只是现有类型的别名(例如整数或浮点数),但对您来说,它们描述了可以使用这些机器类型表示的不同数量之间的差异(例如,秒和米都可以用双精度数表示,但您当然不想将它们加在一起)。

我知道 Common Lisp 是一种动态类型语言。但是,我也知道,如果我使用the 和check-type,某些编译器(例如我使用的SBCL)会进行一些有限的类型检查。如何创建类型别名以便为 SBCL 提供更丰富的类型?或者,如果不是这样,那我怎样才能得到类似于 Common Lisp 中类型丰富的编程的东西呢?

【问题讨论】:

标签: types common-lisp


【解决方案1】:

Common Lisp 有DEFTYPE 用于定义新类型。例如:

(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 #\.)))

但这并不妨碍您将秒数和米数相加:

(deftype meters ()
  'number)

(let ((s 30)
      (m 15))
  (declare (type seconds s)
           (type meters m))
  (+ s m))
;=> 45

您可以创建一个使用CHECK-TYPE 或声明的函数来检查该值在几秒钟内是否有效:

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

但这只会检查该值是否有效。它并不关心您是否将变量声明为米,因为该函数仅传递值。

(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

如果你想强制秒和米永远不会加在一起,你应该只使用类和对象。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-03-18
    • 1970-01-01
    • 2011-08-29
    • 1970-01-01
    • 2013-03-19
    • 1970-01-01
    • 2011-09-09
    • 1970-01-01
    相关资源
    最近更新 更多