how to call to this map function - scheme

I saw a code on a book about how to create a map function in Scheme, the code is the following:
(define map (lambda (f L)
(if null? L '()
(cons (f (car L)) (map f (cdr L))))))
(define square (lambda (x)
(* x x)))
(define square-list (lambda (L)
(map square L)))
Supposedly I can call it with:
(map square-list '(1 2 3 4))
but it is throwing me the following error:
SchemeError: too many operands in form: (null? L (quote ()) (cons (f (car L)) (map f (cdr L))))
Current Eval Stack:
-------------------------
0: (map square-list (quote (1 2 3 4)))
How should I call this function?

You have two errors. First, you forgot to surround the null? check with parentheses (and notice a better way to indent your code):
(define map
(lambda (f L)
(if (null? L)
'()
(cons (f (car L))
(map f (cdr L))))))
Second, you're expected to call the procedure like this:
(square-list '(1 2 3 4 5))
=> '(1 4 9 16 25)

You're missing parens around null? L, i.e. your condition should probably look like
(if (null? L) '()
(cons ...))

Related

Scheme Error Unknown Identifier: map when using higher order function

Essentially, I am trying to write a scheme method which will use the map function to cube every item in a list. so it would go from '(1 2 3 4) to '(1 8 27 64). Here is my current code:
(define (cube-all lst)
(map (lambda (x) (* (* x x) x)) lst)
)
This is the error message:
SchemeError: unknown identifier: map
Current Eval Stack:
-------------------------
0: map
1: (cube-all (quote (1 2 3 4)))
2: (println (cube-all (quote (1 2 3 4))))
Is this due to improper syntax? Or do I have to do something else with map?
Edit: println is another function which just displays the answer
If you are constrained to using the 'scheme' mentioned in a comment then you can't use map.
But ... you can write map:
(define (reverse l)
(define (reverse-loop lt into)
(if (null? lt)
into
(reverse-loop (cdr lt) (cons (car lt) into))))
(reverse-loop l '()))
(define (map f l)
(define (map-loop lt into)
(if (null? lt)
(reverse into)
(map-loop (cdr lt) (cons (f (car lt)) into))))
(map-loop l '()))
(define (cube-all lst)
(map (lambda (x) (* (* x x) x)) lst))
(cube-all '(1 2 3))

Show last appearance of element in list

I want to show the last appearance of an element from a given list. For example: For the list '(1 1 2 1 3 3 4 3 5 6), the result will be '(2 1 4 3 5 6)
This is the code I have:
(define (func L res)
(if (not (null? L))
(foldl (lambda (e)
(if (not (member e (cdr L)))
(cons e (remove-duplicates-right (cdr L)))
(remove-duplicates-right (cdr L))))
res L)
res))
(define (show-last-app L)
(func L '()))
The next error occurs: "foldl: given procedure does not accept 2 arguments"
This is how I solved it only with recursion but I want to use only foldl or filter and don't use functions with side effects:
(define (show-last-app L)
(cond
((null? L)
'())
((not (member (car L) (cdr L)))
(append (list (car L)) (show-last-app (cdr L))))
(else (show-last-app (cdr L)))))
I think you misunderstand how folds work in Scheme. This is closer to what you were aiming for:
(define (show-last-app L)
(foldr (lambda (e acc)
(if (not (member e acc))
(cons e acc)
acc))
'()
L))
If you really, really have to use foldl:
(define (show-last-app L)
(foldl (lambda (e acc)
(if (not (member e acc))
(cons e acc)
acc))
'()
(reverse L)))
Either way, it works as expected:
(show-last-app '(1 2 4 1 5 3 1 6 2))
=> (4 5 3 1 6 2)

Scheme: Split list into list of two sublists of even and odd positions

I'm trying to use direct recursion to sort a list into a list of sublists of even and odd positions.
So (split '(1 2 3 4 5 6)) returns ((1 3 5) (2 4 6))
and (split '(a 2 b 3)) returns ((a b) (2 3))
So far, I have the following code:
(define split
(lambda (ls)
(if (or (null? ls) (null? (cdr ls)))
(values ls '())
(call-with-values
(lambda () (split (cddr ls)))
(lambda (odds evens)
(values (cons (car ls) odds)
(cons (cadr ls) evens)))))))
However, now I'm stumped on how to store multiple outputs into a single list.
I know that calling it like this:
(call-with-values (lambda () (split '(a b c d e f))) list)
returns a list of sublists, however I would like the function itself to return a list of sublists. Is there a better way to do this that doesn't involve the use of values and call-with-values?
Sure. Here's an adapted version of your code:
(define (split ls)
(if (or (null? ls) (null? (cdr ls)))
(list ls '())
(let ((next (split (cddr ls))))
(list (cons (car ls) (car next))
(cons (cadr ls) (cadr next))))))
One thing that I like about the code in the question is that it uses odds and evens in a way that reflects the specification.
The objectives of this solution are:
Readability.
To reflect the language of the specification in the code.
To use O(n) space during execution.
It uses an internal function with accumulators and a trampoline.
#lang racket
;; List(Any) -> List(List(Any) List(Any))
(define (split list-of-x)
(define end-of-list (length list-of-x))
;; List(Any) List(Any) List(Any) Integer -> List(List(Any) List(Any))
(define (looper working-list odds evens index)
(cond [(> index end-of-list)
(list (reverse odds)
(reverse evens))]
[(odd? index)
(looper (rest working-list)
(cons (car working-list) odds)
evens
(add1 index))]
[(even? index)
(looper (rest working-list)
odds
(cons (car working-list) evens)
(add1 index))]
[else
(error "split: unhandled index condition")]))
(looper list-of-x null null 1))
Here's an answer that should be clear if you are familiar with match syntax. It is identical in form and function to Chris Jester-Young's answer, but uses match to clarify list manipulation.
#lang racket
(define (split ls)
(match ls
[`(,first ,second ,rest ...)
(match (split rest)
[`(,evens ,odds) (list (cons first evens)
(cons second odds))])]
[_ (list ls '())]))
(: split ((list-of natural) -> (list-of (list-of natural))))
(define split
(lambda (xs)
(list (filter even? xs) (filter odd? xs))))
(: filter ((%a -> boolean) (list-of %a) -> (list-of %a)))
(define filter
(lambda (p xs)
(fold empty (lambda (first result)
(if (p first)
(make-pair first result)
result)) xs)))
(check-expect (split (list 1 2 3 4 5 6)) (list (list 2 4 6) (list 1 3 5)))
i think this one is also really easy to understand..

Can I assign a list of symbols to a list of elements in Guile?

I'm writing some guile code that gets a list of a set length, and I need to define a variable for every element in the list.
Currently, I have to do something like this:
(define (foo l)
(let ((e-1 (car l))
(e-2 (cadr l))
(e-2 (caddr l))
; ...
(e-n (list-ref (- n 1)
l)))
(compute)))
This gets super tedious. Is there anyway I can do something like this instead?
(define (foo l)
(symbol-def e-1 e-2 e-3 e-4 e-n l)
(compute))
Edit: Made question more guile-specific.
Guile-specific, I've found the ice-9 match module, which has the following form:
(match lst
((pattern) expr))
Example:
(use-modules (ice-9 match))
(let ((l '(test foo bar)))
(match l
((head second third)
second)))
; returns `foo`
Using multiple values is one way to bind the elements of a list of known length to variables:
;;; Using SRFI-8 receive syntax
(use-modules (ice-9 receive))
(define (foo l)
(receive (e-1 e-2 e-3 e-4) (apply values l)
(format #t "~S~%~S~%~S~%~S~%" e-1 e-2 e-3 e-4)))
(foo '(1 2 3 4))
;;; Using SRFI-11 let-values syntax
(use-modules (srfi srfi-11))
(define (foo2 l)
(let-values (((e-1 e-2 e-3 e-4) (apply values l)))
(format #t "~S~%~S~%~S~%~S~%" e-1 e-2 e-3 e-4)))
(foo2 '(a b c d))
;;; Using R5RS call-with-values
(define (foo3 l)
(call-with-values
(lambda () (apply values l))
(lambda (e-1 e-2 e-3 e-4)
(format #t "~S~%~S~%~S~%~S~%" e-1 e-2 e-3 e-4))))
Another thing worth mentioning is define-values
(define (bar l)
(define-values (a b c d) (apply values l))
(compute a b c d))

What is wrong with my scheme code?

The function I wrote for SICP 2.20 is:
(define (same-parity x . y)
(if (null? (car y)
'()
(if (= (even? (car y)) (even? x))
(cons (car y) (same-parity (cons x (cdr y))))
(same-parity (cons x (cdr y))))))
And then I try to call it with
(same-parity 1 2 3 4 5 6 7)
The error I get is:
"The object #t, passed as the first argument to integer-equal? is not the correct type."
I thought that equal works with #t and #f...
An example of code I found online is the following, I ran it and it works. But, what am I doing wrong?
(define (same-parity a . rest)
(define (filter rest)
(cond ((null? rest) '())
((= (remainder a 2) (remainder (car rest) 2))
(cons (car rest) (filter (cdr rest))))
(else
(filter (cdr rest)))))
(filter (cons a rest)))
The = procedure accepts numbers. But even? returns a boolean not a number.
Use equal? instead of =.
equal? works with booleans.
For instance at the REPL:
> (even? 2)
#t
> (= (even? 2) (even? 2))
=: expects type <number> as 1st argument, given: #t; other arguments were: #t
> (equal? (even? 2) (even? 2))
#t

Resources