Диалекты Lispy с хорошей поддержкой программирования многомерных массивов - PullRequest
8 голосов
/ 15 июля 2011

Существуют ли какие-либо диалекты Лисп или схемы, которые хорошо поддерживают Массив и линейные алгебраические манипуляции. Под хорошей поддержкой я имею в виду не интерфейсы для BLAS / LAPACk, а эффективные массивы примитивов в самом языке. Я бы посчитал это эффективным, если бы он мог противостоять Нампи, скажем. Я слышал, что Сталин очень быстр, но я новичок в шутках и не знаком с синтаксически удобной манипуляцией и эффективным представлением многомерных массивов на таких языках. Указатели (без каламбура) будут высоко оценены, особенно если они поддерживаются личным опытом.

Ответы [ 3 ]

12 голосов
/ 15 июля 2011

Массивы в стандартном Common Lisp могут быть многомерными.

Словарь Array описывает доступные операции.

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 имеют некоторые необычные функции, такие как смещенные массивы.Они используют хранилище некоторого другого массива, но могут иметь разную размерную компоновку.

Иногда также полезно писать специальные макросы, которые скрывают шаблон использования массивов.Без этого кода на Лиспе с объявлениями типов многомерные массивы и LOOP могут быть немного большими.Пример типичного кода, в котором не используются специальные лингвистические абстракции:Общие компиляторы Lisp.Могут существовать исключения.

4 голосов
/ 15 июля 2011

Рассматривали ли вы Clojure с библиотекой Incanter ? Он имеет хорошую поддержку матриц и имеет очень качественный код для других вещей, таких как графики, математические функции, статистика и многое другое. Он также имеет хорошую поддержку встроенного параллелизма.

3 голосов
/ 11 апреля 2013

Racket (ранее PLT Scheme) недавно получила хорошие многомерные массивы (math/array) .Кажется, они вдохновлены Python NumPy и Data Parallel Haskell.Некоторые ключевые функции, которые вам могут понравиться:

  • истинная N-мерная гипер прямоугольная форма
  • широковещательная передача (точечная операция над одним или несколькими массивами, например UFuncs в NumPy, но более гибкая)
  • нарезка, преобразование и изменение формы (наравне с 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 кажется хорошей причиной для пересмотра Схемы Ракетки для практических заданий.

...