I want to write in OCaml style with common lisp.

Asked 2 years ago, Updated 2 years ago, 111 views

I'm a beginner at common lisp, but could someone tell me?

What should I do if I want CLISP to wrap recursive functions with the same function name, such as Ocaml? For example, reverse:

let rec reverse xsys=
    match xs with
    | [ ] - > ys
    | x::xs ->reverse xs (x::ys);;
let reverse xs = reverse xs [ ];

I tried writing a macro myself to solve this problem.

 (defconstant elset)

(defmacro defun* (sym bindings & body body)
  (let((temp(gensym))
        (rest(gensym)))
    `(setf(symbol-function',sym)
           (function)
            (lambda, bindings)
             (let((,temp(symbol-function',sym)))
               (flet((,sym(&rest,rest)
                        (apply, temp, rest))
                 ,@body)))))

(defun my-reverse(xsys)
  (cond((null xs)ys)
        (else
         (my-reverse(cdrxs)(cons(carxs)ys)))


(defun*my-reverse(xs)
  (my-reverse xs(list)))

However, when I try to evaluate this in SBCL, I get an error.

*(my-reverse'(123))

debugger invoked on a SB-INT:SIMPLE-PROGRAM-ERROR:
  invalid number of arguments: 2

Could you tell me the solution?

common-lisp

2022-09-30 19:13

4 Answers

Common Lisp has labels as the equivalent of letrec, so if you use them, you can use them. I can write almost as it is, so I don't think you need to write a macro for definition.

The following uses optima for pattern matching.

 (ql:quickload:optima)


;;; a
(defun rev(xs)
  (labels ((rev(xsys))
             (optima: match xs
               ('()ys)
               ((cons xs)(rev xs(cons xys)))))
    (revxs'()))


;;; b
(labels ((rev(xsys))
           (optima: match xs
             ('()ys)
             ((cons xs)(rev xs(cons xys)))))
  (defun rev(xs)
    (revxs'()))


(rev' (0 1 2 3 4 5 6 7 89)
;=>(987 6 5 4 3 2 10)

b is more similar in shape to the original program, but a is more optimistic for Common Lisp.

The reason why the original program doesn't work is that the global my-reverse function gives two arguments where only one argument is taken.

As for the defun* defined, why don't you check the basic structure of Common Lisp and the specifications of the functions you are using again?

Also, regarding the style issue,

 (defconstant elset)

Else will no longer be available as a constraint variable name (in the same package), so it is not good.

 (Defmacro myif (pred then & Optional else)
  ...)

You may end up writing macros like the one shown in and worrying about mysterious errors.

 (cond(...))
      (: else...); or ' else

I think it would be better to compromise on the rank of .


2022-09-30 19:13

Well, instead of wrapping recursive functions with the same function name, why don't you use the optional argument?

 (defun my-reverse(xs&options)
  (cond((null xs)ys)
        (t(my-reverse(cdrxs)(cons(carxs)ys)))))

(my-reverse'(123))
=>(321)


2022-09-30 19:13

Attempted to rewrite defun*.

I can't get rid of the feeling, but it's working for the time being.

 (defmacro defun+ (funsym bindings & body body)
  `(defun, funsym, bindings)
     (labels((,funsym,bindings,@body))
       ,(cons funsym bindings)))

(defmacro defun* (funsym bindings & body body)
  (let((temp(gensym))
        (fexist(fboundp funsym)))
    `(progn
       (when, fexist)
         (setf(symbol-function', temp)
               (symbol-function', funsym))
       (defun, funsym, bindings)
         (if, fexist)
             (flet((,funsym(&rest)
                      (apply#', temprest))
               (progn,@body))
             (progn,@body)))


(defun+my-reverse(xsys)
  (cond((null xs)ys)
        (: else
         (my-reverse(cdrxs)(cons(carxs)ys)))

(defun*my-reverse(xs)
    (my-reverse xs(list)))


2022-09-30 19:13

Regarding the defun* macro, I wrote the following:

 (defmacro defun* (sym bindings & body body)
  (let((my_pkg "MY-FUNCTIONS"))
    `(progn
       (or (find-package, my_pkg)
           (make-package, my_pkg:use'(common-lisp)))
       (setf(symbol-function)
              (intern(string',sym), my_pkg))
             (symbol-function',sym))
       (unintern',sym)
       (setf(symbol-function(intern(string',sym)))
             (lambda, bindings)
               (let((*package*(find-package, my_pkg)))
                 ,@body)))))

We have created a separate package (MY-FUNCTIONS) and saved the function bindings by creating a symbol with the same name as the original function.

 (defun my-reverse(xsys)
  (cond((null xs)ys)
        (t(my-reverse(cdrxs)(cons(carxs)ys)))))

(defun* my-reverse(xs) (my-reversexs'()))

(my-reverse' (1 2 3 4 5)
= > (54 3 21)

This defun* macro works with SBCL 1.0.50, but may not work with other Common Lisp processing systems.


2022-09-30 19:13

If you have any answers or tips


© 2024 OneMinuteCode. All rights reserved.