операция между двумя списками

В Common Lisp есть map, который позволяет вам делать такие вещи:

(map (lambda (x y) (/ x y)) (list 2 4 6 8 10 12) (list 1 2 3 4 5 6))

возвращение (2 2 2 2 2 2)

Однако сейчас я работаю в ACL2, и нет такого понятия, как map. Поэтому, на мой взгляд, единственный оставшийся у меня выбор - это выполнить рекурсию для вычисления того, что я хочу, если нет другого более простого и/или более эффективного способа сделать это.

... Это как раз мой вопрос. Есть ли лучший способ сделать это, чем создать рекурсивную функцию с именем что-то вроде divide-two-lists? Это просто похоже на то, что язык на основе lisp должен делать естественным образом, вместо того, чтобы вам приходилось создавать другую функцию специально только для него, поэтому я и спрашиваю.


person Yokhen    schedule 08.09.2013    source источник
comment
ACL2 ограничен тем, что не поддерживает многие типичные функции Lisp по своей конструкции, а функции более высокого порядка входят в число тех функций, которые были вырезаны.   -  person Rörd    schedule 09.09.2013


Ответы (3)


Вы могли бы довольно легко написать свою собственную карту. Из руководства по GNU Emacs:

(defun mapcar* (function &rest args)
  "Apply FUNCTION to successive cars of all ARGS.
          Return the list of results."
  ;; If no list is exhausted,
  (if (not (memq nil args))
      ;; apply function to cars.
      (cons (apply function (mapcar 'car args))
            (apply 'mapcar* function
                   ;; Recurse for rest of elements.
                   (mapcar 'cdr args)))))

(mapcar* 'cons '(a b c) '(1 2 3 4))
⇒ ((a . 1) (b . 2) (c . 3))

Я не знаком с acl2, поэтому вам, возможно, придется изменить некоторые функции (например, memq) или по-другому работать с аргументами apply или &rest, но это основная часть кода.

person zck    schedule 09.09.2013
comment
ACL2 — это ограниченная версия Common Lisp, в которой явно отсутствуют такие операторы, как funcall или apply (среди прочего), поэтому в ней невозможно то, что было бы легко сделать в других Lisp. (Я бы сказал, что на самом деле это не Лисп, хотя он использует синтаксис Лиспа.) - person Rörd; 09.09.2013
comment
Чтобы уточнить то, что я сказал в начале моего предыдущего комментария, это не просто ограниченная версия CL. Он также предоставляет функции, которых нет в CL. - person Rörd; 09.09.2013

ACL2 основан на логике первого порядка. В логике первого порядка такие утверждения, как

(определить (ПРА) (РА))

не разрешены, потому что R используется и как параметр, и как функция.

теоретически можно обойти это ограничение, буквально определив свой собственный язык в рамках логики первого порядка, которая включает конструкции для логики более высокого порядка. В противном случае вы правы, лучший вариант — определять что-то вроде списка «разделить на два» каждый раз, когда вы хотите использовать функцию карты.

Это утомительно, но именно так должен был использоваться ACL2.

person DanielV    schedule 15.09.2013

Это не совсем подходит для вашего вопроса, но это связано, и поэтому я упоминаю об этом на случай, если это поможет кому-то еще, кто смотрит на ваш вопрос.

Рассмотрим книгу "std/util/defprojection", в которой содержится макрос, позволяющий отображать функцию в списке.

person interestedparty333    schedule 21.07.2014