I would like to define a general function along the lines of:
(define (gen-func other-func)
(other-func))
that will execute the function passed to it. But, I want to be able to pass parameters with other-func.
So if I had:
(define (add-test a b c d)
(+ a b c d))
and
(define (divide-test a b)
(/ a b))
then I could do
(gen-func divide-test 3 4)
and
(gen-func add-test 1 2 3 4)
but it would actually do what I want (which is execute the function with passing along the arbitrary number of arguments). This is part of my process of learning Racket.
What you are looking for is apply and rest arguments:
(define (gen-func func . args)
(apply func args))
The dotted parameter list func . args results in all args after the first one being collected into the list args. The reason that this works is that (func . args) is the same as (cons func args), so when the function is called, func is set to (car arglist), and args are set to (cdr arglist) which is the list of arguments after the first one.
Related
I'm new to Racket, and am struggling to find the right words to explain what I'm trying to do. The best I can come up with is this: How do I use the value of an argument as a symbol, without calling the function which has the same name as the value of the argument, and without just quoting the name of the argument?
Here is a minimal example to show this.
There is a function called ul which does something.
There is another function called make-list which has a single parameter, list-type.
There is a third function, make-ul, which calls make-list with an argument ul.
In the true branch, the function ul is applied. Good so far.
In the false branch, I want to be able to use the value of the argument, which in this case is 'ul, as a symbol. In effect, this line of code would run (λ args (list* 'ul args)). How do I achieve this?
#lang racket
(define (ul . xs) `(div ,#xs))
(define (make-list list-type)
(if (equal? 'something 'something-else)
(λ args (apply list-type args)) ; true branch: call the function "ul"
(λ args (list* list-type args)))) ; false branch: how to use `ul without calling the "ul" function?
(define make-ul (make-list ul))
If your goal is to write good Racket code, then the best answer is don't.
Add a separate argument to take the symbol, like this:
;; make-list : Procedure Symbol -> Any ... -> Any
(define (make-list proc tag-sym)
(if ....
proc ;; (λ args (apply proc args)) simplifies to just proc
(λ args (list* tag-sym args))))
(define make-ul (make-list ul 'ul))
Or if the branch is independent of args, you could just have a single argument of type (U Procedure Symbol) instead:
;; make-list : (U Procedure Symbol) -> Any ... -> Any
(define (make-list list-type)
(cond [(procedure? list-type)
;; (λ args (apply list-type args))
list-type]
[(symbol? list-type)
(λ args (list* list-type args))]))
(define make-ul (make-list ul))
(define make-li (make-list 'li))
If you want to explore Racket features, there are two main ways to do it.
You can make a macro that takes a procedure name and uses it both as a reference and quotes it as a symbol. For example, using the first version of make-list above:
(define-syntax-rule (make-list* proc-name) (make-list proc-name (quote proc-name)))
(define make-ul (make-list* ul)) ;; => (define make-ul (make-list ul 'ul))
You can call object-name on a procedure to ask what Racket thinks its name is. For example, (object-name list) returns 'list, and (object-name ul) should return 'ul. But (object-name make-ul) will not return 'make-ul, because Racket tracks names at compile time, not at run time. (I would advise against writing code that depends on object-name; it makes your code very fragile.)
I am new to lisp and I have a problem, I'm trying to find the number in the list but it is not working. I haven't made the return statement yet
(defun num (x 'y)
(if (member x '(y)) 't nil))
(write (num 10 '(5 10 15 20)))
My output just outputs the nil instead of doing the function and I'm confused of what I am doing wrong.
Solution
(defun member-p (element list)
"Return T if the object is present in the list"
(not (null (member element list))))
The not/null pattern is equivalent to (if (member element list) t nil) but is more common.
In fact, you do not really need this separate function,
member is good enough.
The -p suffix stands for predicate, cf. integerp and upper-case-p.
Your code
You cannot quote lambda list elements, so you need to replace defun num (x 'y) with defun num (x y)
You need not quote t
Quoting '(y) makes no sense, replace it with y.
You do not need to write the function call, the REPL will do it for you.
See also
When to use ' (or quote) in Lisp?
Can you program without REPL on Lisp?
You are almost certainly expected to not just use member, but to write a function which does what you need (obviously in real life you would just use member because that's what it's for).
So. To know if an object is in a list:
if the list is empty it's not;
if the head of the list is equal to the object it is;
otherwise it is in the list if it's in the tail of the list.
And you turn this into a function very straightforwardly:
(defun num-in-list-p (n l)
;; is N in L: N is assumed to be a number, L a list of numbers
(cond ((null l)
nil)
((= n (first l))
t)
(t
(num-in-list-p n (rest l)))))
You could use the built in position function which will return the index of the number if it is in the list:
(position 1 '(5 4 3 2 1))
If you want to define your own function:
CL-USER> (defun our-member(obj lst)
(if(zerop (length lst))
nil
(if(equal(car lst)obj)
T
(our-member obj (cdr lst)))))
OUR-MEMBER
CL-USER> (our-member 1 '(5 4 3 2 1))
T
CL-USER> (our-member 99 '(1 2 3 4 5))
NIL
We can create a function called "our-member" that will take an object (in your case a number) and a list (in your case a list of numbers) as an argument. In this situation our "base-case" will be whether or not the length of the list is equal to zero. If it is and we still haven't found a match, we will return nil. Otherwise, we will check to see if the car of the list (the first element in the list) is equal to the obj that we passed. If so, we will return T (true). However, if it is not, we will call the function again passing the object and the cdr of the list (everything after the car of the list) to the function again, until there are no items left within the list. As you can see, The first example of a call to this function returns T, and the second example call returns NIL.
What makes this utility function a good example is that it essentially shows you the under workings of the member function as well and what is going on inside.
I am a novice in Lisp, learning slowly at spare time... Months ago, I was puzzled by the error report from a Lisp REPL that the following expression does not work:
((if (> 2 1) + -) 1 2)
By looking around then I knew that Lisp is not Scheme...in Lisp, I need to do either:
(funcall (if (> 2 1) '+ '-) 2 1), or
(funcall (if (> 2 1) #'+ #'-) 2 1)
I also took a glimpse of introductary material about lisp-1 and lisp-2, although I was not able to absort the whole stuff there...in any case, I knew that quote prevents evaluation, as an exception to the evaluation rule.
Recently I am reading something about reduce...and then as an exercise, I wanted to write my own version of reduce. Although I managed to get it work (at least it seems working), I realized that I still cannot exactly explain why, in the body of defun, that some places funcall is needed, and at some places not.
The following is myreduce in elisp:
(defun myreduce (fn v lst)
(cond ((null lst) v)
((atom lst) (funcall fn v lst))
(t (funcall fn (car lst) (myreduce fn v (cdr lst))))))
(myreduce '+ 0 '(1 2 3 4))
My questions are about the 3rd and 4th lines:
The 3rd line: why I need funcall? why not just (fn v lst)? My "argument" is that in (fn v lst), fn is the first element in the list, so lisp may be able to use this position information to treat it as a function...but it's not. So certainly I missed something here.
The 4th line in the recursive call of myreduce: what kind of fn be passed to the recursive call to myreduce? '+ or +, or something else?
I guess there should be something very fundamental I am not aware of...I wanted to know, when I call myreduce as shown in the 6th/last line, what is exactly happening afterwards (at least on how the '+ is passed around), and is there a way to trace that in any REPL environment?
Thanks a lot,
/bruin
Common Lisp is a LISP-2 and has two namespaces. One for functions and one for variables. Arguments are bound in the variable namespace so fn does not exist in the function namespace.
(fn arg) ; call what fn is in the function namespace
(funcall fn ...) ; call a function referenced as a variable
'+ is a symbol and funcall and apply will look it up in the global function namespace when it sees it's a symbol instead of a function object. #'+ is an abbreviation for (function +) which resolves the function from the local function namespace. With lots of calls #'+ is faster than '+ since '+ needs a lookup. Both symbol and a function can be passed as fn to myreduce and whatever was passed is the same that gets passed in line 4.
(myreduce '+ 0 '(1 2 3 4)) ; here funcall might lookup what '+ is every time (CLISP does it while SBLC caches it)
(myreduce #'+ 0 '(1 2 3 4)); here funcall will be given a function object looked up in the first call in all consecutive calls
Now if you pass '+ it will be evaluated to + and bound to fn.
In myreduce we pass fn in the recursion and it will be evaluated to + too.
For #'+ it evaluates to the function and bound to fn.
In myreduce we pass fn in the recursion and it will be evaluated to the function object fn was bound to in the variable namespace.
Common Lisp has construct to add to the function namespace. Eg.
(flet ((double (x) (+ x x))) ; make double in the function namespace
(double 10)) ; ==> 20
But you could have written it and used it on the variable namespace:
(let ((double #'(lambda (x) (+ x x)))) ; make double in the variable namespace
(funcall double 10))
Common Lisp has two (actually more than two) namespaces: one for variables and one for functions. This means that one name can mean different things depending on the context: it can be a variable and it can be a function name.
(let ((foo 42)) ; a variable FOO
(flet ((foo (n) (+ n 107))) ; a function FOO
(foo foo))) ; calling function FOO with the value of the variable FOO
Some examples how variables are defined:
(defun foo (n) ...) ; n is a variable
(let ((n 3)) ...) ; n is a variable
(defparameter *n* 41) ; *n* is a variable
So whenever a variable is defined and used, the name is in the variable namespace.
Functions are defined:
(defun foo (n) ...) ; FOO is a function
(flet ((foo (n) ...)) ...) ; FOO is a function
So whenever a function is defined and used, the name is in the function namespace.
Since the function itself is an object, you can have function being a variable value. If you want to call such a value, then you need to use FUNCALL or APPLY.
(let ((plus (function plus)))
(funcall plus 10 11))
Now why are things like they are? ;-)
two namespaces allow us to use names as variables which are already functions.
Example: in a Lisp-1 I can't write:
(defun list-me (list) (list list))
In Common Lisp there is no conflict for above code.
a separate function namespace makes compiled code a bit simpler:
In a call (foo 42) the name FOO can only be undefined or it is a function. Another alternative does not exist. So at runtime we never have to check the function value of FOO for actually being a function object. If FOO has a function value, then it must be a function object. The reason for that: it is not possible in Common Lisp to define a function with something other than a function.
In Scheme you can write:
(let ((list 42))
(list 1 2 3 list))
Above needs to be checked at some point and will result in an error, since LIST is 42, which is not a function.
In Common Lisp above code defines only a variable LIST, but the function LIST is still available.
I'm trying to implement the Towers of Hanoi.I'm not printing out anything between my recursive calls yet, but I keep getting an error saying
'('(LIST) 'NIL 'NIL) should be a lambda expression
I've read that the reason this happens is because of a problem with the parenthesis, however I cannot seem to find what my problem is. I think it's happening in the pass-list function when I am trying to call the hanoi function. My code:
(defun pass-list(list)
(hanoi('('(list)'()'())))
)
(defun hanoi ('('(1) '(2) '(3)))
(hanoi '('(cdr 1) '(cons(car 1) 2) '(3)))
(hanoi '('(cons(car 3)1) '(2)'(cdr 3)))
)
This code has many syntax problems; there are erroneous quotes all over the place, and it looks like you're trying to use numbers as variables, which will not work. The source of the particular error message that you mentioned comes from
(hanoi('('(list)'()'())))
First, understand that the quotes in 'x and '(a b c) are shorthand for the forms (quote x) and (quote (a b c)), and that (quote anything) is the syntax for getting anything, without anything being evaluated. So '(1 2 3) gives you the list (1 2 3), and '1 gives you 1. quote is just a symbol though, and can be present in other lists, so '('(list)'()'()) is the same as (quote ((quote (list)) (quote ()) (quote ()))) which evaluates to the list ((quote (list)) (quote ()) (quote ())). Since () can also be written nil (or NIL), this last is the same as ('(list) 'NIL 'NIL). In Common Lisp, function calls look like
(function arg1 arg2 ...)
where each argi is a form, and function is either a symbol (e.g., list, hanoi, car) or a list, in which case it must be a lambda expression, e.g., (lambda (x) (+ x x)). So, in your line
(hanoi('('(list)'()'())))
we have a function call. function is hanoi, and arg1 is ('('(list)'()'())). But how will this arg1 be evaluated? Well, it's a list, which means it's a function application. What's the function part? It's
'('(list)'()'())
which is the same as
'('(list 'NIL 'NIL))
But as I just said, the only kind of list that can be function is a lambda expression. This clearly isn't a lambda expression, so you get the error that you're seeing.
I can't be sure, but it looks like you were aiming for something like the following. The line marked with ** is sort of problematic, because you're calling hanoi with some arguments, and when it returns (if it ever returns; it seems to me like you'd recurse forever in this case), you don't do anything with the result. It's ignored, and then you go onto the third line.
(defun pass-list(list)
(hanoi (list list) '() '()))
(defun hanoi (a b c)
(hanoi (rest a) (cons (first a) b) c) ; **
(hanoi (cons (first c) a) b (rest c)))
If hanoi is supposed to take a single list as an argument, and that list is supposed to contain three lists (I'm not sure why you'd do it that way instead of having hanoi take just three arguments, but that's a different question, I suppose), it's easy enough to modify; just take an argument abc and extract the first, second, and third lists from it, and pass a single list to hanoi on the recursive call:
(defun hanoi (abc)
(let ((a (first abc))
(b (second abc))
(c (third abc)))
(hanoi (list (rest a) (cons (first a) b) c))
(hanoi (list (cons (first c) a) b (rest c)))))
I'd actually probably use destructuring-bind here to simplify getting a, b, and c out of abc:
(defun hanoi (abc)
(destructuring-bind (a b c) abc
(hanoi (list (rest a) (cons (first a) b) c))
(hanoi (list (cons (first c) a) b (rest c)))))
From the Question How do I pass a function as a parameter to in elisp? I know how to pass a function as a parameter to a function. But we need to go deeper...
Lame movie quotes aside, I want to have a function, which takes a function as a parameter and is able to call itself [again passing the function which it took as parameter]. Consider this snippet:
(defun dummy ()
(message "Dummy"))
(defun func1 (func)
(funcall func))
(defun func2 (func arg)
(message "arg = %s" arg)
(funcall func)
(func2 'func (- arg 1)))
Calling (func1 'dummy) yields the expected output:
Dummy
"Dummy"
Calling (func2 'dummy 4) results in an error message:
arg = 4
Dummy
arg = 3
funcall: Symbol's function definition is void: func
I had expected four calls to dummy, yet the second iteration of func2 seems to have lost its knowledge of the function passed to the first iteration (and passed on from there). Any help is much appreciated!
There probably is a better way to do this with lexical scoping. This is more or less a translation from Rosetta Code:
(defun closure (y)
`(lambda (&rest args) (apply (funcall ',y ',y) args)))
(defun Y (f)
((lambda (x) (funcall x x))
`(lambda (y) (funcall ',f (closure y)))))
(defun factorial (f)
`(lambda (n)
(if (zerop n) 1
(* n (funcall ,f (1- n))))))
(funcall (Y 'factorial) 5) ;; 120
Here's a link to Rosetta code: http://rosettacode.org/wiki/Y_combinator with a bunch of other languages immplementing the same thing. Y-combinator is a construct, from the family of fixed-point combinators. Roughly, the idea is to eliminate the need for implementing recursive functions (recursive functions require more sophistications when you think about how to make them compile / implement in the VM). Y-combinator solves this by allowing one to mechanically translate all functions into non-recursive form, while still allowing for recursion in general.
To be fair, the code above isn't very good, because it will create new functions on each recursive step. This is because until recently, Emacs Lisp didn't have lexical bindings (you couldn't have a function capture its lexical environment), in other words, when the Emacs Lisp function is used outside the scope it was declared, the values of the bound variables will be taken from the function's current scope. In the case above such bound variables are f in the Y function and y in the closure function. Luckily, those are just symbols designating an existing function, so it is possible to mimic that behaviour using macros.
Now, what Y-combinator does:
Captures the original function into variable f.
Returns a wrapper function of one argument, which will call f, when called in its turn, used by Y-combinator to
Return a wrapper function of unbounded number of arguments which will
call the original function passing it all the arguments it was called with.
This structure also dictates you the structure of the function to be used with Y-combinator: it has to take single argument, which must be a function (which is this same function again) and return a function (of any number of arguments) which calls the function inherited from outer scope.
Well, it is known to be a little mind-boggling :)
That's because you're trying to call the function func not the function dummy.
(Hence the error "Symbol's function definition is void: func".)
You want:
(func2 func (- arg 1)))
not:
(func2 'func (- arg 1)))
You do not need to quote func in the func2 call
You are missing a recursion termination condition in func2
Here is what works for me:
(defun func2 (func arg)
(message "arg = %s" arg)
(funcall func)
(when (plusp arg)
(func2 func (- arg 1))))