format integer as chars in common lisp - common-lisp

What's the best way to format output a integer as char sequences? I try below code block, it works but not sure if it's right to do it:
(defun int2chars(x)
(format t "~c~c~c~c~%"
(code-char (ldb (byte 8 24) x))
(code-char (ldb (byte 8 16) x))
(code-char (ldb (byte 8 8) x))
(code-char (ldb (byte 8 0) x))
))
(defun test()
(let ((x #x75756964))
(int2chars x)))
(test)
Input is 0x75756964 and output is uuid

You could write a function that works for integers that are larger or shorter than 32 bits:
(defun bytes-from-integer (integer)
(check-type integer (integer 0))
(loop
with size = (* 8 (1- (ceiling (integer-length integer) 8)))
for offset from size downto 0 by 8
collect (ldb (byte 8 offset) integer)))
(bytes-from-integer #x75756964)
=> (117 117 105 100)
(bytes-from-integer #x7575696475756964)
=> (117 117 105 100 117 117 105 100)
Then, you convert to a string as follows:
(map 'string #'code-char (bytes-from-integer #x75756964))
=> "uuid"
Note: CHECK-TYPE is a macro that checks whether a place satisfies a given type expression. Above, the place is the integer variable, and the type is (integer 0), which is equivalent to (integer 0 *), also known as unsigned-byte.

Related

Why are lists faster then vectors for simple access?

I know there are similar question, e.g. Arrays vs. lists in Lisp: Why are lists so much faster in the code below?, but lists seem to be faster then vectors even for simple element access, which is counter-intuitive. Here is my example:
(let ((x '(0 1 2 3 4 5 6 7 8 9)))
(time (dotimes (i 1000000000) (setf (nth 9 x) 0))))
(let ((x #(0 1 2 3 4 5 6 7 8 9)))
(time (dotimes (i 1000000000) (setf (aref x 9) 0))))
The first block runs almost two times faster on my machine, with SBCL, than the second block. (And if I test read access times, then both lists and vectors have almost the same time). I would expect the list to be some 10 times slower, because it needs to traverse to the end to find the 9th element. Why is list faster?
The strange behaviour is due to the fact that you are modifying a constant data, and this can lead to an undefined behaviour (see the manual):
The consequences are undefined if literal objects (including quoted objects) are destructively modified.
If you change the the two expressions to modify two non-literal data structures, like in:
(let ((x (list 0 1 2 3 4 5 6 7 8 9)))
(time (dotimes (i 1000000000) (setf (nth 9 x) 0))))
(let ((x (vector 0 1 2 3 4 5 6 7 8 9)))
(time (dotimes (i 1000000000) (setf (aref x 9) 0))))
then the results will be completely different as very well shown in the other answer.
I cannot reproduce your observations. Here below is what I measure, along with two other tests with different types of arrays. Note first that my setup script does the following:
(sb-ext:restrict-compiler-policy 'debug 3)
(sb-ext:restrict-compiler-policy 'safety 3)
This might have an impact on code compilation.
Your tests
(print :list)
(let ((x (list 0 1 2 3 4 5 6 7 8 9)))
(time (dotimes (i 1000000000) (setf (nth 9 x) 0))))
(print :simple-vector)
(let ((x (vector 0 1 2 3 4 5 6 7 8 9)))
(time (dotimes (i 1000000000) (setf (aref x 9) 0))))
The trace is as follows:
:LIST
Evaluation took:
6.649 seconds of real time
6.649545 seconds of total run time (6.649545 user, 0.000000 system)
100.02% CPU
21,224,869,441 processor cycles
0 bytes consed
:SIMPLE-VECTOR
Evaluation took:
0.717 seconds of real time
0.716708 seconds of total run time (0.716708 user, 0.000000 system)
100.00% CPU
2,287,130,610 processor cycles
0 bytes consed
Regarding your original question, there is an almost 10 speed factor (9.27) difference between using lists and vectors. I don't know why your tests show differently (edit: so apparently it was related to undefined behaviours, I saw you mutated constant data and fixed it in my code without thinking it could be related :/)
Specialized arrays
I also tried to describe the array as precisely as possible, by declaring in its type the kind of elements it holds, (mod 10), and the array dimensions, (10). The actual array element type in SBCL is (UNSIGNED-BYTE 4), which means the array is likely to packed: multiple array elements can be stored in a machine word (32 or 64bits). Packing is good for space but needs coding/decoding steps when storing/accessing elements.
(print :packed-array)
(let ((x (make-array 10
:element-type '(mod 10)
:initial-contents '(0 1 2 3 4 5 6 7 8 9))))
(declare (type (array (mod 10) (10)) x)
(optimize (speed 3)))
(time (dotimes (i 1000000000)
(setf (aref x 9) (the (mod 10) 0)))))
I also have a version where the actual array element type (unsigned-byte 32), which should avoid doing conversions:
(print :unpacked-array)
(let ((x (make-array 10
:element-type '(unsigned-byte 32)
:initial-contents '(0 1 2 3 4 5 6 7 8 9))))
(declare (type (array (unsigned-byte 32) (10)) x)
(optimize (speed 3)))
(time (dotimes (i 1000000000)
(setf (aref x 9) (the (mod 10) 0)))))
Additional tests:
:PACKED-ARRAY
Evaluation took:
1.168 seconds of real time
1.167929 seconds of total run time (1.167929 user, 0.000000 system)
100.00% CPU
3,727,528,968 processor cycles
0 bytes consed
Here you can see that using the most precise type actually slows the tests in that particular case. This can probably be explained by the overhead of decoding/encoding operations (?)
:UNPACKED-ARRAY
Evaluation took:
0.231 seconds of real time
0.231094 seconds of total run time (0.231094 user, 0.000000 system)
100.00% CPU
737,633,062 processor cycles
0 bytes consed
With arrays of 32bits values, the execution time is smaller.
If you call disassemble for tests on both kinds of vectors (just remove the call to time that adds a lot of noise, and maybe lower the debug levels), eventually the difference boils down to which type of register is used in the loop:
The simple vector uses 64 bits (RCX) because the vector must be able to store objects of type T:
; C0: L2: B900000000 MOV ECX, 0
; C5: 48894A49 MOV [RDX+73], RCX
; C9: 4883C002 ADD RAX, 2
; CD: L3: 483D00943577 CMP RAX, 2000000000
; D3: 7CEB JL L2
The test with 32 bits array uses the ECX (32 bits) register.
; 960: L2: 31C9 XOR ECX, ECX
; 962: 894A25 MOV [RDX+37], ECX
; 965: 4883C002 ADD RAX, 2
; 969: L3: 483D00943577 CMP RAX, 2000000000
; 96F: 7CEF JL L2
Also, the offsets are different, but consistent with the types:
- 37 = 4 (bytes) * 9 (index) + 1 (storage for array size?)
- 73 = 8 (bytes) * 9 (index) + 1 (storage for array size?)

Clisp error : Variable has no value (In this Binary search program high and low has no value)

Simple program for binary search.
elements contain no. of elements
then array contains those elements
then q contains no. of queries
search contains element to be searched.
Why this error is coming about high and low has no value after some iterations.
Kindly help :)
My Code :-
(setf elements (parse-integer (read-line)))
(setf array (make-array elements :fill-pointer 0))
(dotimes (i elements) (vector-push (parse-integer (read-line)) array))
(setf q (parse-integer (read-line)))
(defvar *mid*)
(dotimes (i q)
(setf search (parse-integer (read-line)))
(do ((low 0)
(high (- elements 1))
(mid (floor (+ low high) 2)
(floor (+ low high) 2)))
((>= low high) (setf *mid* nil))
(cond
((eql (elt array mid) search) (setf *mid* mid))
((< (elt array mid) search) (setf high (- mid 1)))
(t (setf low (+ mid 1)))))
(format t "~a" *mid*))
Your code is a fine example of an old adage:
the determined Real Programmer can write FORTRAN programs in any language.
Unfortunately Lisp programmers are generally quiche-eating hippies: so here is one quiche-eater's solution to this problem, using notions not present when FORTRAN IV was handed down to us from above on punched stones. These notions are therefore clearly heretical, but nonetheless useful.
Assuming this is homework, you probably will not be able to submit this answer.
Reading the data
First of all we'll write some functions which read the specification of the problem from a stream or file. I have inferred what it is from your code.
(defun stream->search-spec (stream)
;; Read a search vector from a stream: return a vector to be searched
;; and a vector of elements to search for.
;;
;; This function defines what is in files: each line contains an
;; integer, and the file contains a count followed by that many
;; lines, which specifies first the vector to be searched, and then
;; the things to search for.
;;
;; This relies on PARSE-INTEGER & READ-LINE to puke appropriately.
(flet ((read-vector ()
(let* ((elts (parse-integer (read-line stream)))
(vec (make-array elts :element-type 'integer))) ;won't help
(dotimes (i elts vec)
(setf (aref vec i) (parse-integer (read-line stream)))))))
(values (read-vector) (read-vector))))
(defun file->search-spec (file)
;; Read a search vector from a file. This is unused below but is
;; useful to have.
(with-open-file (in file)
(stream->search-spec in)))
(defun validate-sorted-vector (v)
;; check that V is a sorted vector
(dotimes (i (- (length v) 1) v)
(unless (<= (aref v i) (aref v (1+ i)))
(return-from validate-sorted-vector nil))))
The last function is used below to sanity check the data, since the search algorithm assumes the vector is sorted.
The search function
This implements binary search in the same way yours tries to do. Rather than doing it with loops and explicit assignemnt it does it using a local recursive function, which is far easier to understand. There are also various sanity checks and optionally debugging output. In any implementation which optimises tail calls this will be optimised to a loop; in implementations which don't then there will be a few extra function calls but stack overflow problems are very unlikely (think about why: how big would the vector need to be?).
(defun search-sorted-vector-for (vector for &key (debug nil))
;; search a sorted vector for some value. If DEBUG is true then
;; print what we're doing. Return the index, or NIL if FOR is not
;; present.
(when debug
(format *debug-io* "~&* ~D:~%" for))
(labels ((search (low mid high)
(when debug
(format *debug-io* "~& ~10D ~10D ~10D~%" low mid high))
(if (<= low mid high)
;; more to do
(let ((candidate (aref vector mid)))
(cond ((= candidate for)
;; found it
mid)
((< candidate for)
;; look higher
(search (1+ mid) (floor (+ high mid 1) 2) high))
((> candidate for)
;; look lower
(search low (floor (+ low mid) 2) (1- mid)))
(t
;; can't happen
(error "mutant death"))))
;; low = high: failed
nil)))
(let ((high (1- (length vector))))
(search 0 (floor high 2) high))))
Putting the previous two things together.
search-sorted-vector-with-search-vector will repeatedly search using the two vectors that the *->search-spec functions return. stream->search-results uses stream->search-spec and then calls this on its values. file->search-results does it all from a file.
(defun search-sorted-vector-with-search-vector (vector searches &key (debug nil))
;; do a bunch of searches, returning a vector of results.
(let ((results (make-array (length searches))))
(dotimes (i (length searches) results)
(setf (aref results i) (search-sorted-vector vector (aref searches i)
:debug debug)))))
(defun stream->search-results (stream &key (debug nil))
;; Read search specs from a stream, and search according to them.
;; Return the vector of results, the vector being searched and the
;; vector of search specifications.
(multiple-value-bind (to-search search-specs) (stream->search-spec stream)
(when debug
(format *debug-io* "~&searching ~S~% for ~S~&" to-search search-specs))
(assert (validate-sorted-vector to-search) (to-search) "not sorted")
(values (search-sorted-vector-with-search-vector to-search search-specs
:debug debug)
to-search search-specs)))
(defun file->search-results (file &key (debug nil))
;; sort from a file
(with-open-file (in file)
(stream->search-results in :debug debug)))
Using it
Given a file /tmp/x.dat with:
9
1
10
100
101
102
103
200
201
400
6
10
102
200
1
400
99
then:
> (file->search-results "/tmp/x.dat" :debug t)
searching #(1 10 100 101 102 103 200 201 400)
for #(10 102 200 1 400 99)
* 10:
0 4 8
0 2 3
0 1 1
* 102:
0 4 8
* 200:
0 4 8
5 6 8
* 1:
0 4 8
0 2 3
0 1 1
0 0 0
* 400:
0 4 8
5 6 8
7 7 8
8 8 8
* 99:
0 4 8
0 2 3
0 1 1
2 1 1
#(1 4 6 0 8 nil)
#(1 10 100 101 102 103 200 201 400)
#(10 102 200 1 400 99)
You can see that the last search failed (99 is not in the vector).

Scheme - List of Fibonacci numbers up to certain value

I am trying to write a function that creates a list of the fibonacci sequence but stops when a certain value is found in the list, then returns that list (I hope that makes sense).
So for example if I give it fib-list(55), the function should return:
(1 1 2 3 5 8 13 21 34 55)
So it's not the 55th fibonacci number I want, its the list UP TO the value 55.
The code I have for returning the list so far looks like this:
; Create a list of the fibonacci sequence up to n.
(define (fib-list n)
; n = n, f2 = 1, f1 = 1, fs = a list.
(let loop ((n n) (f2 1) (f1 1) (fs (list)))
(cond
; If n = 0, return reversed list.
((zero? n) (reverse fs))
; Check if n is in list. If so, return list.
((equal? n (car fs)) fs)
;Else, find the next fibonacci number and add it to the list.
(else (loop (- n 1) f1 (+ f2 f1) (cons f2 fs))))))
(display (fib-list 55))
My main problem is finding if an element is in the list, because at the moment I just get an error on the line where I am trying to write the ((equal? statement.
The error says:
mcar: contract violation
expected: mpair?
given: '()
I am still very VERY new to Scheme, so my understanding of the language as a whole isn't great. So please be gentle when telling me why my code sucks/doesn't make sense.
(list) creates an empty list, and on the first iteration you get to (car fs), which tries to apply car to an empty list, and that's an error.
Your code seems a bit confused about the nature of n.
Your description says that it's the largest number you want, but you're recursing like you want the n:th Fibonacci number - terminating on (zero? n) and recursing on (- n 1).
When you're recursing you're still looking for numbers up to the same limit.
Thus, you should not decrement your limit and terminate on zero, you should leave the limit alone and terminate when you reach larger numbers.
Here's how I would write it:
The initial list is (1 1)
At each step:
Compute the next fibonacci number
If this is greater than the limit, reverse the accumulator list and return it
Otherwise, cons it to the accumulator and recurse with the "new" last two fibonacci number.
In code:
(define (fib-list n)
(let loop ((f2 1) (f1 1) (fs '(1 1)))
(let ((next (+ f1 f2)))
(if (> next n)
(reverse fs)
(loop f1 next (cons next fs))))))
Here's another way you can do it using continuation-passing style. By adding a continuation parameter to our loop, we effectively create our own return mechanism. One unique property of this implementation is the output list is built in forward order and does not need to be reversed when n reaches zero.
(define (fib-list n)
(let loop ((n n) (a 0) (b 1) (return identity))
(if (zero? n)
(return empty)
(loop (sub1 n)
b
(+ a b)
(lambda (rest) (return (cons a rest)))))))
(fib-list 10)
;; '(0 1 1 2 3 5 8 13 21 34)
Reading your question a little closer, in fib-list(N) you need N to be the stopping condition for your loop, not the Nth term in the list. This is actually easier to implement as there's no need to count the number of terms generated.
(define (fib-list max)
(let loop ((a 0) (b 1) (return identity))
(if (> a max)
(return empty)
(loop b
(+ a b)
(lambda (rest) (return (cons a rest)))))))
(fib-list 55)
;; '(0 1 1 2 3 5 8 13 21 34 55)
(fib-list 1000)
;; '(0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987)
What's going wrong with the car function?
The car function takes the first element of a list, but if the list is empty it doesn't have a first element. The fs list starts out as empty. When you try to take the first element of an empty list you get this error message:
> (car (list))
mcar: contract violation
expected: mpair?
given: ()
If the list isn't empty, then it has a first element, and it's fine:
> (car (list 4 5 6))
4
Following what you meant in the comment
However, your comment "Check if n is in list" leads me to believe that (equal? n (car fs)) is not what you want anyway. The function for determining whether an element is in a list is called member.
#!r6rs
(import (rnrs base)
(rnrs lists))
> (if (member 4 (list 1 2 4 8))
"it's in the list"
"go fish")
"it's in the list"
> (if (member 5 (list 1 2 4 8))
"it's in the list"
"go fish")
"go fish"
So with that (equal? n (car fs)) test replaced with (member n fs), your code looks like:
; Create a list of the fibonacci sequence up to n.
(define (fib-list n)
; n = n, f2 = 1, f1 = 1, fs = a list.
(let loop ((n n) (f2 1) (f1 1) (fs (list)))
(cond
; If n = 0, return reversed list.
((zero? n) (reverse fs))
; Check if n is in list. If so, return list.
((member n fs) fs)
;Else, find the next fibonacci number and add it to the list.
(else (loop (- n 1) f1 (+ f2 f1) (cons f2 fs))))))
> (fib-list 55)
(10946 6765 4181 2584 1597 987 610 377 233 144 89 55 34 21 13 8 5 3 2 1 1)
This is not the answer you wanted though; you wanted (1 1 2 3 5 8 13 21 34 55).
Why is the list going past 55?
One of the problems is that the n is shadowed, in the same way that in this expression:
> (let ([n 5])
(let ([n 10])
n))
10
The n in the body refers to 10 instead of 5.
The result is going past 55 because inside the loop n is shadowed and has become a different number. I'm guessing in your comment about "check if n is in list", you meant "check if the original n is in list". To do that you have to rename one of the ns:
> (let ([orig-n 5])
(let ([n 10])
orig-n))
5
In the context of your code:
; Create a list of the fibonacci sequence up to n.
(define (fib-list orig-n)
; n = n, f2 = 1, f1 = 1, fs = a list.
(let loop ((n orig-n) (f2 1) (f1 1) (fs (list)))
(cond
; If n = 0, return reversed list.
((zero? n) (reverse fs))
; Check if orig-n is in list. If so, return list.
((member orig-n fs) fs)
;Else, find the next fibonacci number and add it to the list.
(else (loop (- n 1) f1 (+ f2 f1) (cons f2 fs))))))
> (fib-list 55)
(55 34 21 13 8 5 3 2 1 1)
Reversing
This is closer, but it's reversed. You have two base cases, the (zero? n) case and the (member orig-n fs) case. In one of those it's reversed and in one of them it's not. Changing them both to call reverse fixes it:
; Create a list of the fibonacci sequence up to n.
(define (fib-list orig-n)
; n = n, f2 = 1, f1 = 1, fs = a list.
(let loop ((n orig-n) (f2 1) (f1 1) (fs (list)))
(cond
; If n = 0, return reversed list.
((zero? n) (reverse fs))
; Check if orig-n is in list. If so, return reversed list.
((member orig-n fs) (reverse fs))
;Else, find the next fibonacci number and add it to the list.
(else (loop (- n 1) f1 (+ f2 f1) (cons f2 fs))))))
> (fib-list 55)
(1 1 2 3 5 8 13 21 34 55)
Small numbers
This is correct on large Fibonacci numbers like 55, but it still does something weird on small numbers:
> (fib-list 2)
(1 1)
> (fib-list 3)
(1 1 2)
If you only want it to stop when it gets to orig-n, then maybe the decreasing n argument is not needed, and is actually making it stop too early. Removing it (and removing the zero check for it) makes the member check the only stopping case.
This is dangerous, because it could go into an infinite loop if you give it a non-Fibonacci number as input. However, it fixes the small-number examples:
; Create a list of the fibonacci sequence up to n.
; The `orig-n` MUST be a fibonacci number to begin with,
; otherwise this loops forever.
(define (fib-list orig-n)
; f2 = 1, f1 = 1, fs = a list.
(let loop ((f2 1) (f1 1) (fs (list)))
(cond
; Check if orig-n is in list. If so, return reversed list.
((member orig-n fs) (reverse fs))
;Else, find the next fibonacci number and add it to the list.
(else (loop f1 (+ f2 f1) (cons f2 fs))))))
> (fib-list 55)
(1 1 2 3 5 8 13 21 34 55)
> (fib-list 2)
(1 1 2)
> (fib-list 3)
(1 1 2 3)
And finally, consider what happens vs. what should happen if you give it a number like 56.
> (fib-list 56)
;infinite loop
This is a design decision that you have not specified in your question (yet), but there are ways of solving it either way.
Update: orig-n or greater
I should have specified that I need to check if there is a number that is greater than OR equal to orig-n. Can I still use the member function to check for this or will I need to use something different?
You will have to use something different. Just above member in the documentation is the memp function (you could also use exists in this case). The mem is short for member, and the p is short for "predicate". It determines whether any member of the list matches a certain predicate.
> (if (memp positive? (list -4 -2 -3 5 -1))
"one of them is positive"
"go fish")
"one of them is positive"
> (if (memp positive? (list -4 -2 -3 -5 -1))
"one of them is positive"
"go fish")
"go fish"
> (define (five-or-greater? n)
(>= n 5))
> (if (memp five-or-greater? (list -4 -2 -3 6 -1))
"one of them is equal to 5 or greater"
"go fish")
"one of them is equal to 5 or greater"
> (if (memp five-or-greater? (list -4 -2 -3 4 -1))
"one of them is equal to 5 or greater"
"go fish")
"go fish"
To use it for "orig-n or greater", you would have to define a function like:
(define (orig-n-or-greater? n)
(>= n orig-n))
As a local function inside your main function, so that it can refer to orig-n. Then you can use it like (memp orig-n-or-greater? fs).
; Create a list of the fibonacci sequence up to n.
(define (fib-list orig-n)
(define (orig-n-or-greater? n)
(>= n orig-n))
; f2 = 1, f1 = 1, fs = a list.
(let loop ((f2 1) (f1 1) (fs (list)))
(cond
; Check if orig-n or greater is in list. If so, return reversed list.
((memp orig-n-or-greater? fs) (reverse fs))
;Else, find the next fibonacci number and add it to the list.
(else (loop f1 (+ f2 f1) (cons f2 fs))))))
> (fib-list 3)
(1 1 2 3)
> (fib-list 55)
(1 1 2 3 5 8 13 21 34 55)
> (fib-list 56)
(1 1 2 3 5 8 13 21 34 55 89)

Sequence of prime numbers in range

I would like to write a function prime-seq to show a list between two numbers, using from and to.
Here is my code, I think it is if the numbers from the list are true then display them. But I have no idea how to write it, I am very new for this language.
(defn is-prime? [n]
(empty?
(filter #(= 0 (mod n %)) (range 2 n))))
(defn prime-seq [from to]
(drop from (take to is-prime?)))
the result should be:
(prime-seq 1 5)
=> (2 3 5)
You're very close:
(defn is-prime? [n]
(empty? (filter #(= 0 (mod n %)) (range 2 n))))
(defn prime-seq [from to]
(filter is-prime? (range from (inc to))))
(prime-seq 1 29)
=> (1 2 3 5 7 11 13 17 19 23 29)
This is using range generate a sequence of all numbers between from and to (inclusive), then filtering that list using your is-prime? predicate.
As for your is-prime? predicate, there are many approaches to determining primeness. As you comment (mod 1 1) => 0, so your predicate returns true however 1 isn't a prime number. You can simply add a special case for this in your predicate so that any number less than 2 returns false:
(defn is-prime? [n]
(if (< 1 n)
(empty? (filter #(= 0 (mod n %)) (range 2 n)))
false))
Or slightly more terse using and:
(defn is-prime? [n]
(and (< 1 n)
(not (some #(= 0 (mod n %)) (range 2 n)))))
In case people come here for a reasonably fast algorithm for finding prime numbers implemented in Clojure, here's an implementation of the Sieve of Eratosthenes in Clojure (using JVM arrays):
(defn find-primes
"Finds all prime numbers less than n, returns them sorted in a vector"
[n]
(if (< n 2)
[]
(let [^booleans sieve (boolean-array n false)
s (-> n Math/sqrt Math/floor int)]
(loop [p 2]
(if (> p s)
(into []
(remove #(aget sieve %))
(range 2 n))
(do
(when-not (aget sieve p)
(loop [i (* 2 p)]
(when (< i n)
(aset sieve i true)
(recur (+ i p)))))
(recur (inc p))))))))
Example:
(find-primes 100)
=> [2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97]
And some benchmarking:
(require '[criterium.core :as bench])
(bench/bench
(find-primes 100000))
;Evaluation count : 17940 in 60 samples of 299 calls.
; Execution time mean : 3.370834 ms
; Execution time std-deviation : 217.730604 µs
; Execution time lower quantile : 3.040426 ms ( 2.5%)
; Execution time upper quantile : 3.792958 ms (97.5%)
; Overhead used : 1.755126 ns

Implementing a counter as a Scheme procedure [duplicate]

How can I increment a value in scheme with closure? I'm on lecture 3A in the sicp course.
(define (sum VAL)
// how do I increment VAL everytime i call it?
(lambda(x)
(* x x VAL)))
(define a (sum 5))
(a 3)
Use set! for storing the incremented value. Try this:
(define (sum VAL)
(lambda (x)
(set! VAL (add1 VAL))
(* x x VAL)))
Because VAL was enclosed at the time the sum procedure was called, each time you call a it'll "remember" the previous value in VAL and it'll get incremented by one unit. For example:
(define a (sum 5)) ; VAL = 5
(a 3) ; VAL = 6
=> 54 ; (* 3 3 6)
(a 3) ; VAL = 7
=> 63 ; (* 3 3 7)
Answering the comment: sure, you can use let, but it's not really necessary, it has the same effect as before. The difference is that in the previous code we modified an enclosed function parameter and now we're modifying an enclosed let-defined variable, but the result is identical. However, this would be useful if you needed to perform some operation on n before initializing VAL:
(define (sum n)
(let ((VAL n))
(lambda (x)
(set! VAL (add1 VAL))
(* x x VAL))))

Resources