Trying to append recursively, what am I doing wrong in Scheme? - scheme

Trying to recursively append every element from list a to list c. Currently only one elements gets appended. What am I doing wrong? I', trying to reverse a list. But currently stuck understanding how to even append a list to another list.
(define a '(1 2 3))
(define c '())
(define fun
(lambda (() l1) l1
(l l1) (append l1 (car l)) (fun (cdr l) l1)
))
(fun a c)
I'm using a scheme like interpreter, where I cannot use any new built-in functions except of the listfunctions.

You need to use
(lambda (l l1)
(if (null? l)
l1
(append l1 (car l)) (fun (cdr l) l1)))
what you wrote looks like it would work if there was a pattern matching facility, but our lambda is more basic and doesn't pattern match.

Related

Local Procedure Bindings

I'm new to Scheme and Lisp in general, and upon learning I've stumbled upon a cryptic syntax used in local procedure binding:
(define mock
(lambda (s)
;; this is what I don't understand
(let splice ([l '()] [m (car s)] [r (cdr s)])
(append
(map (lambda (x) (cons m x)) r)
(if (null? r) '()
(splice (cons m l) (car r) (cdr r)))))))
It took me a while to grasp that splice is a scoped procedure with 3 arities. Rewriting this in an ML-esque style it seems to produce similar output:
(define mock2
(lambda (s)
;; define `splice` first
(define splice
(lambda (la lb lc)
(append
(map (lambda (x) (cons lb x)) lc)
(if (null? lc) '()
(splice (cons lb la) (car lc) (cdr lc))))))
;; bind `splice` and its arguments together and call it with them
(let ([sp splice] [l '()] [m (car s)] [r (cdr s)])
(splice l m r))))
The second version is a bit longer and somewhat look more imperative, but defining splice as a normal procedure inside the scope before binding it in parallel with the arguments (or just chuck them in as-is) and calling it looks saner.
Question is are these two versions replaceable? If yes, could you help explain the first version's syntax of binding local variables (l, m, and r) within the splice binding form?
Calling splice is like re-entering a loop, which is what it is there for. A tail call is a goto anyway. It is often named loop, instead of thinking up some special name for it.
"looks saner" is debatable, and actually with Schemers you'll lose this one, because this is a very popular Scheme construct, called "named let". It is usually re-written with letrec btw, if/when one wants to rewrite it, to understand it better. Internal define can be used as well, but then, why not use (define (mock s) ... in the first place.
So, the usual way to re-write this
(define mock ; or: (define (mock s) ...
(lambda (s)
(let splice ([l '()] [m (car s)] [r (cdr s)])
(append
(map (lambda (x) (cons m x)) r)
(if (null? r) '()
(splice (cons m l) (car r) (cdr r)))))))
is this:
(define mock
(lambda (s)
(letrec ([splice (lambda (l m r) ; or: (define (splice l m r) ...
(append
(map (lambda (x) (cons m x)) r)
(if (null? r) '()
(splice (cons m l) (car r) (cdr r)))))])
(splice '() (car s) (cdr s)))))
and writing it in the named let way saves one from having it defined in one place and called in another, potentially far away. A call enters its body from the start anyway, and named let better reflects that.
This is pretty self-explanatory. The transformation from one form to the other is purely syntactical, and both can be used interchangeably.

Scheme and Merge Sort?

I was assigned to write a merge sort in Scheme but I have some issues with it. I showed it my professor and he said there is one simple mistake. Can someone help me?
Plzz!
(define msort
(lamdba(1st)
(cond
((null?? 1st) 1st)
((null? (cdr 1st)) 1st)
(#t ((letrec ((half (quotient (lenght 1st) 2))
(merge (lamdba (a b result)
(cond ((null? a) (apped (reserve a) result))
((null? b) (append (reserve a) result))
((> (car a) (car b) (merge a (cdr b) (cons (car b) result))
(#t (merge (cdr a) b (cons (car a) result)))))))
(merge (msort (take 1st half)) (msort (drop 1st half)) '()))))))
One simple mistake? He probably referred to #1, but even after fixing that you have some identifiers and parenthesis to fix:
lambda, null?, length, append, and reverse is spelled incorrectly.
letrec result gets applied since you have excess parenthesis around it.
cond in merge where you compare elements are missing parenthesis two places.
It's obvious you need help with parenthesis matching so you should download a decent IDE to write code in. I use DrRacket for Scheme development (#!R5RS, #!R6RS and #!racket) and it idents (just press CTRL+i to get it reidented after pasting in code) and indicate where function names are written wrong when you hit RUN.
Making merge a global function in the beginning and perhaps move it to a letrec later (if you have to) might ease development. Eg. you could find errors by testing stuff like (merge '(3 2 1) '()).
This is no guarantee the program will work since I only address syntax here. You need to debug it! DrRacket has a debugger too!
I think it is useful to implement first a function that allow to merge two ordered lists:
(define (merge l1 l2)
(if (empty? l1)
l2
(if (empty? l2)
l1
(if (< (car l1) (car l2))
(cons (car l1) (merge (cdr l1) l2))
(cons (car l2) (merge l1 (cdr l2)))))))
Now assume we have a function (get ls pos) capable to return the element of ls in position pos:
(define (get ls pos)
(if (= pos 1)
(car ls)
(get (cdr ls) (- pos 1))))
Finally, we can implement mergesort function:
(define (mergesort l p r)
(if (= p r)
(cons (get l p) empty)
(merge (mergesort l p (floor (/ (+ p r) 2))) (mergesort l (+ (floor (/ (+ p r) 2)) 1) r))))

implement expand function with racket

I can't seem to figure out how to write this function. What I am trying to write is a function expand that takes a list lst as a parameter of the form '(a (2 b) (3 c)) and is evaluated to '(a b b c c c)
This looks like homework, so I'm not giving you a straight answer. Instead, I'll give you some pointers in the right direction. The most useful hint, is that you should split the problem in two procedures, one for processing the "outer" list and the other for generating the repetitions encoded in the inner sublists.
Notice that both procedures are mutually recursive (e.g., they call each other). The expand procedure recurs over the list, whereas the repeat procedure recurs over the number of repetitions. This is the general structure of the proposed solution, fill-in the blanks:
; input: lst - list to be processed
; output: list in the format requested
(define (expand lst)
(cond ((null? lst) ; if the list is null
'()) ; then return null
((not (pair? (car lst))) ; if the first element of the list is an atom
(cons <???> <???>)) ; cons the atom and advance the recursion
(else ; if the first element of the list is a list
<???>))) ; call `repeat` with the right params
; input: n - number of repetitions for the first element in the list
; lst - list, its first element is of the form (number atom)
; output: n repetitions of the atom in the first element of lst
(define (repeat n lst)
(if (zero? n) ; if the number of repetitions is zero
(expand (cdr lst)) ; continue with expand's recursion
(cons <???> ; else cons the atom in the first element and
<???>))) ; advance the recursion with one less repetition
As this was answered three years ago, I don't think that I am helping with homework. Would just like to point out that the two functions really don't need to be mutually recursive. As replicate is a fairly common function, I would propose:
(define (replicate what n)
(if (zero? n)
(list)
(cons what (replicate what (- n 1)))))
(define (my-expand xs)
(if (empty? xs)
(list)
(let ((x (first xs)))
(if (list? x)
(let ((the-number (first x))
(the-symbol (cadr x)))
(flatten (cons (replicate the-symbol the-number)
(my-expand (rest xs)))))
(cons x (my-expand (rest xs)))))))
Of course it is better to use two lists and perform the flatten at the end, something like this:
(define (my-expand xs)
(define (inner-expander xs ys)
(if (empty? xs) (flatten (reverse ys))
(let ((x (first xs)))
(if (list? x)
(let ((the-number (first x))
(the-symbol (cadr x)))
(inner-expander (rest xs) (cons (replicate the-symbol the-number) ys)))
(inner-expander (rest xs) (cons x ys))))))
(inner-expander xs (list)))

Scheme - car/cdr on empty list

I wrote a big program that use car and cdr, and do:
(map car (append (map caddr lists) (map cadr lists))
When lists is list of lists in the next format ((a (b) (c)) (d (e) (f))...(x (y) (z)))
When I did it I got one list (b c e f... y z)
(Note: b,c,...y,z is a list of numbers; a,d...x is a symbol)
But now, I found that b,c,...,y,z can be also empty list, and It gives the next error:
car: expects argument of type <pair>; given ()
What can I do?
Have you tried filtering away empty lists before your map? Something like this:
(map car (filter pair? (append (map caddr lists) (map cadr lists))))
The fundamental issue is that () is not a pair while car only acts on pairs. The simplest solution is just to get rid of everything that isn't a pair before mapping car onto the list; this is what (filter pair? ...) does.
Here's my shot. It's a straight solution, without using map, filter; in that way, I avoid going over and over the elements of the list constructing intermediate lists - except that I used a reverse operation for preserving the original order of the elements, if that's not an issue, remove reverse. For each element in the original list, if either the (b)... or (c)... part is empty, it's skipped.
(define (process lists)
(let loop ((l (reverse lists))
(a '())
(b '()))
(cond ((null? l)
(append b a))
((or (not (pair? (cadar l))) (not (pair? (caddar l))))
(loop (cdr l) a b))
(else
(loop (cdr l) (cons (caadar l) a) (cons (car (caddar l)) b))))))

Scheme append procedure

I'm having trouble appending a list to another list. Below is my code. When I run (append '(1 2) '(3 4)) I get '(1 3 2 4).
I want the output to be '(1 2 3 4)
(define (append l m)
(if (null? l) '()
(cons (car l) (append m (cdr l)))))
Thanks
Well by switching the two lists around like that (switching the position of m and l when calling append recursively), you'll get the first item of the first list followed by the first item of the second list etc.
If you don't want that, you should keep l as the first argument and m as the second. So you get:
(define (append l m)
(if (null? l) '()
(cons (car l) (append (cdr l) m))))
Of course this doesn't work as wanted either, because now you only get the first list back and nothing is appended at all. What you need to do is, once the first list is fully appended (i.e. once l is empty), you need to return the second one as the tail, like this:
(define (append l m)
(if (null? l) m
(cons (car l) (append (cdr l) m))))
I came across this while studying myself. #sepp2k's answer is a fine piece of instruction guiding OP to correct their code to achieve a recursive definition of append. Here's an alternate definition of my-append using the higher-order function foldr:
(define (myappend xs ys)
(foldr cons ys xs))

Resources