Local in scheme - scheme

I am just making up random programs and looking if I can use local. Is there a way I can use local for this? -
(define (filt n)
(filter number? n))
(define (mapn n)
(map add1 (filt n)))
(define (mapl n)
(map list (mapn n)))
(check-expect (mapl(list 1 2 false "true" "b" 'b true 4 9)) (list (list 2) (list 3) (list 5) (list 10)))
The first program makes sure the output are only numbers. The second one adds 1 to each number, and the third program creates a list of each individual element inside the list.
I tried but I get no answer and end up with a user break.
(define (mapit n)
(local [(define (filt l)
(filter number? l))]
(local [(define (mapn b)
(map add1 b))]
(mapit (map list n)))))

You want to use let.
(let ( (name value)
(othername othervalue))
expression-using-name)
So
(define (map-it n)
(let ((filt (lambda (l)
(filter number? l)))
(mpan (lambda (b)
(map add1 b))))
(mapit map list n)))
But what are you trying to accomplish here? You're not actually using mapn or filt anywhere.
I think you can just use
(define (mapl n)
(define (filt n)
(filter number? n))
(define (mapn n)
(map add1 (filt n)))
(map list (mapn n)))
Since scheme allows nested definitions.

Related

in the Scheme language, a code that returns a list with all prime numbers less than or equal to n

I have been writing a code that returns a list with all prime numbers less than or equal to n in the Scheme language.
Example,3 -> 2,3 10 -> 1,3,5,7 11->2,3,5,7,11
Actually, the codes below works.However, when I put 1 for n, the code should show (), but it shows 2. I think that it is because I put 2 on the second line. But I put the 2 for the other test case.
I tried to fix the code, but it did not work.
Are there any points where I can fix?
(define (primes n)
(let loop((result `(2))
(i 3))
(cond ((> i n)(reverse result))
(else (loop
(if (divide-any? i result) result (cons i result))
(+ i 2))))))
(define (divide? n1 n2)
(zero? (modulo n1 n2)))
(define (divide-any? n ls)
(do ((ls ls (cdr ls)))
((or (null? ls)
(divide? n (car ls)))
(not (eqv? '() ls)))))
Yes, the function primes is partial - it only works for certain values.
You can fix it quite simply:
(define (primes n)
(if (<= n 1)
'()
(let loop((result `(2))
(i 3))
(cond ((> i n)(reverse result))
(else (loop
(if (divide-any? i result) result (cons i result))
(+ i 2)))))))

Scheme - returning first n-elements of an array

I'm trying to write a function in Scheme that returns the first n elements in a list. I'm want to do that without loops, just with this basic structure below.
What I've tried is:
(define n-first
(lambda (lst n)
(if (or(empty? lst) (= n 0))
(list)
(append (car lst) (n-first (cdr lst) (- n 1))))))
But I'm getting an error:
append: contract violation
expected: list?
given: 'in
I've tried to debug it and it looks that the tail of the recursion crashes it, meaning, just after returning the empty list the program crashes.
When replacing "append" operator with "list" I get:
Input: (n-first '(the cat in the hat) 3)
Output:
'(the (cat (in ())))
But I want to get an appended list.
A list that looks like (1 2 3) i constructed like (1 . (2 . (3 . ()))) or if you're more familiar with cons (cons 1 (cons 2 (cons 3 '()))). Thus (list 1 2 3)) does exactly that under the hood. This is crucial information in order to be good at procedures that works on them. Notice that the first cons cannot be applied before the (cons 2 (cons 3 '())) is finished so a list is always created from end to beginning. Also a list is iterated from beginning to end.
So you want:
(define lst '(1 2 3 4 5))
(n-first lst 0) ; == '()
(n-first lst 1) ; == (cons (car lst) (n-first (- 1 1) (cdr lst)))
(n-first lst 2) ; == (cons (car lst) (n-first (- 2 1) (cdr lst)))
append works like this:
(define (append lst1 lst2)
(if (null? lst1)
lst2
(cons (car lst1)
(append (cdr lst1) lst2))))
append is O(n) time complexity so if you use that each iteration of n parts of a list then you get O(n^2). For small lists you won't notice it but even a medium sized lists of a hundred thousand elements you'll notice append uses about 50 times longer to complete than the cons one and for large lists you don't want to wait for the result since it grows exponentially.
try so
(define first-n
(lambda (l)
(lambda (n)
((lambda (s)
(s s l n (lambda (x) x)))
(lambda (s l n k)
(if (or (zero? n)
(null? l))
(k '())
(s s (cdr l) (- n 1)
(lambda (rest)
(k (cons (car l) rest))))))))))
(display ((first-n '(a b c d e f)) 4))
(display ((first-n '(a b)) 4))
In scheme you must compute mentally the types of each expression, as it does not have a type checker/ type inference included.

Building accumulator for lazy lists in Racket

I defined a simple lazy list of all integers from zero:
(define integers-from
(lambda (n)
(cons n
(lambda () (integers-from (+ 1 n))))))
(define lz (integers-from 0))
I also coded an accumaltor that gets a lazy list as a parameter
(define lz-lst-accumulate
(lambda (op initial lz)
(if (null? lz)
initial
(cons (op (head lz) initial)
(lambda () (lz-lst-accumulate op (op initial (head lz)) (tail lz)))))))
Does this accumaltor answer the format of lazy lists?
Here is a simple test of the accumulator:
(define acc (lz-lst-accumulate * 1 lz))
(take acc 4)
=> '(1 2 6 24)
take is a helper function that creates a list from the first n elements of a lazy list:
(define head car)
(define tail
(lambda (lz-lst)
((cdr lz-lst)) ))
(define take
(lambda (lz-lst n)
(if (= n 0)
(list)
(cons (car lz-lst)
(take (tail lz-lst) (sub1 n)))) ))
In your lz-lst-accumulate you calculate once (op (head lz) initial) and then also (op initial (head lz)). This is inconsistent; both should be the same and actually calculated only once, since it's the same value:
(define lz-lst-accumulate
(lambda (op initial lz)
(if (lz-lst-empty? lz)
initial
(let ((val (op (head lz) initial)))
(cons val
(lambda () (lz-lst-accumulate op val (tail lz))))))))
It works in your example with numbers only because you use the type-symmetrical operation *. With cons it wouldn't work.
Other than that it's OK. lz-lst-accumulate is usually known as left fold (scanl in Haskell, actually, since you produce the progression of "accumulated" values, foldl f z xs = last (scanl f z xs)).
re: your version of take, it is forcing one too many elements of a stream. Better make it
(define take
(lambda (lz n)
(if (or (<= n 0) (lz-lst-empty? lz))
(list)
(if (= n 1)
(list (car lz)) ; already forced
(cons (car lz)
(take (tail lz) (sub1 n)))))))
so that it only forces as many elements as it has to produce, and not one more (which might be e.g. divergent, like (/ 1 0), invalidating the whole calculation for no reason).
That way, the counter-example in SRFI 41 (of (take 4 (stream-map 1/ (ints-from-by 4 -1)))) will just work (it calculates (1/4 1/3 1/2 1/1) without forcing 1/0, which the usual version of take, like the one you're using, would do).

Creating a list from conditionals during iteration

I have written a simple procedure to find the divisors of a number (not including the number itself). I have figured out how to print them, but I would like to have this function return a list containing each of the divisors.
(define (divisors n)
(do ((i 1 (+ i 1)))
((> i (floor (/ n 2))))
(cond
((= (modulo n i) 0)
(printf "~a " i)))))
My idea is to create a local list, adding elements to it where my printf expression is, and then having the function return that list. How might I go about doing that? I am new to Scheme, and Lisp in general.
Do you necessarily have to use have to use do? here's a way:
(define (divisors n)
(do ((i 1 (add1 i))
(acc '() (if (zero? (modulo n i)) (cons i acc) acc)))
((> i (floor (/ n 2)))
(reverse acc))))
But I believe it's easier to understand if you build an output list with a named let:
(define (divisors n)
(let loop ((i 1))
(cond ((> i (floor (/ n 2))) '())
((zero? (modulo n i))
(cons i (loop (add1 i))))
(else (loop (add1 i))))))
Or if you happen to be using Racket, you can use for/fold like this:
(define (divisors n)
(reverse
(for/fold ([acc '()])
([i (in-range 1 (add1 (floor (/ n 2))))])
(if (zero? (modulo n i))
(cons i acc)
acc))))
Notice that all of the above solutions are written in a functional programming style, which is the idiomatic way to program in Scheme - without using mutation operations. It's also possible to write a procedural style solution (see #GoZoner's answer), similar to how you'd solve this problem in a C-like language, but that's not idiomatic.
Just create a local variable l and extend it instead of printing stuff. When done, return it. Like this:
(define (divisors n)
(let ((l '()))
(do ((i 1 (+ i 1)))
((> i (floor (/ n 2))))
(cond ((= (modulo n i) 0)
(set! l (cons i l))))
l))
Note that because each i was 'consed' onto the front of l, the ordering in l will be high to low. Use (reverse l) as the return value if low to high ordering is needed.

Scheme Factorial (fact* l) Question

I'm a newbie at Scheme, so forgive the question: I have a function that calculates the factorials of a list of numbers, but it gives me a period before the last number in the results. Where am I going wrong?
code:
#lang scheme
(define fact
(lambda (n)
(cond
((= n 0) 1)
((= n 1) 1)
(else (* n (fact (- n 1)))))))
(define fact*
(lambda (l)
(cond
((null? (cdr l)) (fact (car l)))
(else
(cons (fact (car l)) (fact* (cdr l)))))))
output:
> (fact* '(3 6 7 2 4 5))
(6 720 5040 2 24 . 120)
What you have done is create an improper list. Try this:
(define fact*
(lambda (l)
(cond
((null? (cdr l)) (list (fact (car l))))
(else
(cons (fact (car l)) (fact* (cdr l)))))))
The addition of the list in the fourth line should make this work as you expect. Better might be the following:
(define fact*
(lambda (l)
(cond
(null? l) '())
(else
(cons (fact (car l)) (fact* (cdr l)))))))
This allows your fact* function to work on the empty list, as well as reducing the number of places where you make a call to fact.
The other answers have pointed out the reason why you get an improper list as a result of your fact* function. I would only like to point out that you could use the higher-order function map:
(define fact*
(lambda (l)
(map fact l))
(fact* '(3 6 7 2 4 5))
map takes a function and a list as arguments and applies the function to every element in the list, producing a new list.
Use append instead of cons. cons is used to construct pairs, which is why you have the "." that is used to separate the elements of a pair. Here's an example:
(define (factorial n)
(if (<= n 1)
1
(* n (factorial (- n 1)))))
(define (factorial-list l)
(if (null? l)
'()
(append (list (factorial (car l)))
(factorial-list (cdr l)))))

Resources