Procedure? keyword in scheme - functional-programming

I am new to functional programming and I have a piece of code like the following:
(procedure? (car (list cdr)))
Value: #t
I do not understand why this returns true. cdr is a procedure, but what is the car of the list cdr? I do not understand. Can anyone explain?
Thanks

list turns its contents into a list. So (list cdr) is just a list of the element cdr, which itself is a procedure. car gets the first element of a list. So (car (list x)) == x for any x.
This simplifies our problem to (procedure? cdr). Since cdr is clearly a procedure, this returns true.

Related

Why mutating the list to be only its first element with this approach does not work in Common Lisp?

I am trying to learn Common Lisp with the book Common Lisp: A gentle introduction to Symbolic Computation. In addition, I am using SBCL, Emacs, and Slime.
By the end of chapter 10, on the advanced section there is this question:
10.9. Write a destructive function CHOP that shortens any non-NIL list to a list of one element. (CHOP '(FEE FIE FOE FUM)) should return
(FEE).
This is the answer-sheet solution:
(defun chop (x)
(if (consp x) (setf (cdr x) nil))
x)
I understand this solution. However, before checking out the official solution I tried:
(defun chop (xs)
(cond ((null xs) xs)
(t (setf xs (list (car xs))))))
Using this as a global variable for tests:
(defparameter teste-chop '(a b c d))
I tried on the REPL:
CL-USER> (chop teste-chop)
(A)
As you can see, the function returns the expected result.
Unfortunately, the side-effect to mutate the original list does not happen:
CL-USER> teste-chop
(A B C D)
Why it did not change?
Since I was setting the field (setf) of the whole list to be only its car wrapped as a new list, I was expecting the cdr of the original list to be vanished.
Apparently, the pointers are not automatically removed.
Since I have very strong gaps in low-level stuff (like pointers) I thought that some answer to this question could educate me on why this happens.
The point is about how parameters to functions are passed in Common Lisp. They are passed by value. This means that, when a function is called, all arguments are evaluated, and their values are assigned to new, local variables, the parameters of the function. So, consider your function:
(defun chop (xs)
(cond ((null xs) xs)
(t (setf xs (list (car xs))))))
When you call it with:
(chop teste-chop)
the value of teste-chop, that is the list (a b c d) is assigned to the function parameter xs. In the last line of the body of function, by using setf, you are assigning a new value, (list (car xs)) to xs, that is you are assigning the list (a) to this local variable.
Since this is the last expression of the function, such value is also returned by the function, so that the evaluation of (chop test-chop) returns the value (a).
In this process, as you can see, the special variable teste-chop is not concerned in any way, apart from calculating its value at the beginning of the evaluation of the function call. And for this reason its value is not changed.
Other forms of parameter passing are used in other languages, like for instance by name, so that the behaviour of function call could be different.
Note that instead, in the first function, with (setf (cdr x) nil) a data structure is modified, that is a part of a cons cell. Since the global variable is bound to that cell, also the global variable will appear modified (even if, in a certain sense, it is not modified, since it remains bound to the same cons cell).
As a final remark, in Common Lisp it is better not to modify constant data structures (like those obtained by evaluating '(a b c d)), since it could produce an undefined behaviour, depending on the implementation. So, if some structure should be modifiable, it should be built with the usual operators like cons or list (e.g. (list 'a 'b 'c 'd)).

Finding duplicate elements in a Scheme List using recursion

I'm trying to create a function that will check a list of numbers for duplicates and return either #t or #f. I can only use car, cdr and conditionals, no cons.
This is what I have so far but it's giving me the error "car: contract violation expected: pair? given: #f"
(define (dups a)
(if (null? a)
#f
(if (= (car a)(car(dups(cdr a))))
#t
(dups (cdr))
)
)
)
I'm new to both scheme and recursion, any help/advice would be greatly appreciated.
Your second if doesn't make much sense. I'm assuming you wanted to check whether (car a) appears somewhere further down the list, but (car (dups (cdr a))) doesn't give you that. Also, (car (dups ...)) is a type-issue since dups will return a boolean instead of a list, and car is expecting a list (or actually, a pair, which is what lists are composed of).
What you need is a second function to call in the test of that second if. That function takes an element and a list and searches for that element in the list. Of course, if you're allowed, use find, otherwise implement some sort of my-find - it's quite simple and similar to your dups function.

Reverse a list in scheme

I'm trying to reverse a list in scheme and I came up with to the following solution:
(define l (list 1 2 3 4))
(define (reverse lista)
(car (cons (reverse (cdr (cons 0 lista))) 0)))
(display (reverse l))
Although it works I don't really understand why it works.
In my head, it would evaluate to a series of nested cons until cons of () (which the cdr of a list with one element).
I guess I am not understanding the substitution model, could someone explain me why it works?
Obs:
It is supposed to work only in not nested lists.
Taken form SICP, exercise 2.18.
I know there are many similar questions, but as far as I saw, none presented
this solution.
Thank you
[As this happens quite often, I write the answer anyway]
Scheme implementations do have their builtin versions of reverse, map, append etc. as they are specified in RxRS (e.g. https://www.cs.indiana.edu/scheme-repository/R4RS/r4rs_8.html).
In the course of learning scheme (and actually any lisp dialect) it's really valuable to implement them anyway. The danger is, one's definition can collide with the built-in one (although e.g. scheme's define or lisp's label should shadow them). Therefore it's always worth to call this hand-made implementation with some other name, like "my-reverse", "my-append" etc. This way you will save yourself much confusion, like in the following:
(let ([append
(lambda (xs ys)
(if (null? xs)
ys
(cons (car xs) (append (cdr xs) ys))))])
(append '(hello) '(there!)))
-- this one seems to work, creating a false impression that "let" works the same as "letrec". But just change the name to "my-append" and it breaks, because at the moment of evaluating the lambda form, the symbol "my-append" is not yet bound to anything (unlike "append" which was defined as a builtin procedure).
Of course such let form will work in a language with dynamic scoping, but scheme is lexical (with the exception of "define"s), and the reason is referential transparency (but that's so far offtopic that I can only refer interested reader to one of the lambda papers http://repository.readscheme.org/ftp/papers/ai-lab-pubs/AIM-453.pdf).
This reads pretty much the same as the solutions in other languages:
if the list is empty, return an empty list. Otherwise ...
chop off the first element (CAR)
reverse the remainder of the list (CDR)
append (CONS) the first element to that reversal
return the result
Now ... given my understanding from LISP days, the code would look more like this:
(append (reverse (cdr lista)) (list (car lista)))
... which matches my description above.
There are several ways to do it. Here is another:
(define my-reverse
(lambda (lst)
(define helper
(lambda (lst result)
(if (null? lst)
result
(helper (cdr lst) (cons (car lst) result)))))
(helper lst '())))

Scheme Recursion Through Arguments

I'm brand new to Scheme, and this is a homework question, so please no outright answers.
Here is my question:
Write a recursive procedure (any? arg1 arg2 ...), where the argi's are
boolean values. any? returns #t if any of its arguments is #t, and #f
otherwise.
These are the constraints:
You may not use the built-in procedures map, apply, list->vector, or
vector->list in any procedure. Likewise, do not use a let expression
or an internal define expression in any procedure, unless the problem
says otherwise.
Here is the code I have:::
(define any?
(lambda args
(if (null? args)
#f
(if (equal? #t (car args))
#t
(any? (cdr args))))))
My problem seems to be that I am hitting an infinite loop on the last line (any? (cdr args)). I am not sure why that is happening. My professor said a hint was to write any? as an interface procedure, and write a helper that handles the list. I am not sure how that would help.
Any advice would be appreciated!
EDIT: I have added new code. I am still getting an infinite loop.
(define any?
(lambda args
(any-helper args)))
(define any-helper
(lambda (list)
(if (null? list)
#f
(if (equal? #t (car list))
#t
(any? (cdr list))))))
I thought by writing lambda args in my main function, I would be passing a list to my helper function. I'm not sure if that is actually happening. I am not sure how to ensure that I don't recurse over '() infinitely.
Consider the steps taken by the function application (any? #f). This leads to a recursive call to (any? '()). Next, it checks to see if the argument list in this call, '(()), is null? (which it isn't, since it is a list containing '()). (equal #t '(()) is also false, so it keeps recursing since you're calling it with the same number of arguments instead of reducing the size of the input in each recursive call.
Hey, this is my 100th answer!
When you have a symbol argument or a dotted list as prototype the last argument, in your case args, contains the rest of the given operands.
Imagine you evaluate (any? #f 5 6) then args would be (#f 5 6). Since first argument is #f you then call (any? '(5 6)) instead of (any? 5 6).
Usually you would make a named let or a local procedure to handle a one argument list so that your code actually would work, but since you are not allowed to you need to use apply to do this instead.
(apply any? '(#f 5 6)) is the same as (any? #f 5 6). You can think of apply as the opposite as dotted list/symbol prototype in a procedure definition.
PS: Your update using any-helper would work perfectly if you recurse with any-helper instead of any?.

Racket: Identifying tail recursion?

I wrote two different functions in racket to determine whether a list of numbers is ascending:
(define (ascending list)
(if (<= (length list) 1)
#t
(and (< (car list) (car (cdr list))) (ascending (cdr list)))))
(define (ascending-tail list)
(ascending-tail-helper #t list))
(define (ascending-tail-helper prevBool rest)
(if (<= (length rest) 1)
prevBool
(ascending-tail-helper (and prevBool (< (car rest) (car (cdr rest)))) (cdr rest))))
I had the hardest time determining whether or not the first ascending was tail recursive, so I rewrote it using what I believe to be tail recursion.
The reason why I retrospectively believe the first one to not be tail recursive is that I believe at each level of recursion, the function will be waiting for the second argument in the "and" statement to return before it can evaluate the boolean expression. Conversely, for ascending-tail-helper, I am able to evaluate the lesser than expression before I do my recursive call.
Is this correct, or did I make myself even more confused than before?
DrRacket can help you determine whether a call is in tail position or not. Click the "Syntax Check" button. Then move the mouse pointer to the left parenthesis of the expression in question. In your example I get this:
The purple arrow shows that the expression is in tail-position.
From the manual:
Tail Calls: Any sub-expression that is (syntactically) in
tail-position with respect to its enclosing context is annotated by
drawing a light purple arrow from the tail expression to its
surrounding expression.
You are correct, in the first version the recursive call returns to and, whereas in the second version the recursive call is a tail call.
However, and is a macro, and is generally expanded using if
(define (ascending list)
(if (<= (length list) 1)
#t
(if (< (car list) (car (cdr list)))
(ascending (cdr list))
#f)))
which is tail recursive.
One of the requirements for a function to be in tail position is that it's return value be usable as the return value of the parent function without modification or inspection. That is, the parent function should be able to return immediately, having evaluated the tail position statement.
On first appearance, your first function,inspects the return value of ascending. It seems that doesn't return ascending's value but, instead, a value derived from it. However, according to the relevant section of the R5RS spec, the final expression in an and statement is in tail position. (When I'm properly awake, I know this)
So you are wrong.
http://www.schemers.org/Documents/Standards/R5RS/HTML/r5rs-Z-H-6.html#%_sec_3.5
(Note: edited to correct my initial hasty answer).
Racket's documentation on tail positions says that the place to check what's in tail position and what's not is the documentation for the particular form:
Tail-position specifications provide a guarantee about the asymptotic space consumption of a computation. In general, the specification of tail positions goes with each syntactic form, like if.
Racket's docs on and say (emphasis added):
(and expr ...)
If no exprs are provided, then result is #t.
If a single expr is provided, then it is in tail position, so the
results of the and expression are the results of the expr.
Otherwise, the first expr is evaluated. If it produces #f, the result
of the and expression is #f. Otherwise, the result is the same as an
and expression with the remaining exprs in tail position with respect
to the original and form.

Resources