В Lisp, сколько входных данных может на самом деле иметь функция +? - PullRequest
7 голосов
/ 02 апреля 2012

Я относительно новичок в Лиспе, и мне было интересно, действительно ли существует верхний предел для функции "+".

(Полагаю, это относится ко всем другим арифметическим функциям "-", "/" и т. Д.)

Ответы [ 5 ]

11 голосов
/ 02 апреля 2012

Да, есть верхний предел, но точный верхний предел зависит от реализации.Вы гарантированно сможете пройти не менее 50, но все зависит.Если вам нужно суммировать список, вам, вероятно, лучше использовать (reduce #'+ list), что даст вам гораздо лучшую масштабируемость, чем любой другой метод.

Common Lisp HyperSpec имеет еще несколькоinfo.

Когда дело доходит до диапазонов значений, есть два разных случая: числа с плавающей запятой и целые числа.Числа с плавающей точкой по своей природе ограничены, и реализация, которая изменилась с одиночных на двойные, удивила бы меня.С помощью целых и рациональных чисел CL плавно переходит между фиксированными и быстрыми значениями, поэтому ограничение является функцией доступного адресного пространства, доступного для реализации.Я подозреваю, что то же самое справедливо для комплексных чисел (комплексные целые и рациональные числа -> переходить к bignums, если необходимо; комплексные числа с плавающей точкой -> сигнализировать вне диапазона или возвращать Inf или NaN).

8 голосов
/ 02 апреля 2012

Common Lisp был определен таким образом, чтобы его можно было эффективно реализовать на самых разных аппаратных и программных системах. Примерами являются такие процессоры, как Motorola 68000/20/30/40, различные процессоры Intel x86, процессоры на основе стека Lisp Machine, процессоры DEC VAX, RISC, суперкомпьютеры, подобные тем, что принадлежат Cray. В 80-х годах было много конкурирующих семейств процессоров, включая процессоры, разработанные для выполнения кода на Лиспе. Сегодня у нас все еще есть несколько семейств процессоров (x86, x86-64, ARM, SPARC, POWER, PowerPC, ...).

Он также может быть скомпилирован в C, Scheme или другие языки программирования.

Он также может быть скомпилирован с виртуальными машинами, такими как CMUCL, CLISP или виртуальная машина JVM / Java (кажется, что виртуальная машина Java имеет ограничение в 254 аргумента).

Например, компилятор Common Lisp может компилировать код Lisp в простой C-код. Таким образом, было бы хорошо, если бы максимально возможное количество вызовов функций компилятора C могло быть использовано повторно. Особенно для упрощения вызова Lisp из C.

C / C ++ также имеет ограничения на это:

Максимальное количество параметров в объявлении функции

Выше приведены числа, такие как 127 (C) и 256 для C ++. Так что для компилятора Lisp to C это могут быть ограничения. В противном случае код Лисп не будет использовать вызов функции C.

Первый такой компилятор KCL (Kyoto Common Lisp, позже эта реализация превратилась в GCL / GNU Common Lisp и ECL / Embeddable Common Lisp) имел CALL-ARGUMENTS-LIMIT 64.

Например, 64-битная реализация LispWorks / Mac OS X имеет значение 2047 для CALL-ARGUMENTS-LIMIT.

CALL-ARGUMENTS-LIMIT должно быть не меньше 50.

Таким образом, в Common Lisp обработка списка и аргументы вызова не связаны. Если вы хотите обрабатывать списки, вы должны использовать инструменты обработки списков (LIST, MAPCAR, APPEND, REDUCE, ...). Common Lisp предоставляет механизм для доступа к аргументам в виде списка с использованием параметра &REST. Но этого, как правило, следует избегать, поскольку это может привести к накладным расходам на вызов функции, поскольку список аргументов должен быть обработан.

2 голосов
/ 07 января 2015

Это зависит от реализации. «Я бы предложил пользователям LISP потратить 5 минут на тестирование своей платформы».

Для Clojure

(defn find-max-n [n]
  (try 
    (eval (concat (list +) (take n (repeat 1))))
    (println "more than" n)
    ; return n if something goes wrong
    (catch Exception e n))
  (recur (* n 2)))


(find-max-n 1)

Не заканчивается, зависает на 8192, учитывая мои настройки.

more than 1
more than 2
more than 4
more than 8
more than 16
more than 32
more than 64
more than 128
more than 256
more than 512
more than 1024
more than 2048
more than 4096
more than 8192
2 голосов
/ 03 апреля 2012

Clojure предоставляет пример Lisp, где вы можете иметь бесконечное количество аргументов для функции, используя ленивые последовательности:

; infinite lazy sequence of natural numbers
(def naturals (iterate inc 1))

(take 10 naturals)
=> (1 2 3 4 5 6 7 8 9 10)

; add up all the natural numbers 
(apply + naturals)
=> ...... [doesn't terminate]

Конечно, не особенно полезно .....

0 голосов
/ 02 апреля 2012

Простой ответ, нет, хотя плохая реализация, использующая рекурсию, а не хвостовую рекурсию, будет иметь ограничение стека.

В зависимости от вашей реализации + может быть реализовано с использованием рекурсии или как прямой вызов функции.

Я не знаю Common Lisp достаточно хорошо, чтобы знать, какие требования он определяет, но большинство реализаций, если они используют рекурсию, будут использовать хвостовую рекурсию и избегать любых ограничений стека.

Вызов функции сможет получить доступ к аргументам в виде списка, поэтому количество аргументов, которые можно обработать, не ограничено.

РЕДАКТИРОВАТЬ: Поскольку кто-то на самом деле дал ссылку на Common Lisp, это, очевидно, должно быть лучшим ответом, но я бы подумал, что любая хорошая реализация автоматически применяет эквивалент (reduce #'+ arg-list), если предоставлено достаточное количество аргументов.

...