How do we pass two lists as the arguments of a function in Scheme? - scheme

How do we pass two lists as the arguments in defining a function? I mean the two lists are arbitary, and "a real list" will be pass as the parameters during the function execution..
Is it something like
(define checklist
(lambda (list1 list2)
(or (null? list1) (null? list2))
#and my other work here))
or
(define (checklist list1 list2)
(or (null? list1) (null? list2))
#and my other work here)
or
(define checklist
(lambda list1 list2)
(or (null? list1) (null? list2))
#and my other work here)
? I am sorry if its too basic.I've tried these but when I passed 2 lists to run the function,I got "wrong number of arguments passed" error.Thank you!

The third makes a rest argument list1 and returns the value of the global variable list2 or an error if it doesn't exist. But giving 3+ expressions to define is not legal so the third won't be accepted.
Since (define (checklist l1 l2) ...) is just fancy way of writing (define checklist (lambda (1 2) ...)) the two first examples are the exact same.
Note that (or x y z) will evaluate to the first true value and if you have expressions after it becomes dead code. If you were expecting to do something if or if not (or x y z) were true or not you need to use a conditional like (if (or x y z) something-expression something-else-expression)

Related

Scheme: how to get first atom from list

I need help with one issue: I can't handle how to get the first atom from the list in SCHEME language. I think I should make a loop, something like "while" and compare each element on boolean (?atom) and print first matched item.
Unfortunately, It's difficult for me to handle scheme syntax.
Please, can you propose any solution for me?
define func ?atom:
(define (atom? x) (not (or (pair? x) (null? x))))
Recursion is not that different from the usual way yo solve problems - you just have to be careful and set some meaningful base cases. For instance, how would you solve this problem in Java? by traversing all the list, and stoping when either 1) we found the element that matches the condition or 2) there are no more elements. This is exactly what we need to do:
(define (first-atom lst)
(cond ((null? lst) #f) ; there are no more elements in the list
((atom? (car lst)) ; current element is an atom
(car lst)) ; return it
(else ; otherwise
(first-atom (cdr lst))))) ; look in the rest of the list
It works as expected:
(first-atom '((2) 42 (3)))
=> 42
(first-atom '((1) (2)(3)))
=> #f
In your question you have the definition to atom? that returns #t if the argument is an atom and #f otherwise.
The function should handle the empty list. eg. What should happen when you do this:
(first-atom '())
Thus you need to check if the argument is the empty list and return whatever you supposed to return when there are no atoms in the arguments. Then you'll have a else expression that handles the rest.
You can use first to get the first element to check if it is an atom and then return it or you recure with the rest of the list.
Now here is something very similar that finds the number of elements in a list:
(define (length lst)
(if (null? lst)
0 ; obviously a 0 length list
(+ 1 (length (cdr lst))))) ; obviously one plus whatever length the rest is
Imagine what happens if you do (length '(1 2)). It does (+ 1 (length '(2))) which again does (+ 1 (+ 1 (length '()))) which again does (+ 1 (+ 1 0)). Simple as that. All loops are recursive functions in Scheme.
You reference to while indicates you might be familiar with other programming languages. I knew C, C++, Pascal, perl, PHP, and Java when starting to learn Lisp and I suddenly realized all the languages I knew were only subtle dialects of one language, Algol. I wasn't learning my sixth language, but my second. Scheme doesn't have a while loop. It has recursion. you need to get a book and start at the first page as if you didn't know how to program at all as assimilation from Algol will point you in the wrong direction.

How to convert a list into its elements

This must be very easy to accomplish but I am new to racket and dont know how:
I have a list (1 2 3 4) and would like to convert it into (1)(2)(3)(4)
Or is there a way to build it as (1)(2)(3)(4). I am using
cons '(element) call-function
to build it inside a function (recursively)
Try this:
(map list '(1 2 3 4))
From your text, I see that you do '(element). Problem with that is that everything which is quoted is never anything but what you see. Thus if element happens to be a variable it won't be expanded because of the quote.
The right way to get a list with one element would be to use list. eg. (list element) to get whatever the variable element to be the one element in your list. However, you won't need this in a roll-your-own recursive procedure:
(define (listify lst)
(if (null? lst) ; if lst is null we are done
'() ; evaluate to the empty list
(cons (list (car lst)) ; else we make a list with the first element
(listify (cdr lst))))) ; and listify the rest of the list too
Most of the procedure now is facilitating going through the argument, but since it's a common thing to do we can use higher order procedures with foldr so that you only concentrating on what is going to happen with the element in this chain in correspondence with the rest of the process:
(define (listify lst)
(foldr (lambda (e acc)
(cons (list e) ; chain this element wrapped in a list
acc)) ; with the result from the rest of the list
'() ; initiate with an empty list
lst)) ; go through lst
Of course, since we do something with each element in a list and nothing fancy by using map we only need to supply what to do with each element rather telling how to join the chains in the list together as well.
(define (listify lst)
(map list lst)) ; make a new list by applying a list of each element
It's actually a single argument version of zip:
(require srfi/1)
(zip '(1 2 3 4)) ; ==> ((1) (2) (3) (4))
(zip '(1 2 3) '(a b c)) ; ==> ((1 a) (2 b) (3 c))
There you go. As simple as it can get.

How can i get only one solution from filter map?

(filter-map (lambda (x y) (and (eq? x z) y) ) list1 list2 )
in scheme, i have two list list1 and list2, if any element of list1 equal to z, i want to return corresponding to list2 element. i know only one element on list1 equal to z.
My code is working but i get a result such that '(bla) but i want to only a result such that bla how can i remove this parentheses?
You can use car to retrieve the first element in the output list, but I don't think filter-map is the best option here - after all you're not interested in the list of results returned by filter-map, only in a single element - and this is unavoidable, a list will be returned even if it's empty. Basically, you need to look for a value in an association list. Try this instead:
(cdr (assq 'z (map cons list1 list2)))
=> 'bla
Explanation:
(map cons list1 list2) builds an association list, where the elements in list1 are the keys and the elements in list2 are the values
assq looks for the key-value pair that has 'z as its key (using eq? for the comparisons), and returns that pair
cdr returns the value part of that pair
Alternatively, you can check if your interpreter has a hash table implementation available (useful if you have to efficiently perform more than one search), for instance in Racket:
(hash-ref (make-hasheq (map cons list1 list2)) 'z)
=> 'bla
Explanation:
(map cons list1 list2) builds an association list, where the elements in list1 are the keys and the elements in list2 are the values
make-hasheq creates a new hash table using the association list, and uses eq? when finding a value given the key
hash-ref returns the value corresponding to the key 'z
Be aware that both of the above options will raise an error when we attempt to obtain the value if the key wasn't present in list1, you have to decide how to handle this case if the need arises; for example we can return #f:
(let ((pair (assq 'z (map cons list1 list2))))
(and pair (cdr pair)))
(hash-ref (make-hasheq (map cons list1 list2)) 'z
(const #f))
The naive approach would be to call car on the result, since car returns the first element of a list. But that would cause an error if no element matches - your function would return an empty list, and car will fail.
Some languages (i.e. Haskell) implement an option type. An option type is either empty or contains exactly one value. It's somewhat analogue to a list that can contains no more than one value. You can implement one for scheme and use it as the return type.
An alternative approach is to return the lists' first element, or #f (false) if no result was found. This approach is based on the fact that Scheme is a dynamic language.
While filter-map is nice and functional, an iterative answer might be the more straightforward (read: intelligible) way to approach this.
#lang racket
(define list1 '(a b z d))
(define list1a '(a b c d)) ; doesn't have 'z in it
(define list2 '(1 2 3 4))
(define (find-matching-pair lst1 lst2)
(let loop ((l1 lst1)
(l2 lst2))
(cond ((null? l1) #f) ; didn't find it
((eqv? (car l1) 'z) (car l2)) ; this ASSUMES l2 is not shorter than l1
(else (loop (cdr l1) (cdr l2))))))
(find-matching-pair list1 list2) ; => 3
(find-matching-pair list1a list2) ; => #f

Scheme,level intermediate student, find min without recursion

How can I write a function using abstract list functions (foldr, map, and filter) without recursion that consumes a list of numbers (list a1 a2 a3 ...) and produces a new list removing the minimum number from the original list?
The recursion code is:
(define (find-min lst)
(cond
[(empty? (rest lst)) (first lst)]
[else
(local [(define min-rest (find-min (rest lst)))]
(cond
[(< (first lst) min-rest) (first lst)]
[else min-rest]))]))
A fold applies a 2-argument function against a given value and the car of a list uses the result against the successive cars or the cdrs or the list. this is what we want.
Whereas map returns a new list by doing something with each element of a list.
And filter returns a smaller or equal list based on some predicate.
Now just to formulate a function that can choose the lessor of two arguments
(define (the-lessor x y)
(if (< x y)
x
y))
From there implementation is straightforward.
(define (min L) (fold the-lessor (car L) (cdr L)))
Since this looks like a homework question, I'm not going to provide all the code, but hopefully push you in the right direction.
From the HTDP book, we see that "The Intermediate Student language adds local bindings and higher-order functions." The trick here is probably going to using "local bindings".
Some assumptions:
(remove-min-from-list '()) => not allowed: input list must be non-empty
(remove-min-from-list '(1)) => '()
(remove-min-from-list '(1 2 3 1 2 3)) => '(2 3 2 3) ; all instances of 1 were removed
Somehow, we need to find the minimum value of the list. Call this function min-of-list. What are its inputs and outputs? It's input is a list of numbers and its output is a number. Of the abstract list functions, which ones allow us to turn a list of numbers into a number? (And not another list.) This looks like foldl/foldr to me.
(define (min-of-list lst)
(foldr some-function some-base lst))
Since you already showed that you could write min-of-list recursively, let's move on. See #WorBlux's answer for hints there.
How would we use this in our next function remove-min-from-list? What are the inputs and outputs of remove-min-from-list? It takes a list of numbers and returns a list of numbers. Okay, that looks like map or filter. However, the input list is potentially shorter than that output list, so filter and not map.
(define (remove-min-from-list lst)
....
(filter some-predicate list))
What does some-predicate look like? It needs to return #f for the minimum value of the list.
Let's pull this all together and use local to write one function:
(define (remove-min-from-list lst)
(local [(define min-value ...)
(define (should-stay-in-list? number) ...min-value ...)]
(filter should-stay-in-list? lst)))
The key here, is that the definition for should-stay-in-list? can refer to min-value because min-value came before it in the local definitions block and that the filter later on can use should-stay-in-list? because it is in the body of the local.
(define (comparator n) (local [(define (compare v) (not (equal? v n)))] compare))
(define (without-min list) (filter (comparator (foldr min (foldr max 0 list) list)) list))

Scheme: a good set function

I need to write a good set function that checks whether its argument lst is a properly represented set, i.e. it is a list consisting only of integers, with no duplicates, and returns true #t or false #f. For example:
(good-set? (1 5 2)) => #t
(good-set? ()) => #t
(good-set? (1 5 5)) => #f
(good-set? (1 (5) 2)) => #f
so I have began writing the function as:
(define (good-set? lst)
so I don't know how to proceed after this. Can anybody help?
One option would be to use andmap and sets, as has been suggested by #soegaard:
(define (good-set? lst) ; it's a good set if:
(and (andmap integer? lst) ; all its elements are integers and
(= (length lst) ; the list's length equals the size
(set-count (list->set lst))))) ; of a set with the same elements
But if you can't use sets or other advanced procedures, then traverse the list and test if the current element is an integer and is not present somewhere else in the list (use member for this), repeating this test for each element until there are no more elements in the list. Here's the general idea, fill-in the blanks:
(define (good-set? lst)
(cond (<???> ; if the list is empty
<???>) ; then it's a good set
((or <???> ; if the 1st element is not an integer or
<???>) ; the 1st element is in the rest of the list
<???>) ; then it's NOT a good set
(else ; otherwise
(good-set? <???>)))) ; advance recursion
Sets are built into the Racket standard library: I would recommend not reimplementing them in terms of lists unless you really need to do something customized.
If we need to treat this as a homework assignment, I would recommend using a design methodology to systematically attack this problem. In this case, see something like How to Design Programs with regards to designing functions that work on lists. As a brief sketch, we'd systematically figure out:
What's the structure of the data I'm working with?
What tests cases do I consider? (including the base case)
What's the overall shape of the function?
What's the meaning of the natural recursion?
How do I combine the result of the natural recursion in order to compute a solution to the total?
For this, check if the first number is duplicated, if it is not, then recurse by checking the rest. As such:
(define (good-set? list)
(or (null? list) ; nothing left, good!
(let ((head (car list)))
(rest (cdr list)))
(and (number? head) ; a number
(not (member = head rest)) ; not in the rest
(good-set? rest))))) ; check the rest
If you need member, then
(define (member pred item list)
(and (not (null? list))
(or (pred item (car list))
(member pred item (cdr list)))))

Resources