I am trying to understand what is happening when writing this code by drawing it with the box and pointer method but cant quite get it. Anybody that could help?
(define bar (list 'a 'b 'c 'd 'e))
(set-cdr! (cdddr bar) (cdr bar))
My idea:
Also I don't know how to start to draw a diagram for the code under, I cant see where the points and boxes for (car) need to be.
(define bah (list 'bring 'a 'towel))
(set-car! bah (cdr bah))
This is the initial situation:
And this is the final situation:
If you try to print bah, it is printed as a three element list, whose first element is a two element list:
((a towel) a towel)
But in fact the two structures are shared, so that, for instance, if you do:
(set-car! (cddr bah) 'handkerchief)
bah will be printed as:
((a handkerchief) a handkerchief)
Related
Structure and Interpretation of Computer Programs (SICP)'s box-and-pointer diagrams in Figures 3.16 and 3.17 don't appear equivalent (purely with respect to value, not memory) even though it says they are. ("When thought of as a list, z1 and z2 both represent "the same" list, ((a b) a b))", pg. 258)
(define x (list 'a 'b))
(define z1 (cons x x))
(define z2 (cons (list 'a 'b) (list 'a 'b)))
SICP diagrams the pair z1 like this:
and z2 like this:
The arrows in the pair, z1, don't both seem to be pointing to the entire pair, x. They don't even point to the same thing, despite both having received the same (memory and value) pair.
I would evaluate the first diagram as (a b), and the second as ((a b) a b)
I could guess that each arrow is actually pointing to the entire pair, x, but in figure 2.3 on page 98:
it very clearly points to an entire box by either pointing to the side or in between two items.
Am I understanding box-and-pointer diagrams incorrectly or something else entirely?
You're reading too much into it. :-) If it points into the box anywhere, assume it's a pointer to that cons cell. You cannot specifically point to the car or cdr portion of it.
Your last assumption is correct. The dot indicates where the pointer value is, the whole double box the arrow is pointing at is the target. It doesn't matter if it's pointing on the side, top middle, top left or top right. It's the whole pair that is the "address" of the object.
You can't point to a part of an object without accessing its part with car and cdr. The second you do that you have whatever it was pointed to and not a indirect pointer. (car '(a b)) ; ==> a and a doesn't have any essence of the list that still is pointing to it until it is garbage collected.
We could illustrate it like this instead:
[=#1|#3|#2]
[=#2|#3|()]
[=#3|a |#4]
[=#4|b |()]
The first value with =# is the location of the box itself, while the next two are car and cdr. Above, x points to the address #3 and z1 to #1. Let's make z2
[=#5|#6|#8]
[=#6|a |#7]
[=#7|b |()]
[=#8|#9|()]
[=#9|a |#10]
[=#10|b |()]
As you can see, z2 uses two more cons than z1 since it doesn't reuse the same object as both elements of its list, but uses individual similar-looking lists.
In the drawings, both car and cdr of z1 point to the same list x. z2 points to two different lists, but the elements in those lists are the same.
The reason for this is that symbols are singletons. Thus, you only have one symbol object for a and evaluating 'a in two different places will both point to the same a. Other singletons are #f, #t and ()
cons always creates a fresh pair and list is just a procedure that cons together the arguments. Thus the same code (list 'a 'b) two places in the expression makes two different objects that just look the same.
(eq? (car z1) (cdr z1)) ; ==> #t same object
(eq? (car z2) (cdr z2)) ; ==> #f not same object
(equal? (car z2) (cdr z2)) ; ==> #t they look the same, but they are not the same. (created at different places)
Quoted data can be seen as created all at once before the program starts. Thus this is undefined.
(eq? '(a b) '(a b)) ; ==> #t or #f (undefined)
(eq? '(b c) (cdr '(a b c))) ; ==> #t or #f (undefined)
The reason is that Scheme is allowed, but not obligated, to reuse data the same way as with the structure z1.
In Chapter 3 of The Little Schemer, the answer to the question of why we don't simplify the rember function right away is "because then a function's structure does not coincide with its argument's structure." I'm having trouble understanding what a function's structure is, what an argument's structure is, and what the difference is between them.
Here's the unsimplified version:
(define rember
(lambda (a lat)
(cond
((null? lat) (quote ()))
(else (cond
(( eq? (car lat) a) (cdr lat))
(else (cons (car lat)
(rember a
( cdr lat)))))))))
And here's the simplified:
(define rember
(lambda (a lat)
(cond
((null? lat) (quote ()))
((eq? (car lat) a) (cdr lat))
(else (cons (car lat)
(rember a (cdr lat)))))))
From what I can tell, the main difference is that the function has gone from two conds asking one question each to one cond asking two questions.
The function's arguments are the atom "a" and the list "lat."
This is the first time, outside of the densely written foreword, where the book references the word "structure." In my mind, the definition of the word "structure" so far is open to interpretation.
Someone has asked this exact question here before, but I have trouble following the answer. Why does a two-cond structure coincide or not coincide with the structure of a list? A list, in my mind, doesn't have any conditions at all!
Isn't a condition equivalent to a question in Scheme? Perhaps I'm misunderstanding what a condition is, which could be a reasonable root of my frustration. Anyways, any clarification on this would be very much appreciated! Thank you!
Here for “structure of function” the author probably means that the body of the function, that is the condition:
(cond
((null? lat) ...)
(else ... (cond... (car lat) ... (cdr lat) ...)))
patterns exactly the “recursive” definition of a list, as either:
an empty list, or
a value with at least one element (the car), and a list (the cdr).
The new definition instead “folds” the two cond inside a single one, so that the “structure” of the function (the structure of the cond) does not reflect any more the “structure” of its list argument.
List is a type that could have been defined, with some pseudocode, as
(define-variant-record list
( () ) ; '() is a list
((hd . tl) ; a cons pair (with car field named `hd` and cdr `tl`)
(list tl)) ) ; is a list, if `tl` itself is a list
Then, it could be handled with a hypothetical (cf. EOPL) patern-matching construct variant-case:
(define rember
(lambda (a lat) ; an atom and a list of atoms
(variant-case (lat) ; follow the `lat` --
( () ; an empty list case, or
(quote ()))
( (hd . tl) ; a non-empty list, with car field `hd` and cdr `tl`
(cond
(( eq? hd a) tl)
(else
(cons hd
(rember a tl))))))))
which, by way of using the variant-case belonging to the data-type definition of list, naturally and visibly follows its structure (i.e. the two cases of its definition).
The first formulation (with the nested conds) just emulates the non-existent variant-case with the explicit access to the concrete data-type implementation, with the cars and the cdrs as it does.
The inner cond does not belong to this, and just deals with the specifics of rember on its own. That's why mashing the two conds into one may be seen as mixing the non-related concerns into one mish-mash (generally speaking; although here both are extremely simple and clear).
I am trying to finish a finite state machine in Scheme. The problem is, that I am not sure how to tell it what characters it should test. If I want to test a String "abc112" then how do I do that?
Here is the code:
#lang racket
(define (chartest ch)
(lambda (x) (char=? x ch)))
;; A transition is (list state char!boolean state)
(define fsmtrlst
(list
(list 'start char-alphabetic? 'name)
(list 'start char-numeric? 'number)
(list 'start (chartest #\() 'lparen)
(list 'start (chartest #\)) 'rparen)
(list 'name char-alphabetic? 'name)
(list 'name char-numeric? 'name)
(list 'number char-numeric? 'number)))
(define (find-next-state state ch trl)
(cond
[(empty? trl) false]
[(and (symbol=? state (first (first trl)))
((second (first trl)) ch))
(third (first trl))]
[else (find-next-state state ch (rest trl))]))
(define fsmfinal '(name number lparen rparen))
(define (run-fsm start trl final input)
(cond
[(empty? input)
(cond
[(member start final) true]
[else false])]
[else
(local ((define next (find-next-state start (first input) trl)))
(cond
[(boolean? next) false]
[else (run-fsm next trl final (rest input))]))]))
And here is the launch code which I am trying to test:
(fsmtrlst (list 'start (lambda (abc112) (char=? abc112 ))))
EDIT:
ok,.. the overall product is okey, but my tutor is not happy with it,.. he wants me to make a finite state machine with transition function -> something like a global definition which would say: when in state X comes character Y go to Z ... and then i will test a list of characters to see if it is false or true ... So the only difference is that the code shouldn't be specific to use only numbers and letters but any character... is it somehow possible? thank you for your answer
EDIT 2: now I have the basic info how it should look like:
That is, the machine looks like
A ---------> B ----------> C ----------> D ----------> (E)
letter number number letter
(define fsmtrlst
(list
(list 'A char-alphabetic? 'B)
(list 'B char-numeric? 'C)
(list 'C char-numeric? 'D)
(list 'D char-alphabetic 'E)))
(define fsmfinal '(E))
(define fsmstart 'A)
but i am not sure how to write the definition of fsmstart.
Thank you for answers.
This accepts sequences of exactly four characters which are letter, number, number, letter, and nothing else.
EDIT 3: I am using tutorials online and a book that my mentor teacher provided. I figured out the fsm I wanted to make. Thank you for your help.
Just out of curiosity:
How would differ to have rather specific fsm?
Example:
START ----"b"-----> STATE A -----"a" ----> STATE B -----"c"-----> FINAL STATE
That the fsm would be true only when the list of characters is "bac" and nothing else.
Is it possible?
Thank you for your feedback.
EDIT 4:
Ok, I managed to do write but once again, I am not sure how to make the input of characters. This is the code:
There are 3 states but it will be true only when going from state A to state C.
(define (chartest ch)
(lambda (x) (char=? x ch)))
(define fsm-trans
'((A, "a", B), (A, "b", A), (B, "c", C)))
(define (find-next-state state ch trl)
(cond
[(empty? trl) false]
[(and (symbol=? state (first (first trl)))
((second (first trl)) ch)) <- And also this line returns an error
(third (first trl))]
[else (find-next-state state ch (rest trl))]))
(define fsm-final '(C))
(define start-state 'A)
(define (run-fsm start trl final input)
(cond
[(empty? input)
(cond
[(member start final) true]
[else false])]
[else
(local ((define next (find-next-state start (first input) trl)))
(cond
[(boolean? next) false]
[else (run-fsm next trl final (rest input))]))]))
(run-fsm start-state fsm-trans fsm-final (list '("a", "c"))) <- I know this is the last problem with the code, the definition of the input. How can I tell Scheme what characters I want to test?
Thank you for your answer!!!
I am curious: I take it you did not write this fsm? Is this for a homework assignment or are you trying to teach yourself? The code for the FSM looks fine (quite fine, in fact). However, your launch line:
(fsmtrlst (list 'start (lambda (abc112) (char=? abc112 ))))
Makes no sense. Here is why: fsmtrlst is the finite state machine transition list. It was defined in the first big block of code. It is not a function to be called. I believe the function you want to call is run-fsm. That takes a start symbol, a transition list, a list of final states, and an input. The input is not actually a string, but a list. As a consequence, you can launch it with the following line:
(run-fsm 'start fsmtrlst fsmfinal (string->list "abc112"))
That will call run-fsm with the defined transition list fsmtrlst, the defined list of final states, and the input-ready form of the string "abc112".
Incidentally, everything except 'start is defined to be a final (accepting) state. Not all inputs are accepting inputs, though. For example, replacing "abc122" with "abc(122" is not accepted.
Is this what you want?
Update:
Your edit has clarified things. Your definition of fsmstart is fine. You did miss a question mark (?) on one of your char-alphabetic? usages in fsmtrlst. Is your confusion that you don't know how to use your new definitions? First, you should remove the old definitions of fsmtrlst and fsmfinal. Otherwise, you will likely get a duplicate definition error. From your new definition, your line to execute should look like:
(run-fsm fsmstart fsmtrlst fsmfinal (string->list "w00t"))
This will return #t, because "w00t" is a character followed by two numbers, followed by a character.
I speculate that you are still having difficulty with the syntax rules of scheme, and not just problems with the logic of your particular program. You might want to try a simpler exercise.
UPDATE 2: Shouldn't you consider formulating a new question?
Your most recent update has broken the code. The transition portion of the fsm worked because transitions were defined as a list:
(from-state test-function to-state)
You have attempted to create a transition:
(from-state string-literal to-state)
You could change (A, "a", B) to (A (lambda (x) (string=? x "a") B).
When you tried to invoke your function, you took a function that expected a list of characters and gave it a list of list of strings. These are not the same thing. Also, did you notice that you put commas in your lists, but they existed nowhere else in the code? These mistakes are why I suggest you begin a scheme tutorial. These are basic scheme problems, unrelated to your particular exercise. I suggest you rewind your edits to what you had yesterday.
Unfortunately, I can no longer update this answer. I wanted to update my answer so that if someone came along your question with similar concerns, they would see a complete answer. However, you have provided a moving target. Please consider halting your edits and submit a new question when you have one.
I am writing a recursion function returning an empty list in the base case. However the output of functions shows "empty" word in the my list, which I don't want.Like this;
(list (list 'abc) (list 'def) empty (list 'ghi))
How can I prevent this? Thanks.
The problem is probably because Racket has several printing styles for values. Try changing it (in the language selection dialog) to "write" or whatever it's called, which should make it output ((abc) (def) () (ghi)) instead.
The empty that you see in the result is not a "word" -- note that it's not quoted. If you do expect an empty list in the result, then it looks like you got one. You can even check for that:
> (empty? (third (list (list 'abc) (list 'def) empty (list 'ghi))))
#t
Without knowing details, my best guess would be something like
(let ((result (recursive-call ...)))
(if (null? result) (resursive-call (cdr whatever-list))
(cons result (cdr whatever-list)))
Essentially, just check if the result is the empty list, and if so, don't put it into the list that you're returning.
I know if I write my scheme code in the following way and type in (word ‘(a b c)), it will out put the list in the same order. Could you please tell me if there was a way I can print it out in opposite order. Ex- (list ‘c ‘b ‘a).
it needs to be the user's input I print out in opposite order. So, I can't call it (reverse '(a b c)). since the user input can be something like '(x y z).
Thanks a lot.
(define(word x )
(if(null? x) x
(cons(car x)(word (cdr x)))))
(word '(a b c))
(list 'a 'b 'c)
(reverse '(a b c))
will reverse your string. However I suspect that this is probably homework and you are supposed to write your own reverse function.
If so, can you reverse an empty list? If you have a list and have the reverse of the rest of the list, can you get the reverse of the whole list? Can you see how to make a function that reverses the list from these pieces?
Is this what you want?
(list->string (reverse (string->list "market")))
"tekram"
Thanks all for your information and help. I found a way to do it. just in-case there was anyone else looking.
(define (word lis)
(if (null? lis)
'()
(append (word (cdr lis))
(list (car lis)))))
Hint: cons creates a list composed of its first argument followed by its second argument. Right now, you're using it to create a list of the first element followed by the same function applied to the rest of the elements, and that creates a list in the same order as it was.
What do you suppose would happen if you created a list of the same function applied to the rest of the elements followed by the first element?