1

Consider the following function definition in Lisp:

(defun Fct(F L)
    (cond
        ((null L) nil)
        ((funcall F (car L)) (cons (funcall F (car L)) (Fct F (cdr L)) ) )
        (T nil)
    )
)

Give a solution to avoid the double call (funcall F (car L)).You wil not use set,setq,setf. Justify the answer.

This is how I redefined the function:

(defun Fct2(F L)
    (funcall #'(lambda (x)
                    (cond
                        ((null L) nil)
                        (x (cons x (Fct2 F (cdr L)) ) )
                        (T nil)
                    )
                )
        (F (car L))
    )
) 

I works, but I can't see if there is no more double call behind. Also I have seen someone who did it in another way:

(defun redefine(f l)
    (funcall #' (lambda (x)                    
                        (cond 
                            ((null l) nil)
                            (x (cons x (Fct f (cdr l))))
                            (t nil)
                        )                   
                )
                (funcall f (car l))
    )
)

(using the old Fct inside)

But I think that Fct2 is the good way to proceed. I'd like to hear some opinions.

Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • What you are doing with the lambda expression in `Fct2` [is equivalent to using a `let` form.](https://stackoverflow.com/a/49455384/6879826) – ad absurdum Jan 02 '21 at 21:27

1 Answers1

1

The function fct takes a function f and a list L as arguments and returns a list of ts for the elements of L which evaluate to a true value for f un
til either L is exhausted, or an element evaluates to false for F.

For example:

(fct #'plusp '(1 2 -3 4 10)) => (t t),
(fct #'listp '((1 2 3) 4 '(a))) => (t),
(fct #'listp nil) => nil.

The functions fct2 and redefine do not satisfy this behaviour.

In other to avoid evaluating an expression multiple times, simply bind the result of evaluating the expression to a symbol. Consider the following implementation which achieves the desired result:

(defun fct-2 (func list)
  (when list
    (let ((head (funcall func (car list))))
      (when head
        (cons head (fct-2 func (cdr list)))))))

The macro when is especially useful when you have an if form with no else part. In fct-2, we bind the result of (funcall func (car list)) to head which we use later.

Side notes:

  1. Commonlisp has separate name spaces for functions and variables so we can use names like list as variable names with no problems, this can lead to clearer programs instead of names like L for lists.
  2. Check out https://mumble.net/~campbell/scheme/style.txt and https://lisp-lang.org/style-guide/ for guides on writing and formatting (common)lisp programs.
Xero Smith
  • 1,968
  • 1
  • 14
  • 19