В Lisp сколько входных данных может иметь функция +?

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

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

5 ответов

Решение

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

Common Lisp HyperSpec имеет еще немного информации.

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

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 использовалось как можно больше. Особенно также, чтобы сделать вызов Лисп из Си проще.

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

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

Выше приведены числа, такие как 127 (C) и 256 для C++. Так что для компилятора Lisp to C это могут быть ограничения. В противном случае код Lisp не будет использовать вызов функции 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параметр. Но этого, как правило, следует избегать, поскольку это может привести к накладным расходам на вызов функции, поскольку список аргументов должен быть обработан.

Это зависит от реализации. "Я бы предложил пользователям 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

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]

Не особенно полезно, конечно.....

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

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

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

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

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

Другие вопросы по тегам