1

In common lisp there is map, which lets you do this kind of thing:

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

returning (2 2 2 2 2 2)

However now I am working at ACL2 and there is no such a thing as map. So in my mind the only choice left I have is doing recursion to calculate what I want, unless there is another simpler and/or more efficient way of doing it.

... Which is exactly my question. Is there a better way of doing it than to create a recursive function called something like divide-two-lists? It just feels like something that a lisp-based language should naturally do instead of having you to create another function specifically just for it, hence why I am asking.

Ren
  • 4,594
  • 9
  • 33
  • 61
  • ACL2 is restricted to not support many typical Lisp features by design, and higher-order functions are among those features that have been cut. – Rörd Sep 09 '13 at 09:48

3 Answers3

0

You could pretty easily write your own map. From the GNU Emacs guide:

(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))

I'm unfamiliar with acl2, so you might have to change some functions (e.g. memq), or deal differently with how apply or &rest arguments work, but this is the meat of the code.

zck
  • 2,712
  • 2
  • 25
  • 44
  • 1
    ACL2 is a restricted version of Common Lisp that's explicitly missing operators like `funcall` or `apply` (among other things), so things that would be easy in other Lisps are not possible in it. (I would argue that it's not really a Lisp, even though it uses Lisp syntax.) – Rörd Sep 09 '13 at 09:44
  • To clarify what I said at the beginning of my previous comment, it's not just a restricted version of CL. It does also provide features that CL doesn't. – Rörd Sep 09 '13 at 09:51
0

ACL2 is based on first order logic. In first order logic, statements like

(define (P R A) (R A))

are not allowed because R is being used as both a parameter and a function.

It is theoretically possible to get around this limitation by literally defining your own language within first order logic that includes the constructs for higher order logic. Otherwise, you are correct, your best option is to define something like divide-two-lists every single time you want to use a map function.

That's tedious, but it is how ACL2 was meant to be used.

DanielV
  • 643
  • 4
  • 14
0

This isn't exactly suitable to your question, but it's related, and so I mention it in case it helps someone else who is looking at your question.

Consider the book "std/util/defprojection", which provides a macro that lets you map a function across a list.

interestedparty333
  • 2,386
  • 1
  • 21
  • 35