Why does my code freeze when I recurse with ellipses? - recursion

It does not look like it is recursing infinitely because I have a base case, and each recursion call takes a smaller list arg1.
#lang racket
(define a '("Hat" "Shoes"))
(define b '("Coat" "Hat"))
(define c '("Shirt" "Pants"))
(define-syntax func
(syntax-rules ()
((func arg1 arg2 ... n)
(if (or (empty? arg1) (empty? arg2) ...)
empty
(if (or (member (first arg1) arg2) ...)
(cons (string-append n "." (first arg1)) (func (rest arg1) arg2 ... n))
(cons (first arg1) (func (rest arg1) arg2 ... n))
)
)
)
)
)
(func a b c "prefix")

You define a macro func.
Then you use the macro: (func a b c "prefix").
When a macro is used, the macro expander looks up the definition and matches the use with the input pattern and uses the template to produce the expansion.
Here (func a b c "prefix") is matched with (func arg1 arg2 ... n).
So arg1 = a, arg2 = (b c), and n = "prefix".
Now the template is used. Inside the template I spot:
(func (rest arg1) arg2 ... n))
Let's fill in:
(func (rest a) b c "prefix"))
of course the rest of the template is also filled in.
Now since the output of the macro has a use of func the macro expander
now needs to expand the new use: (func (rest a) b c "prefix")).
The output of that expansion will contain (func (rest (rest a)) b c "prefix")) (and more). The macro expander now expands that expression and gets (func (rest (rest (rest a))) b c "prefix")).
The problem is not that func uses func, but that the size of the arguments to func doesn't decrease. It shows that one must be careful when writing recursive macros.

Don’t use a macro for this. Macros should be used for generating code, but there is no need to do that here. Be especially wary about using macros that expand to themselves—they will recursively expand! As soegaard has helpfully pointed out, in this case, your macro is infinitely expanding, producing an infinite amount of code. This is obviously very bad.
Remember that macros run at compile-time, not at runtime, so it is impossible for a macro’s expansion to depend on a runtime value. For that reason, your “base case” does not make sense in the context of macros: from the macro’s point of view, there is no point at which it will stop expanding.
What you want is a plain old variadic function. The syntax to do that in Racket/Scheme looks like this:
(define (f . args)
; do something with args
)
In the above example, args will be bound to a list containing all of the arguments provided to f. You can use this to implement func as a function. If you also want the more declarative pattern matching functionality that syntax-rules provides, you should take a look at match.

Related

Creating a function which takes any number of functions as arguments

