Counting in Scheme without recursion? - list

So, I have a homework assignment that is asking me to make a function that counts the number of elements in a list without using recursion. (Which seems crazy to me, since Scheme is all about recursion from what I've learned so far, but that's a different discussion.) We're also not allowed to use the built-in length function.
I'm assuming this involves map somehow, but beyond that, I'm stuck, and everything I've googled for help offers a recursive solution (or uses !set, which the class hasn't taught us about and which I'm assuming is not the answer they're looking for).

If you take a rather fussy definition of recursion: a function is recursive iff it calls its own name, either directly or indirectly, then you can write things which are not 'recursive' in this very limited sense, by, really, noting that functions that don't have names can't be recursive (again: in this limited sense).
So you can start with this slightly odd function:
(λ (f)
(λ (l)
(if (null? l)
0
(+ 1 ((f f) (cdr l))))))
This is a function which takes another function, f as an argument and returns a function which takes a list as an argument and which:
if the list is empty will correctly compute its length;
if the list is not empty, then if (f f) is a function which will correctly compute the length of the cdr of the list, this function will compute the length of the whole list, by adding one to it.
So, wait: this function, if given another function which, when called with itself as an argument, will return a function which will compute the length of the rest of a list, will compute the length of a list. That means that this function itself is a candidate for this f function: when called with itself as an argument it should return a function which computes the length of a list. So, OK, we can wrap it up a bit to make this proposed length-computing function:
((λ (g)
(g g))
(λ (f)
(λ (l)
(if (null? l)
0
(+ 1 ((f f) (cdr l)))))))
Should be a function which computes the length of a list. And we can try it:
> (((λ (g)
(g g))
(λ (f)
(λ (l)
(if (null? l)
0
(+ 1 ((f f) (cdr l)))))))
'(1 2 3))
3
Well, it does seem to compute the length of the list. So we can, finally, give this thing a name to make it easier to call:
(define list-length
((λ (g)
(g g))
(λ (f)
(λ (l)
(if (null? l)
0
(+ 1 ((f f) (cdr l))))))))
And now
> (list-length '())
0
> (list-length '(a b c d))
4
OK.
So, conventionally, this is done by giving the thing that applies a function to itself a name: it's the U combinator:
(define U
(λ (f) (f f)))
And then we can rewrite list-length in terms of U:
(define list-length
(U (λ (f)
(λ (l)
(if (null? l)
0
(+ 1 ((U f) (cdr l))))))))
And the question is: is list-length recursive? Well, maybe?

Related

Recursion/Lists in Racket

I am trying to make the function remove-member, where I have a list of strings and I give one of the members of the string (i.e. "A") to the function, and it removes that member and returns the rest of the list without that member. At the moment I have created tests and started my function, but I am lost beyond that. I know recursion functions include the first member of the list and the rest of it, but how would I remove the first member of a string?
(define str (list->string (list 'A 'B 'C)))
(check-expect (remove-occurrences "A") (list 'B 'C))
(check-expect (remvove-occurrences '()) (list 'A 'B 'C))
(define (remove-occurrences r)
(cond
[(empty? r) str]
[(??? r)]))
To remove a single element from a list:
Is the list empty? If it is, we're done and the result is the empty list.
OK, it's not empty. Is the first element of the list the same as the element you want to remove? If it is then the result is the rest of the list.
OK, it's not empty, and the first element didn't match. So the answer is a list consisting of a cons of the first element and the result of removing the element from the rest of the list. Which you now know how to do.
Alternatively, to remove all occurrences of an element from a list:
Is the list empty? If it is, we're done and the result is the empty list.
OK, it's not empty. Is the first element of the list the same as the element you want to remove? If it is then the result is the the result of removing all occurrences of the element from rest of the list, which you know how do to now.
OK, it's not empty, and the first element didn't match. So the answer is a list consisting of a cons of the first element and the result of removing the element from the rest of the list. Which you now know how to do.
How these functions differ:
> (remove-one '(a b b c) 'b)
'(a b c)
> (remove-all '(a b b c) 'b)
'(a c)
Let's follow the data type.
This way we get the mundane tasks taken care of automatically for us, and get to focus our creative mental abilities on more interesting, less common aspects of our problem:
(define (list-p ad)
(cond
((null? ad) ; follow
#t)
((pair? ad)
(let ((a (car ad)) ; the
(d (cdr ad))) ; type!
(list-p d)))
(else #f)))
We can see this predicate as a constructor of Boolean values. Creating a list following the same example aka skeleton code is also easy:
(define (list-l ad)
(cond
((null? ad) ; return proper
(list)) ; type here, and
((pair? ad)
(let ((a (car ad))
(d (cdr ad)))
(list-l d))) ; here
(else #f)))
We've just followed the type's skeleton code, mended it in the few appropriate places, and got ourselves a working code which creates values of the proper type, all by itself!
But does it create any interesting value, fully using the supplied argument? Evidently, not. For that we must mend the recursive call:
(define (list-copy ad)
(cond
((null? ad)
(list))
((pair? ad)
(let ((a (car ad))
(d (cdr ad)))
(cons ... ; here
(list-copy d))
))
(else #f)))
Now you get to tweak this further, consing the first element of a pair conditionally, as required by your problem.
(note: null? could be called empty? in your dialect).

Why is my lisp function giving me this output?

I am writing a function that will take a list from a user and will flatten this list into one simplified list. The function seems to only return the first item on the list and not the rest? Any suggestions on why it is doing this?
Example:
> (flatten '(a () b (c d))
(a b c d)
This is what I have so far
(defun flatten (list)
(cond
((null list)t)
(list (first list) (rest list))
(t(append (flatten (first list))
(flatten (rest list)))
(t(cons (first list (flatten (rest list))))))))
The output it is giving
> (flatten '(a () b (c d)))
(NIL B (C D))
You are editing the original question with updated code, which makes it a moving target. Currently, your code is the following one, after I ask Emacs to indent it with M-q (lisp-mode):
(defun flatten (list)
(cond
((null list)t)
(list (first list) (rest list))
(t (append (flatten (first list))
(flatten (rest list)))
(t (cons (first list (flatten (rest list))))))))
;; ^^^ Something is not good, why is the clause indented?
Parentheses structure the code for the computer, whereas indentation is a way to print this structure for human readers. This redundancy allows you to detect problems in source code when one does not match the other. Here, the (t cons) is not a cond clause, it is nested inside the previous clause.
Second, as said in comments, cond will go to the first clause for which the test succeeds. If you wrote (cond (t X) ...), nothing in the ... part would change the meaning of the code, which always returns X. In your code, you test as follows:
(null list) tests whether list is eq to nil.
list does not test whether list is a list. There is a predicate named listp to detect that. When you put list alone like this, you are asking whether list is a generalized true value, which is necessarily true when you previously ruled out nil (the previous clause).
The default clause (t ...) has no way to be used, because the previous test cannot fail.
Here is a skeleton:
(defun flatten (form)
(cond
((null list) ...)
((consp list) ...)
(t ...)))
Instead of consp you could write listp, but note that by definition a list is either nil or a cons cell, so consp is a little more explicit and does not overlap with a test for nil. Note also that I always test against the type of form, which is a pattern that is often found. That's why you might prefer to use typecase.

Making list of functions in Scheme

I want to create a list of functions in Scheme. As I figured out it would be something like this
(define (sqr x) (* x x))
(define (dbl x) (* 2 x))
(define (add-5 x) (+ 5 x))
(define list-of-funs '(sqr dbl add-5))
but I wonder how I can call separate functions from the list. Is there a better way to define a list of functions and call them separately?
Yes, there is a better way. You should use list, rather than quoting:
(define list-of-funs (list sqr dbl add-5))
The reason for this is that '(sqr dbl add-5) produces a list of symbols, whereas (list sqr dbl add-5) produces a list of procedure objects. You can invoke procedure objects. You cannot invoke symbols.
You can access the functions individually, by using first, second, or third (from SRFI 1) to pick elements out of the list, e.g.,
((first list-of-funs) 49) ; => 7
Or else you might decide you want to map through them, or whatever. e.g.,
(define (square-double-and-add5 x)
(map (lambda (f) (f x)) list-of-funs))

What does (cons? list-name) do?

I was wondering what (cons? list-name) does. Does it just check that list-name is not a non-empty list? Is it just like the opposite of (empty? list-name)? If so, then is it not better to just say (empty? list-name) and then say else instead of cons?? For example:
(define (f list-name)
(cond
[(empty? list-name) empty]
[(cons? list-name) "do something]))
jozefg's answer is right in pointing out that (cons? x) is not the same as (not (empty? x)), in general, because there are things (e.g., numbers) that are neither cons cells nor the empty list.
However, your variable was list-name, so you may have some reason to expect that its value is, in fact a list. A list, in Scheme, is either:
the empty list; or
a cons cell whose car is the first element of a list and whose cdr is the rest of the list.
Because of this, if you're writing a function that requires a list be passed in, then it does make sense to simply check for the trivial case (the empty list) with empty?, and to assume, since you've required a list, that anything that doesn't match that case is a cons cell on which you can call cdr and cdr. This is because while
(cons? x) == (not (empty? x))
is not true of values in general, it is true for lists. That is, if you already know that lst is a list, then
(cons? lst) == (not (empty? lst))
is true. There are a number of functions that do the same thing when we're talking about lists and cons cells. E.g., empty? and null? do the same thing, but they signal a slightly different intent on the part of the programmer. Similarly, car and cdr do the same thing as first and rest, but car and cdr signal that you might be treating something as a pair of two things, whereas first and rest clearly signal the intent that you're working with a list.
Your code, since it seems to expect a list, should probably be the following, since, for a list, if it's not the empty list, it must be a cons.
(define (f lst)
(cond
[(empty? lst) empty]
[else "do something]))
More generally, the code you write should depend on what kind of input you expect. E.g., in the first case, it's fine to check for empty, and assume a cons otherwise, because you're expecting a list. In the second case, you have to check for all the different kinds of things you might see.
(define (frob-list lst)
(cond
[(empty? lst) empty] ; arg is ()
[else ...])) ; arg is (x . y)
(define (frob-object obj)
(cond
[(null? obj) ...] ; arg is ()
[(cons? obj) ...] ; arg is (x . y)
[(number? obj) ...] ; arg is r
... ; arg is ...
[else ...])) ; else ...
cons? checks whether the value is a cons cell, e.g., something that's (cons foo bar) for some foo and bar.
> (cons? 1)
#f
> (cons? '())
#f
> (cons? (list 1 2 3))
#t
> (cons? (cons 1 2))
#t
If (cons? a) is true, then it is safe to use car and cdr on a.
This isn't the opposite of empty? since empty? is true if and only if the argument is the empty list, so (empty? 1) == (cons? 1) == #f.
Sidenote: Please don't put PLEASE HELP!! or similar in your question titles, everyone here is happy to help, but it's a bit obnoxious to read. Just something to keep in mind in the future. Welcome to SO.

Why does my Scheme function return an error "application: not a procedure"?

I want to get the second value of '(a b c) and I don't want to use cadr.
I can get the right answer:
(car (cdr '(a b c)))
'b
But when I built the function:
(define test (lambda (list) (car (cdr (list)))))
(test '(a b c))
I get the following error:
. . application: not a procedure;
expected a procedure that can be applied to arguments
given: '(a b c)
arguments...: [none]
I really don't know what's this error means.
There are incorrect parentheses in your code, surrounding the list parameter - in Scheme this: (f) means "apply the f function with no arguments", so in your code this: (list) is trying to invoke the list parameter as if it were a function, which is not, raising an error.
Also notice that it's a bad idea to call list the parameter, there's already a built-in procedure with that name; that's why I renamed it to lst. This should fix it:
(define test
(lambda (lst)
(car (cdr lst))))
(test '(a b c))
=> b