I am learning Scheme and as a toy example I am doing a solution verifier (not a solver) for Towers of Hanoi.
I want to use a purely functional style (just to get into the mindset) and I represent the tower as a simple list of three lists. The starting state can look something like this:
'((0 1 2 3 4) () ())
How would I implement a function that takes a state, a source index and a target index and returns the new state? In an imperative style this would be something trivial like:
state[target].push(state[source].pop())
But every functional solution I can think of is terribly convoluted. For example:
(define (makeMove state source target)
(letrec ((recMake (lambda(tower pos disc)
(if (null? tower) '()
(cons (if (eqv? pos source)
(cdr (car tower))
(if (eqv? pos target)
(cons disc (car tower))
(car tower)))
(recMake (cdr tower)
(+ pos 1)
disc))))))
(recMake state 0 (car (list-ref state source)))))
This seems to work, but there must be a better way. I suppose a map would be somewhat better than recursion, but still too much. Would it be easier if I represented state differently?
Also, feel free to criticize my code. I don't really know what I am doing.
EDIT:
If possible, I prefer that you not assume that the number of towers are always 3.
Here's a super-straightforward way. I'm not sure what the significance of the disc "numbers" are in your implementation, but I made it behave the same as your answer does, pushing and popping them.
(define (make-move state source target)
(define (alter-tower tower index disc)
(cond ((= index source) (cdr tower)) ; remove a disc
((= index target) (cons disc tower)) ; add a disc
(else tower))) ; this tower wasn't changed
(let ((disc (car (list-ref state source))))
(let ((s0 (alter-tower (list-ref state 0) 0 disc))
(s1 (alter-tower (list-ref state 1) 1 disc))
(s2 (alter-tower (list-ref state 2) 2 disc)))
(list s0 s1 s2))))
If you assume the existence of a map-with-index function, which comes standard in many languages and libraries but is not built into Scheme, then you could roll up the bottom set of operations on each tower into a call to that, and it would be much cleaner.
In general, try to come up with pure functions down to the lowest level possible which do what you want. In this solution, I invented a pure function "alter-tower" which can return the result of your command on a single tower, and that's what makes the rest of the solution very straightforward.
Since you asked for feedback, I note that = is identical for eqv? when applied to numbers, that internal defines work in Scheme and act as you'd expect (e.g. you can call them recursively) and that the usual naming convention in Lisp is to separate multi-word identifiers with hyphens, instead of using camel-case.
Good luck!
EDIT: Here's a version, for example, that uses Racket's list comprehensions:
(define (make-move state source target)
(define (alter-tower tower index disc)
(cond ((= index source) (cdr tower)) ; remove a disc
((= index target) (cons disc tower)) ; add a disc
(else tower))) ; this tower wasn't changed
(let ((disc (car (list-ref state source))))
(for/list ([(tower idx) (in-indexed state)])
(alter-tower tower idx disc))))
Many functional languages have a map that can take a predicate which consumes the index, so those two lines might instead look like:
(map (lambda (tower idx) (alter-tower tower idx disc)) state)
So depending on your Scheme dialect and libraries it might be different. (I don't think there's an SRFI for this, but I might be mistaken.) Or you could always write the above version of map yourself.
Related
I wonder how do you, experienced lispers / functional programmers usually make decision what to use. Compare:
(define (my-map1 f lst)
(reverse
(let loop ([lst lst] [acc '()])
(if (empty? lst)
acc
(loop (cdr lst) (cons (f (car lst)) acc))))))
and
(define (my-map2 f lst)
(if (empty? lst)
'()
(cons (f (car lst)) (my-map2 f (cdr lst)))))
The problem can be described in the following way: whenever we have to traverse a list, should we collect results in accumulator, which preserves tail recursion, but requires list reversion in the end? Or should we use unoptimized recursion, but then we don't have to reverse anything?
It seems to me the first solution is always better. Indeed, there's additional complexity (O(n)) there. However, it uses much less memory, let alone calling a function isn't done instantly.
Yet I've seen different examples where the second approach was used. Either I'm missing something or these examples were only educational. Are there situations where unoptimized recursion is better?
When possible, I use higher-order functions like map which build a list under the hood. In Common Lisp I also tend to use loop a lot, which has a collect keyword for building list in a forward way (I also use the series library which also implements it transparently).
I sometimes use recursive functions that are not tail-recursive because they better express what I want and because the size of the list is going to be relatively small; in particular, when writing a macro, the code being manipulated is not usually very large.
For more complex problems I don't collect into lists, I generally accept a callback function that is being called for each solution. This ensures that the work is more clearly separated between how the data is produced and how it is used.
This approach is to me the most flexible of all, because no assumption is made about how the data should be processed or collected. But it also means that the callback function is likely to perform side-effects or non-local returns (see example below). I don't think it is particularly a problem as long the the scope of the side-effects is small (local to a function).
For example, if I want to have a function that generates all natural numbers between 0 and N-1, I write:
(defun range (n f)
(dotimes (i n)
(funcall f i)))
The implementation here iterates over all values from 0 below N and calls F with the value I.
If I wanted to collect them in a list, I'd write:
(defun range-list (N)
(let ((list nil))
(range N (lambda (v) (push v list)))
(nreverse list)))
But, I can also avoid the whole push/nreverse idiom by using a queue. A queue in Lisp can be implemented as a pair (first . last) that keeps track of the first and last cons cells of the underlying linked-list collection. This allows to append elements in constant time to the end, because there is no need to iterate over the list (see Implementing queues in Lisp by P. Norvig, 1991).
(defun queue ()
(let ((list (list nil)))
(cons list list)))
(defun qpush (queue element)
(setf (cdr queue)
(setf (cddr queue)
(list element))))
(defun qlist (queue)
(cdar queue))
And so, the alternative version of the function would be:
(defun range-list (n)
(let ((q (queue)))
(range N (lambda (v) (qpush q v)))
(qlist q)))
The generator/callback approach is also useful when you don't want to build all the elements; it is a bit like the lazy model of evaluation (e.g. Haskell) where you only use the items you need.
Imagine you want to use range to find the first empty slot in a vector, you could do this:
(defun empty-index (vector)
(block nil
(range (length vector)
(lambda (d)
(when (null (aref vector d))
(return d))))))
Here, the block of lexical name nil allows the anonymous function to call return to exit the block with a return value.
In other languages, the same behaviour is often reversed inside-out: we use iterator objects with a cursor and next operations. I tend to think it is simpler to write the iteration plainly and call a callback function, but this would be another interesting approach too.
Tail recursion with accumulator
Traverses the list twice
Constructs two lists
Constant stack space
Can crash with malloc errors
Naive recursion
Traverses list twice (once building up the stack, once tearing down the stack).
Constructs one list
Linear stack space
Can crash with stack overflow (unlikely in racket), or malloc errors
It seems to me the first solution is always better
Allocations are generally more time-expensive than extra stack frames, so I think the latter one will be faster (you'll have to benchmark it to know for sure though).
Are there situations where unoptimized recursion is better?
Yes, if you are creating a lazily evaluated structure, in haskell, you need the cons-cell as the evaluation boundary, and you can't lazily evaluate a tail recursive call.
Benchmarking is the only way to know for sure, racket has deep stack frames, so you should be able to get away with both versions.
The stdlib version is quite horrific, which shows that you can usually squeeze out some performance if you're willing to sacrifice readability.
Given two implementations of the same function, with the same O notation, I will choose the simpler version 95% of the time.
There are many ways to make recursion preserving iterative process.
I usually do continuation passing style directly. This is my "natural" way to do it.
One takes into account the type of the function. Sometimes you need to connect your function with the functions around it and depending on their type you can choose another way to do recursion.
You should start by solving "the little schemer" to gain a strong foundation about it. In the "little typer" you can discover another type of doing recursion, founded on other computational philosophy, used in languages like agda, coq.
In scheme you can write code that is actually haskell sometimes (you can write monadic code that would be generated by a haskell compiler as intermediate language). In that case the way to do recursion is also different that "usual" way, etc.
false dichotomy
You have other options available to you. Here we can preserve tail-recursion and map over the list with a single traversal. The technique used here is called continuation-passing style -
(define (map f lst (return identity))
(if (null? lst)
(return null)
(map f
(cdr lst)
(lambda (r) (return (cons (f (car lst)) r))))))
(define (square x)
(* x x))
(map square '(1 2 3 4))
'(1 4 9 16)
This question is tagged with racket, which has built-in support for delimited continuations. We can accomplish map using a single traversal, but this time without using recursion. Enjoy -
(require racket/control)
(define (yield x)
(shift return (cons x (return (void)))))
(define (map f lst)
(reset (begin
(for ((x lst))
(yield (f x)))
null)))
(define (square x)
(* x x))
(map square '(1 2 3 4))
'(1 4 9 16)
It's my intention that this post will show you the detriment of pigeonholing your mind into a particular construct. The beauty of Scheme/Racket, I have come to learn, is that any implementation you can dream of is available to you.
I would highly recommend Beautiful Racket by Matthew Butterick. This easy-to-approach and freely-available ebook shatters the glass ceiling in your mind and shows you how to think about your solutions in a language-oriented way.
I've written some simple loops with recursion and the loop macro but the thing that bothers me is that counting up needs two parameters and counting down doesn't.
Does an example exist?
The start of this question was just how to print something that increments up. The first function 'printsomestuff' was where I started.
(defun printsomestuff (stuff times)
(if (= times 0)
'im-the-return-value
(progn
(print stuff)
(printsomestuff stuff (1- times)))))
(defun counting-down (topnumber)
(if (= topnumber 0)
'done
(progn
(print topnumber)
(counting (- topnumber 1)))))
(defun loopcounting (uptonumber)
(loop for i from 1 to uptonumber
do (print i)))
(defun recurcounting-up (uptonumber)
(let ((incrementer 0))
(if
(= incrementer uptonumber)
'done
(progn
(print incrementer)
(recurcounting-up (+ incrementer 1))))))
(defun recur-counting-up-two (uptonumber startnumber)
(if (> startnumber uptonumber)
'done
(progn
(print startnumber)
(recur-counting-up-two uptonumber (+ startnumber 1)))))
recurcounting-up infinitely loops with 0 because the reset of the incrementer on every function call. That is not what I wanted.
It has nothing to do with whether you're counting up or down. The issue is whether the base case of the recursion can be hard-coded in the function or needs to be supplied as a parameter. In your counting down examples, you always end at 0, so it doesn't need to be a parameter -- you only need a parameter for the current number. But in your counting up example, the ending number can't be put into the code, so it needs that as a second parameter.
If you were always counting up to 100, you could code that just like your counting down examples. Similarly, if you wanted to count down to an arbitrary number, not just 0, you would need two parameters.
To add to what Barmar said (his answer actually answers the question, this is really a comment on it), if you use local functions then you can make the recursive function have only a single parameter. You can even make it count in the appropriate direction. But this is just a hack: if the base case or the step of some recursion is not fixed (ie are not always 0 & 1- say) then you are going to have to provide them.
Counting in either direction in CL:
(defun count/printing (from to)
(let ((next (if (< from to) #'1+ #'1-)))
(labels ((count (i)
(print i)
(if (= i to)
i
(count (funcall next i)))))
(count from))))
and in Racket, which makes it a little more elegant by being a Lisp-1 & having named let:
(define (count/printing from to)
(define next (if (< from to) add1 sub1))
(let count ([i from])
(displayln i)
(if (= i to)
i
(count (next i)))))
My solution looks like this after taking into account tfb's answer.
(defun recur-counting-up-two (uptonumber startnumber)
(if (> startnumber uptonumber)
'done
(progn
(print startnumber)
(recur-counting-up-two uptonumber (+ startnumber 1)))))
(defun count-up (uptonumber)
(recur-counting-up-two uptonumber 0))
It just creates a second toplevel wrapper function with one parameter passed in hard coded.
Although tfb's answer might seem more compact I find this to be more readable from a distance. Less center embedding is always a good thing in a language that does it too much already for readability.
I've written two versions of a lisp function. The main difference between the two is that one is done with recursion, while the other is done with iteration.
Here's the recursive version (no side effects!):
(defun simple-check (counter list)
"This function takes two arguments:
the number 0 and a list of atoms.
It returns the number of times the
atom 'a' appears in that list."
(if (null list)
counter
(if (equal (car list) 'a)
(simple-check (+ counter 1) (cdr list))
(simple-check counter (cdr list)))))
Here's the iterative version (with side effects):
(defun a-check (counter list)
"This function takes two arguments:
the number 0 and a list of atoms.
It returns the number of times the
atom 'a' appears in that list."
(dolist (item list)
(if (equal item 'a)
(setf counter (+ counter 1))
(setf counter (+ counter 0))))
counter)
As far as I know, they both work. But I'd really like to avoid side-effects in the iterative version. Two questions I'd like answered:
Is it possible to avoid side effects and keep iteration?
Assuming the answer to #1 is a yes, what are the best ways to do so?
For completeness, note that Common Lisp has a built-in COUNT:
(count 'a list)
In some ways, the difference between side-effect or no side-effect is a bit blurred. Take the following loop version (ignoring that loop also has better ways):
(loop :for x :in list
:for counter := (if (eq x 'a) (1+ counter) counter)
:finally (return counter))
Is counter set at each step, or is it rebound? I. e., is an existing variable modified (like in setf), or is a new variable binding created (as in a recursion)?
This do version is very much like the recursive version:
(do ((list args (rest list))
(counter 0 (+ counter (if (eq (first list) 'a) 1 0))))
((endp list) counter))
Same question as above.
Now the “obvious” loop version:
(loop :for x :in list
:count (eq x 'a))
There isn't even an explicit variable for the counter. Are there side-effects?
Internally, of course there are effects: environments are created, bindings established, and, especially if there is tail call optimization, even in the recursive version destroyed/replaced at each step.
I see as side effects only effects that affect things outside of some defined scope. Of course, things appear more elegant if you can also on the level of your internal definition avoid the explicit setting of things, and instead use some more declarative expression.
You can also iterate with map, mapcar and friends.
https://lispcookbook.github.io/cl-cookbook/iteration.html
I also suggest a look at remove-if[-not] and other reduce and apply:
(length (remove-if-not (lambda (x) (equal :a x)) '(:a :b :a))) ;; 2
Passing counter to the recursive procedure was a means to enable a tail recursive definition. This is unnecessary for the iterative definition.
As others have pointed out, there are several language constructs which solve the stated problem elegantly.
I assume you are interested in this in a more general sense such as when you cannot find
a language feature that solves a problem directly.
In general, one can maintain a functional interface by keeping the mutation private as below:
(defun simple-check (list)
"return the number of times the symbol `a` appears in `list`"
(let ((times 0))
(dolist (elem list times)
(when (equal elem 'a)
(incf times)))))
I'm trying to reverse a list in scheme and I came up with to the following solution:
(define l (list 1 2 3 4))
(define (reverse lista)
(car (cons (reverse (cdr (cons 0 lista))) 0)))
(display (reverse l))
Although it works I don't really understand why it works.
In my head, it would evaluate to a series of nested cons until cons of () (which the cdr of a list with one element).
I guess I am not understanding the substitution model, could someone explain me why it works?
Obs:
It is supposed to work only in not nested lists.
Taken form SICP, exercise 2.18.
I know there are many similar questions, but as far as I saw, none presented
this solution.
Thank you
[As this happens quite often, I write the answer anyway]
Scheme implementations do have their builtin versions of reverse, map, append etc. as they are specified in RxRS (e.g. https://www.cs.indiana.edu/scheme-repository/R4RS/r4rs_8.html).
In the course of learning scheme (and actually any lisp dialect) it's really valuable to implement them anyway. The danger is, one's definition can collide with the built-in one (although e.g. scheme's define or lisp's label should shadow them). Therefore it's always worth to call this hand-made implementation with some other name, like "my-reverse", "my-append" etc. This way you will save yourself much confusion, like in the following:
(let ([append
(lambda (xs ys)
(if (null? xs)
ys
(cons (car xs) (append (cdr xs) ys))))])
(append '(hello) '(there!)))
-- this one seems to work, creating a false impression that "let" works the same as "letrec". But just change the name to "my-append" and it breaks, because at the moment of evaluating the lambda form, the symbol "my-append" is not yet bound to anything (unlike "append" which was defined as a builtin procedure).
Of course such let form will work in a language with dynamic scoping, but scheme is lexical (with the exception of "define"s), and the reason is referential transparency (but that's so far offtopic that I can only refer interested reader to one of the lambda papers http://repository.readscheme.org/ftp/papers/ai-lab-pubs/AIM-453.pdf).
This reads pretty much the same as the solutions in other languages:
if the list is empty, return an empty list. Otherwise ...
chop off the first element (CAR)
reverse the remainder of the list (CDR)
append (CONS) the first element to that reversal
return the result
Now ... given my understanding from LISP days, the code would look more like this:
(append (reverse (cdr lista)) (list (car lista)))
... which matches my description above.
There are several ways to do it. Here is another:
(define my-reverse
(lambda (lst)
(define helper
(lambda (lst result)
(if (null? lst)
result
(helper (cdr lst) (cons (car lst) result)))))
(helper lst '())))
NOTE: I would like to do this without rackets built in exceptions if possible.
I have many functions which call other functions and may recursively make a call back to the original function. Under certain conditions along the way I want to stop any further recursive steps, and no longer call any other functions and simply return some value/string (the stack can be ignored if the condition is met).. here is a contrived example that hopefully will show what I'm trying to accomplish:
(define (add expr0 expr1)
(cond
[(list? expr0) (add (cadr expr0) (cadr (cdr expr0)))]
[(list? expr1) (add (cadr expr1) (cadr (cdr expr1)))]
[else (if (or (equal? expr0 '0) (equal? expr1 '0))
'(Adding Zero)
(+ expr0 expr1))]
))
If this were my function and I called it with (add (add 2 0) 3), Then the goal would be to simply return the entire string '(Adding Zero) ANYTIME that a zero is one of the expressions, instead of making the recursive call to (add '(Adding Zero) 3)
Is there a way to essentially "break" out of recursion? My problem is that if i'm already deep inside then it will eventually try to evaluate '(Adding Zero) which it doesn't know how to do and I feel like I should be able to do this without making an explicit check to each expr..
Any guidance would be great.
In your specific case, there's no need to "escape" from normal processing. Simply having '(Adding Zero) in tail position will cause your add function to return (Adding Zero).
To create a situation where you might need to escape, you need something a
little more complicated:
(define (recursive-find/collect collect? tree (result null))
(cond ((null? tree) (reverse result))
((collect? tree) (reverse (cons tree result)))
((not (pair? tree)) (reverse result))
(else
(let ((hd (car tree))
(tl (cdr tree)))
(cond ((collect? hd)
(recursive-find/collect collect? tl (cons hd result)))
((pair? hd)
(recursive-find/collect collect? tl
(append (reverse (recursive-find/collect collect? hd)) result)))
(else (recursive-find/collect collect? tl result)))))))
Suppose you wanted to abort processing and just return 'Hahaha! if any node in the tree had the value 'Joker. Just evaluating 'Hahaha! in tail position
wouldn't be enough because recursive-find/collect isn't always used in
tail position.
Scheme provides continuations for this purpose. The easiest way to do it in my particular example would be to use the continuation from the predicate function, like this:
(call/cc
(lambda (continuation)
(recursive-find/collect
(lambda (node)
(cond ((eq? node 'Joker)
(continuation 'Hahaha!)) ;; Processing ends here
;; Otherwise find all the symbols
;; in the tree
(else (symbol? node))))
'(Just 1 arbitrary (tree (stucture) ((((that "has" a Joker in it)))))))))
A continuation represents "the rest of the computation" that is going to happen after the call/cc block finishes. In this case, it just gives you a way to escape from the call/cc block from anywhere in the stack.
But continuations also have other strange properties, such as allowing you to jump back to whatever block of code this call/cc appears in even after execution has left this part of the program. For example:
(define-values a b (call/cc
(lambda (cc)
(values 1 cc))))
(cc 'one 'see-see)
In this case, calling cc jumps back to the define-values form and redefines a and b to one and see-see, respectively.
Racket also has "escape continuations" (call/ec or let/ec) which can escape from their form, but can't jump back into it. In exchange for this limitation you get better performance.