I'm having trouble figuring out how to go about creating a function that can take a series of the same function as arguments with the last argument as an operand. For example:
(func sqrt sqrt sqrt 390625)
The call above should return 5 as (sqrt 390625) > (sqrt 625) > (sqrt 25) > 5
I'm having trouble figuring out the exact way I should write this as any way I have tried has given me errors or achieved an infinite loop.
This the code is have so far:
(define func
(lambda L
(cond ( (equal? (length L) 2) ((car L) (cadr L)) ) ;; If the list consists of only 2 elements, carry out the function (element 1) onto the operand (element 2)
( #t (apply (car L) (func (cdr L))) ) ;; otherwise, apply the function (1st element) onto the rest of the list
)
)
)
The first condition works, for example returning 5 if i call (func sqrt 25), however the recursive call is throwing errors.
I would appreciate any help with this.
The OP doesn't provide a definition for chain, so that part is unclear, but I think that a fundamental problem here is that there is no recursive call to func; further, apply isn't used in the right position.
Instead of using (equal (length L) 2) as a base case, it might be nicer to make recursive calls as long as the first element in the input is a procedure, or otherwise just return the element:
#lang racket
(define multi-call
(lambda args
(let ((arg (car args)))
(if (procedure? arg)
(arg (apply multi-call (cdr args)))
arg))))
Here, when arg is a procedure, then it is applied to the result of calling multi-call recursively on the remaining arguments. Note that multi-call takes an arbitrary number of arguments, wrapping them in the list args. The reduction step provides (cdr args), which is a list of the remaining arguments. This means that apply should be used to call multi-call on those remaining arguments because multi-call expects an arbitrary number of arguments, not a list of arguments.
multi-call.rkt> (multi-call sqrt sqrt sqrt 390625)
5

Check if lisp object ends in NIL

I am trying to write an fx in lisp to tell if an object ends in nil.
(setq isList (lambda (listOfValues)
(if (null listOfValues) t)
( funcall isList (cdr listOfValues) )
)
)
However, I am having trouble checking if its nil in all cases. In particular, cdr would fail at last elt if it is not a list. How can I resolve this?
Before we get closer to answer your actual question, a few things. First, use defun to define functions, not "set a variable to a lambda", it will make you happier down the line. Second, Common Lisp style would vale been one of values, list-of-values, or just list (that would indicate we knew it was a list, so I would probably just have gone with values here), not "listOfValues" (case is typically smashed, and neither "listofvalues" nor "LISTOFVALUES" are easy to read).
So, back to the code. A list is composed of cons cells, of either atoms or other cons cells. We have two test functions, either consp or atom that would be useful in this case. We know that if we're looking at a cons, we need to recurse on its cdr, otherwise we're at the last element and can just check if we're looking at nil.
(defun is-proper-list (values)
(if (consp values)
(is-proper-list (cdr values))
(null values))) ;; We could do this test as (eql nil) as well
It can be done faster with
(defun listp (l)
(tailp nil l))
(tailp nil ...) tests, whether nil is the end of a given object after cdr-ing to the end.
tailp is a very special function. So don't use it without understanding it.
(tailp '(b c) '(a b c)) is e.g. NOT T, because '(b c) is not the same object like the ( ... b c). But in this case, because NIL is '() and is unique in Lisp, any nil is object-identical. Therefore one can use tailp here for this specific test, whether a given list ends with NIL.
listp is a lisp-convention conform name for this.
(predicate functions returning booleans ending with p for predicate.
Since no - used in the name, attach p without - otherwise attach -p).
(tailp (cdr '(a b c)) '(a b c)) ;; NIL
;; because the two lists are not object-identical
(setq l '(a b c))
(tailp (cddr l) l) ;; T ;; object-identical

Variable Not A Number Error in Lisp (Which is not true)

I have a code which takes a list and returns all possible permutations by the parameter result.
But when I compile I have an error which says *** - =: (1+ INDEX) is not a number.
Is this message true or I messed up the code generally?
I am new to lisp I can looking for a fix and also open to suggestions from fucntional programmers.
;; Creates permutatiions of a given list and returns it via parameter
(defun create-permuations (source)
(setf result (list))
(create-permuations-helper source 0 '() result)
result)
(defmacro create-permuations-helper (source index cur result)
(if (= (list-length cur) index)
(cons cur result)
(loop for i from 0 to (list-length cur) do
(create-permuations-helper source (1+ index)
(append cur (list (nth i source))) result))))
99% of times when a compiler reports an error you can trust it to be true. Here Index is the list (1+ index), literally the 1+ symbol followed by the index symbol. This is so because you are using a macro, and macros operate on code.
In your macro, you do not return a form to be evaluated, you execute code during macro-expansion that depends on itself. That alone is an undefined behaviour. For example:
(defmacro a (x)
(if (plusp x)
(a (- x 1))
nil))
In the body of a, you want to expand code using a recursive call to itself. But the macro is not yet fully known and cannot be until the whole macro is defined.
Maybe the particular lisp implementation binds a to the macro function in body of the macro, which is a strange thing to do, or you evaluated the definition twice. The first time the compiler assumes a is an unknown function, then binds a to a macro, and the second time it tries to expand the macro.
Anyway macro are not supposed to be recursive.
In the example, since the macro does not evaluate its argument, the nested call to the macro is given the literal expression (- x 1), and not its actual value, which cannot be known anyway since x is unknown. You are crossing a level of abstraction here by trying to evaluate things at macroexpansion time.
But, macros can expand into code that refers to themselves.
(defmacro a (x)
(if (plusp x)
`(b (a ,(- x 1)))
nil))
Now, (a 2) expands into (b (a 1)), which itself macroexpands into (b (b (a 0))), and finally reaches a fixpoint which is (b (b nil)).
The difference is that the macro produces a piece of code and returns, which the compiler macroexpands again, whereas in the first example, the macro must already be expanded in the body of its own definition.
Possible implementation
One way to solve your problem is to define a local function that has access to a variable defined in your main function. Then, the local function can set it, and you do not need to pass a variable by reference (which is not possible to do):
(defun permut (list)
(let (result)
(labels ((recurse (stack list)
(if list
(dolist (x list)
(recurse (cons x stack)
(remove x list :count 1)))
(push stack result))))
(recurse nil list))
result))
Alternatively, you can split the process in two; first, define permut-helper, which is a higher-order function that takes a callback function; it generates permutations and calls the callback for each one:
(defun permut-helper (stack list callback)
(if list
(dolist (x list)
(permut-helper (cons x stack)
(remove x list :count 1)
callback))
(funcall callback stack)))
You call it with a function that pushes results into a list of permutations:
(defun permut (list)
(let (result)
(flet ((add-result (permutation)
(push permutation result)))
(permut-helper nil list #'add-result))
result))

Function with rest arguments calling a function with rest arguments

Let us suppose we have a function func1 :
(defun func1 (&rest values)
; (do something with values...)
(loop for i in values collect i))
Now, we have a function func2 which calls func1 :
(defun func2 (&rest values)
; (do something with values...)
(func1 ???))
What should I put instead of ??? to "copy" all the parameters of func2's values to func1's values ?
For instance, I would have the following behavior :
(func2 1 2 3 4) ; result is (1 2 3 4) and not ((1 2 3 4)).
In an earlier question I tried to do something like this :
(defun func2 (&rest values)
(macrolet ((my-macro (v)
`(list ,#v)))
(func1 (my-macro values))))
But the defun cannot get the value because it is not runtime. In this answer, he suggested that I use apply, but this function takes a &rest parameter too, so it doesn't solve my problem...
If possible, I would rather avoid to change the prototype of both functions, and the behavior of func1.
In common lisp, it has to be
(apply #'func1 values) ;; since `func1` has to be looked up in function namespace
remember, Clojure and Racket/Scheme are Lisp1, and common lisp is Lisp2.
Alternative solution (just for the sake)
I was asking myself, how to get it done without apply - just for the sake.
The problem with
`(func2 ,#values)
is, that if e.g.
(func2 (list 1 2 3) (list 4) 5)
is called, the values variable is ((1 2 3) (4) 5)
But when it is spliced into (func1 ,#values), what is created is
(func1 (1 2 3) (4) 5). But if we compare this with the func2 call,
it should be rather (func1 (list 1 2 3) (list 4) 5) which is perhaps not possible, because when (func2 (list 1 2 3) (list 4) 5) is called -
in the lisp manner - the arguments of func2 are each evaluated, before they enter the function body of func2, so we end up with values as a list of already evaluated arguments, namely ((1 2 3) (4) 5).
So somehow, concerning the arguments for func1 in the last expression, we are one evaluation-step offbeat.
But there is a solution with quote, that we manage to quote each of the arguments before giving it to func1 in the last expression, to "synchronize" the func1 function call - to let the arguments' evaluation pause for one round.
So my first aim was to generate a new values list inside the func2 body where each of the values list's argument is quoted (this is done in the let-binding).
And then at the end to splice this quoted-values list into the last expression: (func1 '(1 2 3) '(4) '5) which can be regarded as equivalent to (func1 (list 1 2 3) (list 4) 5) for this kind of problems / for this kind of calls.
This was achieved by this code:
(defun func2 (&rest vals)
(let ((quoted-values (loop for x in vals
collect `',x)))
; do sth with vals here - the func2 function -
(eval `(func1 ,#quoted-values))))
This is kind of a macro (it creates code btw. it organizes new code) but executed and created in run-time - not in pre-compile time. Using an eval we execute that generated code on the fly.
And like macroexpand-1, we can look at the result - the code - to which the func1 expression "expands", by removing eval around it - I call it func2-1:
(defun func2-1 (&rest vals)
(let ((quoted-values (loop for x in vals
collect `',x)))
; do sth with vals here - the func2 function -
`(func1 ,#quoted-values)))
And if we run it, it returns the last expression as code immediately before it is evluated in the func2 version:
(func2-1 (list 1 2 3) (list 4) 5)
;; (FUNC1 '(1 2 3) '(4) '5) ;; the returned code
;; the quoted arguments - like desired!
And this happens if we call it using func2 (so with evaluation of the func1 all:
(func2 (list 1 2 3) (list 4) 5)
;; ((1 2 3) (4) 5) ;; the result of (FUNC1 '(1 2 3) '(4) '5)
So I would say this is exactly what you desired!
lists vs. spread arguments
In Common Lisp it is good style to pass lists as lists and not as spread arguments:
(foo (list 1 2 3)) ; better interface
(foo 1 2 3) ; interface is not so good
The language has been defined in a way that efficient function calling can be used by a compiler and this means that the number of arguments which can be passed to a function is limited. There is a standard variable which will tell us how many arguments a particular implementation supports:
This is LispWorks on my Mac:
CL-USER 13 > call-arguments-limit
2047
Some implementations allow much larger number of arguments. But this number can be as low as 50 - for example ABCL, Common Lisp on the JVM, allows only 50 arguments.
Computing with argument lists
But sometimes we want the arguments as a list and then we can use the &rest parameter:
(lambda (&rest args)
(print args))
This is slightly in-efficient, since a list will be consed for the arguments. Usually Lisp tries to avoid to cons lists for arguments - they will be passed in registers or on the stack - if possible.
If we know that the argument list will not be used, then we can give the compiler a hint to use stack allocation - if possible:
(lambda (&rest args)
(declare (dynamic-extent args))
(reduce #'+ args))
In above function, the list of arguments can be deallocated when leaving the function - because the argument list is no longer used then.
If you want to pass these arguments to another function you can use FUNCALL and usually more useful APPLY:
(lambda (&rest args)
(funcall #'write (first args) (second args) (third args)))
or more useful:
(lambda (&rest args)
(apply #'write args))
One can also add additional arguments to APPLY before the list to apply:
CL-USER 19 > ((lambda (&rest args)
(apply #'write
(first args) ; the object
:case :downcase ; additional args
(rest args))
(values))
'(defun foo () 'bar)
:pretty t
:right-margin 15)
(defun foo ()
'bar)

(compose) in Common Lisp

We find this function builder to realize composition in P.Graham's "ANSI Common Lisp" (page 110).
The arguments are n>0 quoted function names. I don't understand it completely, so I'll quote the code here and specify my questions underneath it:
(defun compose (&rest fns)
(destructuring-bind (fn1 . rest) (reverse fns)
#'(lambda (&rest args)
(reduce #'(lambda (v f) (funcall f v))
rest
:initial-value (apply fn1 args)))))
The argument list to compose is reversed and unpacked, its (now first) element bound to 'fn1' and the rest to 'rest'.
The body of the outermost lambda is a reduce: (funcall fi (funcall fi-1 ... ) ), with operands in inverted order to restore the initial one.
1) What is the role of the outermost lambda expression? Namely, where does it get its 'args' from? Is it the data structure specified as the first argument of destructuring-bind?
2) Where does the innermost lambda take its two arguments from?
I mean I can appreciate what the code does but still the lexical scope is a bit of a mystery to me.
Looking forward to any and all comments!
Thanks in advance,
//Marco
It's probably easier if you consider first a couple of practical examples:
(defun compose1 (a)
(lambda (&rest args)
(apply a args)))
(defun compose2 (a b)
(lambda (&rest args)
(funcall a (apply b args))))
(defun compose3 (a b c)
(lambda (&rest args)
(funcall a (funcall b (apply c args)))))
So the outermost lambda is the return value: a function that takes any arguments, what it does with it is applying the last function and chaining all the others in reverse order on the result got from last function.
Note: compose1 could be defined more simply as (defun compose1 (a) a).
A somewhat equivalent but less efficient version could be
(defun compose (&rest functions)
(if (= (length functions) 1)
(car functions)
(lambda (&rest args)
(funcall (first functions)
(apply (apply #'compose (rest functions))
args)))))
1) The outermost lambda creates a closure for you, because the result of (combine ...) is a function that calulates the composition of other functions.
2) The innermost lambda gets ists argument from the function reduce. Reduce takes a function (the innermost lambda) of two arguments and applies it stepwise to a list, e.g.
(reduce #'- '(1 2 3 4)) is (- (- (- 1 2) 3) 4)

Resources