Scheme if structure - if-statement

It gives me this error for my if structure:
if: expected a question and two answers, but found 4 parts
However i am doing it according to the syntax.
(if (or (null? list1) (null? list2))
display(result-list)
(begin
(append result-list (list((car list1) list2)))
(inner ((cdr list1) list2 result-list)))
)
Could you please tell me where am i doing it wrong?

The second line should be (display result-list).
The way you wrote it, display is the then-part of the if, (result-list) is the else-part and the begin-block is the superfluous fourth part that your compiler/interpreter complains about.

Shouldn't this display(result-list) be (display result-list)? Remember, (call param1 param2) is the scheme syntax, call(param1 param2) is C.

Related

Scheme - list passed into function returning empty

I am trying to define a helper function that takes an integer and a list as parameters and produces cartesian product of the integer and the list.
I believe I have the logic figured out. But when I test my code and pass a list into the function, the function returns an empty list.
(define (helper element set)
(cond
((null? set) '())
(cons '(element (car set)) (helper element (cdr set)))
)
)
For example, when I run (helper 5 '(6 8 9)) it returns an empty list.
I can't figure out why, but I think it has something to do with passing an integer with a list as parameters but I can't find anything to confirm this.
You have the wrong syntax for cond. The format is
(cond (test1 then1)
(test2 then2)
...)
There is no special allowance that the last case doesn't need a test. So when you write
(cond
((null? set) '())
(cons '(element (car set))
(helper element (cdr set))))
your test is the symbol cons, and your then-expression is "evaluate '(element (car set)), throwing the result away, and then evaluate and return (helper element (cdr set))" (there is an implicit begin around the expressions in the then part of a cond). Thus, helper always just recurses down to an empty set eventually, and then returns it, making no changes to it.
What you meant to do instead was use something that's always true as your last test, and then use the cons form as the body. Traditionally else is used for this, although #t is also fine:
(define (helper element set)
(cond
((null? set) '())
(else (cons '(element (car set))
(helper element (cdr set))))))
You will then discover another problem, which is that you meant to construct a list containing the values referred to by element and (car set), not to quote that list. What is the difference between quote and list? will help you understand what's doing on there.
try this:
(define (helper element set)
(map (lambda(x) (cons element x)) set))

Scheme function to take a list and an atom as parameters and returns index of the first location where atom occurs

I'm very new to Scheme and am working on a problem defined as follows:
Write a scheme function find-loc which takes two parameters, a list lst and an atom atm, and returns the index of the first location where atm occurs in the list.
The location index is 1-relative. If atm does not occur in the list, the function returns n + 1, where n is the length of the list.
what I've got so far is:
(define (find-loc list atm)
(if (not(list? list))
0
(cond
((null? list)
1)
((eq? (car list)atm)
1))
(else (+ (find-loc (cdr list atm) 1) )))
I feel that I'm close but am a bit stuck. My main questions are as follows:
how do I define what the atom is?
why am I getting the following error? "define: expected only one expression for the function body, but found 1 extra part"
An atom is defined by this predicate:
(define (atom? x)
(and (not (null? x))
(not (pair? x))))
The error you're receiving is because the syntax of the if expression is incorrect - it must have two parts after the condition (consequent and alternative), and you wrote three. A few comments:
It's better to use a cond when testing for multiple conditions
Don't name a variable as list, it clashes with a built-in procedure of the same name
Better use equal? for testing equality, it's more general
We should use our new and shiny atom? predicate, as per the requirements - even though the null? check is redundant at this point
This is what I mean:
(define (find-loc lst atm)
(cond ((not (list? lst)) 0)
((null? lst) 1)
((and (atom? (car lst)) (equal? (car lst) atm)) 1)
(else (+ 1 (find-loc (cdr lst) atm)))))

Returning smallest item in a list in Scheme

Note: I am doing this for homework. I'm not looking for the algorithm to solve my problem, just trying to understand how Scheme works.
I'm new to scheme and trying to write a small program to find the smallest item in a list. The program is working in the since that it is finding the correct answer (so the logic is somewhat sound), but I only know this because an error is coming up that it's trying to treat my answer as a function and call it.
(DEFINE (startmin mylist)
(
(repeatmin (CAR mylist) (CDR mylist))
))
(DEFINE (repeatmin curmin mylist)
(
(IF (NULL? mylist) ;If the list is empty
;This is where I'm at a loss. I want a way for this value to be
;sent out once the list is empty
curmin ;return the current minimum
(IF (< curmin (CAR mylist)) ;if the current minimum is less than the head of the list
(repeatmin curmin (CDR mylist)) ;recurse with curmin
(repeatmin (CAR mylist) (CDR mylist)) ;otherwise recurse with the head of the list.
)
)
))
I'm really at a loss of how I get the value, once found, back out of the recursion as it keeps trying to treat the value as a function.
Your parentheses are off. If you write
((if ...))
it means that the result from if is a function that immediately should be called once the value is cmoputed. It seems like you are using parentheses as if they are blocks, like {} in C, but they are not. In fact (begin ...) is a block in Scheme. And of course a function, let and cond terms have implicit begin.. Thus
(define (func . args)
(begin
x
y))
Is the same as
(define (func . args)
x
y)
Also please format your code correctly. Indentation helps you read the code and the nesting. I really don't pay attention to the parentheses, just the position which is crucial. Choose an editor that does this for you. Eg. DrRacket is a nice one I use.

Checking equivalency of #t? (Scheme)

I have a functions that is called 'ordered'. Calling it with a list, it returns either #t or #f.
How could i check what the value it returns in an if statement outside of the function?
Right now i have:
(if (eqv? (ordered (car list)) '#t ))
Which doesn't really work..
How could i rewrite it?
Thanks!
To elaborate on Chris's answer, you don't have to check explicitly for #t equality. You can use the result of the procedure application directly in your if
(if (ordered (car list))
"ordered returned true"
"ordered returned non-true")
Or in cond
(cond [(ordered (car list)) "ordered returned true"]
[else "ordered returned non-true"])
Also, it's conventional to suffix your procedure's name with ? if it returns a boolean value
(define (ordered? list) ...)
That way, it's a little more readable and easy-to-understand in other parts of your code
(if (ordered? (car list)) ...)
(cond [(ordered? (car list)) ...]
[else ...])
You can always use
(if (ordered (car lst))
...)
In Scheme, the only false value is #f. Everything else is considered true.

removing elements from a list in Scheme

it's my first time posting and i have a doubt on scheme.
I have to remove all occurrences of an element from a list, passed both as an arguments,
when entering parameters like that:
]=> (rmobject '(1 2 3 5 0 2 3 5 3) 3)
I'm getting an error:
The object (3 5 3 2 3 6 3) is not applicable
I suppose it's because of the second lambda, that is not working properly but why?
(define (rmobject list1 obj)
(if (null? list1)
'()
(if (= obj (car list1))
((lambda (list1) (cdr list1)) list1)
((lambda (list1) (list1)) list1)))
(cons (car list1) (rmobject (cdr list1) obj)))
I rewrote the code and this works properly on removing the elements but the proper doesn't, and both are suppose the same. Thanks in advance
(define (rmobject list1 obj)
(if (null? list1)
'()
(if (= obj (car list1))
(rmobject (cdr list1) obj)
(cons (car list1) (rmobject (cdr list1) obj)))))
The first version in your code doesn't make much sense. Why use lambdas in this way? you're supposed to recursively call the same procedure being defined, not creating a one-shot anonymous procedure, that won't work for solving the problem at hand. And this part: (list1) is causing the error The object is not applicable: you're trying to invoke the list as if it were a procedure - because it's surrounded by parenthesis. Remember that in Scheme, a syntax such as this one: (foo) indicates that the foo procedure is to be called.
The second version of your code is fine, that's the simple way to implement a remove-all procedure. A bit of nitpicking, though: when you find yourself nesting ifs, it's a sure sign that a cond would be more appropriate. Also notice that it's a good idea to use equal? instead of =, in that way your procedure will work for more than just numbers:
(define (rmobject list1 obj)
(cond ((null? list1)
'())
((equal? obj (car list1))
(rmobject (cdr list1) obj))
(else
(cons (car list1)
(rmobject (cdr list1) obj)))))
For future reference: the procedure you're implementing it's generally included as part of the interpreter. For example, in Racket we have remove*, which uses equal? as the default procedure for testing equality:
(define (rmobject list1 obj)
(remove* (list obj) list1))
Also, you can use filter as in #Maxwell's answer. Another way to write it:
(define (rmobject list1 obj)
(filter (negate (curry equal? obj)) list1))
Anyway, this works:
(rmobject '(1 2 3 5 0 2 3 5 3) 3)
=> '(1 2 5 0 2 5)
The problem is that in the line ((lambda (list1) (list1)) list1))) you compose a function that accepts an argument (list1), which you then attempt to call as a function. Because the function is actually passed a list instead, the interpreter exits with an error.
As you discovered in your second attempt, composing functions via lambda is not necessary or even coherent using the algorithm you came up with. Even so, there are many techniques for this that are much simpler than the one you use in your second attempt. I will demonstrate one that actually does use lambda so you can see how it works. The alternative technique I am referring to relies on filter and works like so:
(define (rmobject list1 obj)
(filter (lambda (x) (not (equal? x obj))) list1))