2011-07-15 48 views
8

是否有任何支持数组和线性代数操作的Lisp或模式方言?通过良好的支持,我不是指BLAS/LAPACk的接口,而是语言本身中有效的数组原语。比如,如果它能够对抗Numpy,我会认为它是有效的。我听说斯大林速度非常快,但我很new舌,不熟悉句法方便的操作和多维数组在这些语言中的高效表示。指针(无双关语)将深受赞赏,特别是如果支持个人经验。具有良好多维数组编程支持的Lispy方言

回答

12

Arrays标准Common Lisp可以是​​多维的。

Array Dictionary描述了可用的操作。

CL-USER 12 > (defparameter *a* (make-array '(3 2 4) :initial-element 'foo)) 
*A* 

CL-USER 13 > *a* 
#3A(((FOO FOO FOO FOO) (FOO FOO FOO FOO)) 
    ((FOO FOO FOO FOO) (FOO FOO FOO FOO)) 
    ((FOO FOO FOO FOO) (FOO FOO FOO FOO))) 

CL-USER 14 > (setf (aref *a* 1 1 2) 'bar) 
BAR 

CL-USER 15 > *a* 
#3A(((FOO FOO FOO FOO) (FOO FOO FOO FOO)) 
    ((FOO FOO FOO FOO) (FOO FOO BAR FOO)) 
    ((FOO FOO FOO FOO) (FOO FOO FOO FOO))) 

CL-USER 16 > (array-dimensions *a*) 
(3 2 4) 

使用数组时,使用Common Lisp的另一个特性:类型声明和编译器优化可能会很有用。 Common Lisp允许在不声明类型的情况下编写通用代码。但是在关键部分,可以声明变量,参数,返回值等类型。然后可以指示编译器摆脱一些检查或使用类型特定的操作。支持的数量取决于编译器。还有更复杂的编译器,如SBCL,LispWorks和Allegro CL,它们支持各种优化。一些编译器也提供了大量的编译信息。

最后的手段是使用外部函数接口(FFI)来调用C代码或使用内联汇编程序(它由一些编译器支持)。

Common Lisp在默认情况下具有标准中的LOOP宏。它允许表达典型的命令循环结构。还有一个替代方案,即ITERATE宏 - 它对于多维数组可能有一些优势。

另请注意,Lisp阵列具有一些不寻常的功能,如位移阵列。这些使用一些其他阵列的存储,但可以有不同的尺寸布局。

编写特殊的宏有时也很有用,它隐藏了使用数组的样板。没有类型声明的Lisp代码,多维数组和LOOP可能有点大。不使用特殊语言抽象的典型代码示例如下:fft.lisp

SIMD指令或其他形式的数据并行性的特殊用途通常不由Common Lisp编译器开箱即用。例外情况可能存在。

4

您是否考虑过使用Incanter库的Clojure?它对矩阵有很好的支持,并且具有用于绘图,数学函数,统计等其他内容的高质量代码。它也很好地支持内置的并行机制。

3

球拍(以前称为PLT计划)最近有不错的multi-dimensional arrays (math/array)。它们似乎受Python NumPy和Data Parallel Haskell的启发。您可能喜欢的一些主要特点:

  • 真N维hyperrectangular形状
  • 广播(在一个或多个阵列逐点操作,如在NumPy的UFuncs,但更灵活)
  • 切片,转化和重塑(与NumPy的票面)
  • 阵列推导
  • 部分和完全降低(倍)
  • 可选的可变性(可变阵列允许明确array-set!
  • 可选懒惰(数组是通过默认严格)
  • 可选分型(用于快速代码所需)

这对阵列原语。他们也碰巧和math/matrix一起打得很好。

> (require math/array math/matrix) 
> (define arr3d (array-reshape (list->array (range 1 19)) #[2 3 3])) 
> arr3d 
(array #[#[#[1 2 3] #[4 5 6] #[7 8 9]] #[#[10 11 12] #[13 14 15] #[16 17 18]]]) 
> (array-map * arr3d arr3d) 
(array 
#[#[#[1 4 9] 
    #[16 25 36] 
    #[49 64 81]] 
    #[#[100 121 144] 
    #[169 196 225] 
    #[256 289 324]]]) 
> (define m (array-slice-ref arr3d (list 1 ::...))) 
> m 
(array #[#[10 11 12] #[13 14 15] #[16 17 18]]) 
> (array-shape m) 
'#(3 3) 
> (matrix-trace m) 
42 

math/array似乎是一个很好的理由重新考虑 方案 球拍实际任务。