I'm learning racket and new to functional programming and wrote the following code for stack:
(define stack '(0))
(define (push x stack)
(set! stack (cons x stack)))
(define (pop stack)
(let ((result (car stack)))
(set! stack (cdr stack))
result))
When I do
(push 2 stack)
There is no error.
When I do (pop stack) I get back 0.
What am I doing wrong.
You have a global st variable, but you are calling set! on local variables in push and pop. You need to remove the st argument from your functions. The problem might be more clear if you renamed the st argument to something else (like stack).
(define (push x stack)
(set! stack (cons x stack))) ; stack is mutated, but st remains unchanged
You are using global state i.e st and passing st as parameter to push as well and that is causing the local st in push to be updated and the global st remains '(0).
You can solve this by getting rid of the global st as shown below:
(define (push x st)
(cons x st))
(define (pop st)
(values (car st) (cdr st)))
Usage:
(let ((stack '(0)))
(define-values (v s) (pop (push 2 stack)))
v)
This is my version/implementation:
(define stack empty)
(define (push x)
(set! stack (append stack (list x))))
(define (pop)
(define reversedStack (reverse stack))
(define result (car reversedStack))
(set! stack (reverse (cdr reversedStack)))
result)
Related
I'm trying to implement quicksort in CLisp, and so far I'm able to partition the list around a pivot. However, when I try to combine and recursively sort the sublists, I get either a stack overflow or an error with let, and I'm not sure what's going wrong. Here's my code:
(defun pivot (n xs)
(list (getLesser n xs) (getGreater n xs))
)
(defun getLesser (m l)
(cond
((null l) nil)
((<= m (car l)) (getLesser m (cdr l)))
(t (cons (car l) (getLesser m (cdr l)))))
)
(defun getGreater (m l)
(cond
((null l) nil)
((> m (car l)) (getGreater m (cdr l)))
(t (cons (car l) (getGreater m (cdr l)))))
)
(defun quicksort (xs)
(cond
((null xs) nil)
(t
(let (partition (pivot (car xs) xs))
(cond
((null (car partition)) (cons (quicksort (cdr partition)) nil))
((null (cdr partition)) (cons (quicksort (car partition)) nil))
(t (append (quicksort (car partition)) (quicksort (cdr partition)))))))))
My idea was to have a local variable partition that is a list of 2 lists, where car partition is the list of number less than the pivot, and cdr partition is the list of numbers greater than the pivot. Then, in the final cond construct, if there were no numbers less than the pivot I would recursively sort the 2nd list; if there were no numbers greater than the pivot I would sort the 1st list; else I would recursively sort both and append them in order. Can anyone help me out?
Compiling the file gives you hints about wrong syntax.
GNU CLISP produces these diagnostics:
$ clisp -q -c foo.lisp
;; Compiling file /tmp/foo.lisp ...
WARNING: in QUICKSORT in lines 20..28 : Illegal syntax in LET/LET*: (PIVOT (CAR XS) XS)
Ignore the error and proceed
;; Deleted file /tmp/foo.fas
There were errors in the following functions:
QUICKSORT
1 error, 1 warning
SBCL produces similar diagnostics:
$ sbcl --eval '(compile-file "foo.lisp")' --quit
This is SBCL 1.3.1.debian, an implementation of ANSI Common Lisp.
More information about SBCL is available at <http://www.sbcl.org/>.
SBCL is free software, provided as is, with absolutely no warranty.
It is mostly in the public domain; some portions are provided under
BSD-style licenses. See the CREDITS and COPYING files in the
distribution for more information.
; compiling file "/tmp/foo.lisp" (written 08 MAY 2019 08:58:54 PM):
; compiling (DEFUN PIVOT ...)
; compiling (DEFUN GETLESSER ...)
; compiling (DEFUN GETGREATER ...)
; compiling (DEFUN QUICKSORT ...)
; file: /tmp/foo.lisp
; in: DEFUN QUICKSORT
; (LET (PARTITION (PIVOT (CAR XS) XS))
; (COND ((NULL (CAR PARTITION)) (CONS (QUICKSORT #) NIL))
; ((NULL (CDR PARTITION)) (CONS (QUICKSORT #) NIL))
; (T (APPEND (QUICKSORT #) (QUICKSORT #)))))
;
; caught ERROR:
; The LET binding spec (PIVOT (CAR XS) XS) is malformed.
;
; compilation unit finished
; caught 1 ERROR condition
; /tmp/foo.fasl written
; compilation finished in 0:00:00.021
You can then look up the expected syntax in CLHS: http://www.ai.mit.edu/projects/iiip/doc/CommonLISP/HyperSpec/Body/speope_letcm_letst.html
The syntax for LET is (LET BINDINGS . BODY), where BINDINGS is a list of bindings; each binding is a (SYMBOL VALUE) list. Alternatively, a binding can just be SYMBOL, which stands for (SYMBOL NIL). Your code is:
(let (partition (pivot (car xs) xs))
...)
Let's write one binding per line and normalize all bindings as a proper list:
(let ((partition nil)
(pivot (car xs) xs)))
...)
You can see that the code:
binds partition to NIL
has a malformed second binding: there are three elements, namely pivot, (car xs) and xs, which does not match the expected (SYMBOL VALUE) syntax.
I attempted a question of making a program that replaces all instances of an element A within a list L with T and unlike elements with NIL. The bet is to not use mapcar.
Here is what I did earlier. I am storing all T and NIL in a new list POS then returning POS.
(defun SRC (A L)
(defun _SRC (A L POS)
(COND ((NOT (EQUAL (CAR L) NIL))
(_SRC A (CDR L) (APPEND POS (LIST (EQUAL A (CAR L))))))
((EQUAL (CAR L) NIL)
(APPEND POS (LIST (EQUAL A NIL))))
(T POS)))
(CDR (_SRC A L (LIST NIL))))
Current behaviour:
The program is working nicely, except when searching for NIL itself, but that special case is not of concern here.
Few example runs of my code:-
(SRC 'g '(a g g o t g))
> (nil t t nil nil t)
When searching for NIL in a list:-
(SRC nil '(t a t nil nil))
> (nil nil nil t)
In this singular case our program ends on finding the first NIL in the list, for other searches, the program works fine. So I tried adding the ability of searching within lists of lists.
My updated code for searching within lists of lists without mapcar:
(defun SRC (A L)
(defun _SRC (A L POS)
(COND ((LISTP (CAR L))
(APPEND POS (LIST (SRC A (CAR L)))))
((NOT (EQUAL (CAR L) NIL))
(_SRC A (CDR L) (APPEND POS (LIST (EQUAL A (CAR L))))))
((EQUAL (CAR L) NIL)
(APPEND POS (LIST (EQUAL A NIL))))
(T POS)))
(CDR (_SRC A L (LIST NIL))))
Now, the output that I expect from this code is as follows:
(SRC 'e '(a b e c (e g e) h t e))
> (nil nil t nil (t nil t) nil nil t)
Instead my code runs forever, causing stack overflow, and I could not figure out anything with callstacks or backtracking.
Unreadable code due to lack of indentation.
Your code is unreadable, because your code is not indented.
(defun SRC (A L)
(defun _SRC (A L POS)
(COND ((NOT (EQUAL (CAR L) NIL)) (_SRC A (CDR L) (APPEND POS (LIST (EQUAL A (CAR L))))))
((EQUAL (CAR L) NIL) (APPEND POS (LIST (EQUAL A NIL))))
(T POS)))
(CDR (_SRC A L (LIST NIL))))
Let's indent your code.
(defun SRC (A L)
(defun _SRC (A L POS)
(COND ((NOT (EQUAL (CAR L) NIL))
(_SRC A (CDR L) (APPEND POS (LIST (EQUAL A (CAR L))))))
((EQUAL (CAR L) NIL)
(APPEND POS (LIST (EQUAL A NIL))))
(T POS)))
(CDR (_SRC A L (LIST NIL))))
Style and basic mistakes
Basic mistakes or programming style problems:
defun should not be nested. defun is not for defining local functions. defun should only be used for global functions. Use flet or labels for local functions.
use first and rest instead of car and cdr
use speaking variables
use lowercase
Don't start with nested functions
I would start without nested functions.
(defun _src (element list pos)
(cond ((not (equal (first list) nil))
(_src a (rest list) (append pos (list (equal element (car list))))))
((equal (first list) nil)
(append pos (list (equal element nil))))
(t pos)))
(defun src (element list)
(cdr (_src element list (list nil))))
Simplify recursion
But then you can greatly simplify it using the usual recursive pattern:
(defun mark% (element list result)
(if (null list)
result ; empty list -> return result
(mark% element ; mark the rest of the list
(rest list)
(cons (equal element (first list)) ; equal for the first element?
result))))
(defun mark (element list)
"return a list with boolean values if element is found in the list"
(reverse (mark% element list nil))) : needs to reverse the result
Note
Generally don't program recursive functions like that, since Lisp actually already offers MAP and MAPCAR - those provide the mapping functionality in one place and it is not needed to bake the recursive mapping into each function of your own.
Preferably use higher level iteration facilities like LOOP:
CL-USER 13 > (loop for e in '(a b a b)
collect (equal 'a e))
(T NIL T NIL)
Nested lists
You can adapt the above function to nested lists by adding a case testing for the first element being a list and then doing something in that case...
(defun mark% (element list result)
(cond ((null list)
result)
((consp (first list))
(mark% element
(rest list)
(cons (mark element (first list))
result)))
(t
(mark% element
(rest list)
(cons (equal element (first list))
result)))))
Debugging
Use trace and/or step to see what your code is doing.
I'm using the beginning language with list abbreviations for DrRacket and want to make a powerset recursively but cannot figure out how to do it. I currently have this much
(define
(powerset aL)
(cond
[(empty? aL) (list)]
any help would be good.
What's in a powerset? A set's subsets!
An empty set is any set's subset,
so powerset of empty set's not empty.
Its (only) element it is an empty set:
(define
(powerset aL)
(cond
[(empty? aL) (list empty)]
[else
As for non-empty sets, there is a choice,
for each set's element, whether to be
or not to be included in subset
which is a member of a powerset.
We thus include both choices when combining
first element with smaller powerset,
that, which we get recursively applying
the same procedure to the rest of input:
(combine (first aL)
(powerset (rest aL)))]))
(define
(combine a r) ; `r` for Recursive Result
(cond
[(empty? r) empty] ; nothing to combine `a` with
[else
(cons (cons a (first r)) ; Both add `a` and
(cons (first r) ; don't add, to first subset in `r`
(combine ; and do the same
a ; with
(rest r))))])) ; the rest of `r`
"There are no answers, only choices". Rather,
the choices made, are what the answer's made of.
In Racket,
#lang racket
(define (power-set xs)
(cond
[(empty? xs) (list empty)] ; the empty set has only empty as subset
[(cons? xs) (define x (first xs)) ; a constructed list has a first element
(define ys (rest xs)) ; and a list of the remaining elements
;; There are two types of subsets of xs, thouse that
;; contain x and those without x.
(define with-out-x ; the power sets without x
(power-set ys))
(define with-x ; to get the power sets with x we
(cons-all x with-out-x)) ; we add x to the power sets without x
(append with-out-x with-x)])) ; Now both kind of subsets are returned.
(define (cons-all x xss)
; xss is a list of lists
; cons x onto all the lists in xss
(cond
[(empty? xss) empty]
[(cons? xss) (cons (cons x (first xss)) ; cons x to the first sublist
(cons-all x (rest xss)))])) ; and to the rest of the sublists
To test:
(power-set '(a b c))
Here's yet another implementation, after a couple of tests it appears to be faster than Chris' answer for larger lists. It was tested using standard Racket:
(define (powerset aL)
(if (empty? aL)
'(())
(let ((rst (powerset (rest aL))))
(append (map (lambda (x) (cons (first aL) x))
rst)
rst))))
Here's my implementation of power set (though I only tested it using standard Racket language, not Beginning Student):
(define (powerset lst)
(if (null? lst)
'(())
(append-map (lambda (x)
(list x (cons (car lst) x)))
(powerset (cdr lst)))))
(Thanks to samth for reminding me that flatmap is called append-map in Racket!)
You can just use side effect:
(define res '())
(define
(pow raw leaf)
(cond
[(empty? raw) (set! res (cons leaf res))
res]
[else (pow (cdr raw) leaf)
(pow (cdr raw) (cons (car raw) leaf))]))
(pow '(1 2 3) '())
I am trying to use recursion to stack a basic block I created (y), x amount of times high.
(define stack-copies-of
(lambda (x y)
(cond
((= x 0) 0)
((> x 0) (stack y y)
I didn't go any further because well... I'm stumped. I want the stack of blocks to appear on the screen. Thank you!
First of all, you are not using recursion. stack-copies-of is not stack.
You need to look at basic list operations. Heres some that makes a list:
;; easiest version, looks most like the one you started with
(define (make-list num-elements)
(if (zero? num-elements)
'() ; the tail of the list is the empty list
(cons '* (make-list (- num-elements 1)))))
;; tail recursive version using auxillary procedure
(define (make-list num-elements)
;; we define a local auxillary procedure to do the work
(define (make-list-aux num-elements acc)
(if (zero? n)
acc ; return the produced list
(make-list-aux (- n 1)
(cons '* acc))))
;; fire it off
(make-list-aux num-elements '()))
;; exactly the same as the previous, but with a named let
(define (make-list num-elements)
;; a named let can be called by name as a procedure, creating a loop
(let make-list-aux ((num-elements num-elements)
(acc '()))
(if (zero? n)
acc
(make-list-aux (- n 1)
(cons '* acc)))))
(display (make-list 10)) ; print the result
I expect what you're after could be based on one of these except instead of '* you use your extra argument.
If your data structure is a stack you can define it and the related operations push, pop and one to display the stack.
(define stack '())
(define (push e)
(set! stack (cons e stack)))
(define (pop)
(let ((e (car stack)))
(set! stack (cdr stack))
e))
(define (display-stack)
(for-each
(lambda (e) (display e) (newline))
stack))
the following is the recursive function to stack n times an element
(define (stack-ntimes n e)
(when (> n 0)
(push e)
(stack-ntimes (- n 1) e)))
"define a procedure 'reduce-per-key' which a procedure reducef and a list of associations in which each key is paired with a list. The output is a list of the same structure except that each key is now associated with the result of applying reducef to its associated list"
I've already written 'map-per-key' and 'group-by-key' :
(define (map-per-key mapf lls)
(cond
[(null? lls) '()]
[else (append (mapf (car lls))(map-per-key mapf (cdr lls)))]))
(define (addval kv lls)
(cond
[(null? lls) (list (list (car kv)(cdr kv)))]
[(eq? (caar lls) (car kv))
(cons (list (car kv) (cons (cadr kv) (cadar lls)))(cdr lls))]
[else (cons (car lls)(addval kv (cdr lls)))]))
(define (group-by-key lls)
(cond
[(null? lls) '()]
[else (addval (car lls) (group-by-key (cdr lls)))]))
how would I write the next step, 'reduce-per-key' ? I'm also having trouble determining if it calls for two arguments or three.
so far, I've come up with:
(define (reduce-per-key reducef lls)
(let loop ((val (car lls))
(lls (cdr lls)))
(if (null? lls) val
(loop (reducef val (car lls)) (cdr lls)))))
however, with a test case such as:
(reduce-per-key
(lambda (kv) (list (car kv) (length (cadr kv))))
(group-by-key
(map-per-key (lambda (kv) (list kv kv kv)) xs)))
I receive an incorrect argument count, but when I try to write it with three arguments, I also receive this error. Anyone know what I'm doing wrong?
Your solution is a lot more complicated than it needs to be, and has several errors. In fact, the correct answer is simple enough to make unnecessary the definition of new helper procedures. Try working on this skeleton of a solution, just fill-in the blanks:
(define (reduce-per-key reducef lls)
(if (null? lls) ; If the association list is empty, we're done
<???> ; and we can return the empty list.
(cons (cons <???> ; Otherwise, build a new association with the same key
<???>) ; and the result of mapping `reducef` on the key's value
(reduce-per-key <???> <???>)))) ; pass reducef, advance the recursion
Remember that there's a built-in procedure for mapping a function over a list. Test it like this:
(reduce-per-key (lambda (x) (* x x))
'((x 1 2) (y 3) (z 4 5 6)))
> '((x 1 4) (y 9) (z 16 25 36))
Notice that each association is composed of a key (the car part) and a list as its value (the cdr part). For example:
(define an-association '(x 3 6 9))
(car an-association)
> 'x ; the key
(cdr an-association)
> '(3 6 9) ; the value, it's a list
As a final thought, the name reduce-per-key is a bit misleading, map-per-key would be a lot more appropriate as this procedure can be easily expressed using map ... but that's left as an exercise for the reader.
UPDATE:
Now that you've found a solution, I can suggest a more concise alternative using map:
(define (reduce-per-key reducef lls)
(map (lambda (e) (cons (car e) (map reducef (cdr e))))
lls))