常见的lisp typecase与defgeneric运行时分析

时间:2015-05-31 18:28:44

标签: graphics common-lisp generic-programming

我正在编写一个使用opengl的常见lisp的应用程序,随着事情的发展,我意识到我有一些选择。我有一堆不同的类,它们都需要代码来快速而经常地渲染它们,所以我正在考虑以下代码结构:

(defgeneric render (x))
(defmethod render ((x vanilla-foo))
   (generic-foo-stuff)
   (vanilla-specific-stuff)
   (more-generic-foo-stuff))
(defmethod render ((x chocolate-foo))
   (generic-foo-stuff)
   (chocolate-specific-stuff)
   (more-generic-foo-stuff))

等等,很多这些方法。另一种方法是使用typecase语句:

(defun render (any-old-foo)
   (generic-foo-stuff)
   (typecase
      (vanilla-foo 
         (vanilla-specific-stuff))
      (chocolate-foo
         (chocolate-specific-stuff))
      ;;and so on, lots of cases here
    )
    (more-generic-foo-stuff))

我认为这些都是以自己的方式丑陋,但我的假设是lisp将在引擎盖下使用某种哈希表O(1)查找,将传递给泛型函数的参数类型映射到位置所需的方法,而第二种方法将需要O(n)类型比较通过typecase语句。另一方面,根据散列的速度有多慢或多快,在第一种方法真正加快之前,我可能需要数千种foo风味。

有一个很好的表现理由我应该喜欢一个吗?我也对其他建议或对某种文件的引用持开放态度,这些文件使我更清楚在每种情况下发生的事情。我也很好奇你可能遇到的这种冲突的其他情况。

谢谢!

2 个答案:

答案 0 :(得分:6)

至少你可以通过将通用内容分解为:before:after方法来减少使用泛型函数的代码:

(defgeneric render (x))

(defmethod render :before (x) ; Do what always has to be done first
  (generic-foo-stuff))

(defmethod render :after (x) ;  Do what always has to be done last
  (more-generic-foo-stuff))

(defmethod render ((x vanilla-foo)) ; Do only vanilla-specific things here
   (vanilla-specific-stuff))

(defmethod render ((x chocolate-foo)) 
   (chocolate-specific-stuff))

答案 1 :(得分:5)

如果一个

,可以使用泛型函数
  • 有多种各种参数组合的实现
  • 希望使功能可扩展
  • 希望通过重用片段( methods
  • 来汇编代码

然后我们也可以使用:before:after方法重写您的示例。

如果代码应该尽可能快速和静态,那么泛型函数就不是一个好的选择。

如果您需要提前计划性能,那么您最好进行一些实验并测量时间。