I am attempting to write my own simplified map procedure in R5RS. In short, it takes a procedure and two lists, and returns a list with the results of the procedure called on every pair of objects in the two argument lists, until either is empty.
This works fine for arithmetic operators, such as:
(map2-rec + '(1 2 3) '(1 2 3 4))
However, when I attempt to pass an anonymous lambda function (the return value of my both? procedure) which returns either #t or #f, this does not work.
(define (map2-rec proc items1 items2)
(if (or (null? items1) (null? items2))
'()
(cons (proc (car items1) (car items2))
(map2-rec proc (cdr items1) (cdr items2)))))
(define (both? proc)
(lambda (item1 item2)
((if (and (proc item1) (proc item2))
#t
#f))))
The specific error I am receiving in DrRacket is:
application: not a procedure;
expected a procedure that can be
applied to arguments
given: #t
arguments...: [none]
If someone could tell me how I can correct this error, I'd be very happy. I cannot understand why this code fails myself.
There's an extra (and erroneous) pair of parentheses in both?, surrounding the if expression. This should fix it:
(define (both? proc)
(lambda (item1 item2)
(if (and (proc item1) (proc item2))
#t
#f)))
Now your procedure works as expected:
(map2-rec + '(1 2 3) '(1 2 3 4))
=> '(2 4 6)
(map2-rec (both? even?) '(1 2 3) '(1 2 3 4))
=> '(#f #t #f)
Related
I want to apply or to every element of list, example:
(apply or '(#t #t #f)) expected result #t, but I'm getting error:
'#' to 'apply' has wrong type (kawa.lang.Macro) (expected: procedure, sequence, or other operator)
As I understand or is not a procedure.
Is there any procedure that can be used instead of or?
The easiest way to do this is with exists*. Whenever you would use (apply or some-list), you can use (exists values some-list). Or if you like, you can define a function that uses exists to do that:
#!r6rs
(import (rnrs base)
(rnrs lists))
(define (or* . lst)
(exists values lst))
values is the identity function, so (values x) is just x.
exists is a higher-order function defined so that (exists f (list x ...)) is equivalent to (or (f x) ...).
For example (exists values (list #t #t #f)) is equivalent to (or (values #t) (values #t) (values #f)), which is the same as (or #t #t #f).
Trying it out:
> (apply or* '(#t #t #f))
#t
> (apply or* '(#f #f #f))
#f
> (or* #t #t #f)
#t
> (or*)
#f
*exists is sometimes known as ormap or any
In SRFI-1 List Library you have every and any which basically is and and or for a procedure over a list.
#!r6rs
(import (rnrs base)
(only (srfi :1) every any)
(define num1-10 '(1 2 3 4 5 6 7 8 9 10))
(define odd1-9 '(1 3 5 7 9))
(every odd? num1-10) ; ==> #f
(any odd? num1-10) ; ==> #t
(every odd? odd1-9) ; ==> #t
For a list of booleans the procedure only need to return the argument. values returns it's argument and serve as identity:
(define booleans '(#f #t))
(every values booleans) ; ==> #f
(any values booleans) ; ==> #t
SRFI-1 is a safe choice as it is the list library of the upcoming R7RS Red edition. In many R5RS and R6RS implementations SRFI-1 is included and you can easily add it from the SRFI reference implementation if it isn't. In DrRacket's default language DrRacket, that has ormap and andmap, you can opt to use SRFI-1 instead by importing them with (require srfi/1).
You could define your own procedure that uses or
(define (orp . ls)
(if (null? ls) #f
(if (< (length ls) 2) (car ls) (or (car ls) (orp (cdr ls))))))
And use it:
(apply orp '(#t #f #t))
The main point is that or (and if, cond, and ....) operator has lazy evaluation semantics. Hence (or #t (/ 1 0)) does not make a division by zero. Because of that or cannot be an ordinary function.
You might code a lambda to force the eager evaluation, e.g. define your eager-or variadic function, and apply that.
I'm new to racket and trying to write a function that checks if a list is in strictly ascending order.
'( 1 2 3) would return true
'(1 1 2) would return false (repeats)
'(3 2 4) would return false
My code so far is:
Image of code
(define (ascending? 'list)
(if (or (empty? list) (= (length 'list) 1)) true
(if (> first (first (rest list))) false
(ascending? (rest list)))))
I'm trying to call ascending? recursively where my base case is that the list is empty or has only 1 element (then trivially ascending).
I keep getting an error message when I use check-expect that says "application: not a procedure."
I guess you want to implement a procedure from scratch, and Alexander's answer is spot-on. But in true functional programming style, you should try to reuse existing procedures to write the solution. This is what I mean:
(define (ascending? lst)
(apply < lst))
It's shorter, simpler and easier to understand. And it works as expected!
(ascending? '(1 2 3))
=> #t
(ascending? '(1 1 2))
=> #f
Some things to consider when writing functions:
Avoid using built in functions as variable names. For example, list is a built in procedure that returns a newly allocated list, so don't use it as an argument to your function, or as a variable. A common convention/alternative is to use lst as a variable name for lists, so you could have (define (ascending? lst) ...).
Don't quote your variable names. For example, you would have (define lst '(1 2 3 ...)) and not (define 'lst '(1 2 3 ...)).
If you have multiple conditions to test (ie. more than 2), it may be cleaner to use cond rather than nesting multiple if statements.
To fix your implementation of ascending? (after replacing 'list), note on line 3 where you have (> first (first (rest list))). Here you are comparing first with (first (rest list)), but what you really want is to compare (first lst) with (first (rest lst)), so it should be (>= (first lst) (first (rest lst))).
Here is a sample implementation:
(define (ascending? lst)
(cond
[(null? lst) #t]
[(null? (cdr lst)) #t]
[(>= (car lst) (cadr lst)) #f]
[else
(ascending? (cdr lst))]))
or if you want to use first/rest and true/false you can do:
(define (ascending? lst)
(cond
[(empty? lst) true]
[(empty? (rest lst)) true]
[(>= (first lst) (first (rest lst))) false]
[else
(ascending? (rest lst))]))
For example,
> (ascending? '(1 2 3))
#t
> (ascending? '(1 1 2))
#f
> (ascending? '(3 2 4))
#f
If you write down the properties of an ascending list in bullet form;
An ascending list is either
the empty list, or
a one-element list, or
a list where
the first element is smaller than the second element, and
the tail of the list is ascending
you can wind up with a pretty straight translation:
(define (ascending? ls)
(or (null? ls)
(null? (rest ls))
(and (< (first ls) (first (rest ls)))
(ascending? (rest ls)))))
This Scheme solution uses an explicitly recursive named let and memoization:
(define (ascending? xs)
(if (null? xs) #t ; Edge case: empty list
(let asc? ((x (car xs)) ; Named `let`
(xs' (cdr xs)) )
(if (null? xs') #t
(let ((x' (car xs'))) ; Memoization of `(car xs)`
(if (< x x')
(asc? x' (cdr xs')) ; Tail recursion
#f)))))) ; Short-circuit termination
(display
(ascending?
(list 1 1 2) )) ; `#f`
I'm trying to write my own function to reverse list in LISP. The problem is input
(revert '(2 3 (4 5 (6))))
My code looks like this:
(defun revert (l)
(if (null l)
nil
(append (revert (cdr l)) (list (car l)))))
It returns
((4 5 (6)) 3 2)
instead of this:
(((6) 5 4) 3 2)
How can I fix it to work correctly?
Since you want to reverse sublists as well, you have to use REVERT on the CAR as well as CDR:
(defun revert (l)
(if (null l)
nil
(append (revert (cdr l))
(list (revert (car l))))))
This however requires you to handle the possibility that L might be an atom, which should be returned as is. Since NIL is also an atom you can just change the condition to check for ATOM instead of NULL.
(defun revert (list)
(if (atom list)
list
(append (revert (cdr list))
(list (revert (car list))))))
(revert '(2 3 (4 5 (6))))
;=> (((6) 5 4) 3 2)
In Common Lisp, it's preferred to use full words for names, so it's better to name l list. You could also name the function something like tree-reverse.
I am trying to create a function (last) that takes an function ( f ) and a List as an parameter. The list is passed to the function (odd?) and if the last element in the list is odd it returns true(#t) else it returns false (#f) .But the following code is not working , what is the correct way to declare the function as an parameter .
(define (last f L)
(if (null? L) '() ( last f (cdr L)) ))
(last odd? '( 0 5 3 8 6 7))
Here'a how you can write a solution using just built-in functions, notice the correct syntax for passing a procedure as a parameter, and also be aware that it's a bad idea to name your function as last, it clashes with an existing procedure, the very same that you should use to solve the problem!
(define (my-last f L)
(f (last L)))
If you definitely have to write the function from scratch, then make sure that you understand what base cases are needed:
(define (my-last f L)
(cond ((null? L) #f)
((null? (cdr L)) (f (car L)))
(else (my-last f (cdr L)))))
Either way, it works as expected:
(my-last odd? '(0 5 3 8 6 7))
=> #t
For how you wrote the function, you have an extra parentheses set in the call. It should just be (last odd? '(0 5 3 8 6 7)) as someone suggested you in the comments.
I apologize for the unclear topic title.
I have this function in Scheme which is a custom implementation of the map function. It works fine, but I got lost trying to understand it.
(define (my-map proc . ls)
(letrec ((iter (lambda (proc ls0)
(if (null? ls0)
'()
(cons (proc (car ls0))
(iter proc (cdr ls0))))))
(map-rec (lambda (proc ls0)
(if (memq '() ls0)
'()
(cons (apply proc (iter car ls0))
(map-rec proc (iter cdr ls0)))))))
(map-rec proc ls)))
The problem lays in cons (proc (car ls0)). If I'm correct, when passing (1 2 3) (4 5 6) to the ls parameter the actual value of it will be ((1 2 3) (4 5 6)). Therefore iter car ls0 in map-rec will pass (1 2 3) to iter. Hence proc (car ls0) in iter will have the form: (car (car (1 2 3))), but this is impossible, right?
I know my thinking is flawed somewhere, but I can't figure out where.
Here's one way to understand the procedure:
The iter helper is the same as map, but operating on a single list.
The map-rec helper generalizes iter, working for a list of lists, stopping when at least one of the lists is empty
This part: (apply proc (iter car ls0)) applies the procedure on the first element of each list; the call to iter creates a list of the car part of the lists
And this part: (map-rec proc (iter cdr ls0)) simultaneously advances the recursion over all the lists; the call to iter creates a list of the cdr part of the lists
Perhaps renaming the procedures will make things clear. Here's a completely equivalent implementation, making explicit the fact that map-one operates on a single list and map-many operates on a list of lists:
(define (map-one proc lst) ; previously known as `iter`
(if (null? lst)
'()
(cons (proc (car lst))
(map-one proc (cdr lst)))))
(define (map-many proc lst) ; previously known as `map-rec`
(if (memq '() lst)
'()
(cons (apply proc (map-one car lst))
(map-many proc (map-one cdr lst)))))
(define (my-map proc . lst) ; variadic version of `map-many`
(map-many proc lst))
It works just like the original my-map:
(my-map + '(1 2 3) '(4 5 6) '(7 8 9))
=> '(12 15 18)
And you can check that map-one is really a map that works on a single list:
(map-one (lambda (x) (* x x))
'(1 2 3 4 5))
=> '(1 4 9 16 25)
See the effect of (map-one car lst) on a list of lists:
(map-one car '((1 4 5) (2 6 7) (3 8 9)))
=> '(1 2 3)
Likewise, see how (map-one cdr lst) works:
(map-one cdr '((1 4 5) (2 6 7) (3 8 9)))
=> '((4 5) (6 7) (8 9))