I tried to solve this puzzle https://puzzling.stackexchange.com/questions/40094/who-committed-the-crime using Racket.
A crime has been carried out by one person, there are 5 suspects. Each
suspect is asked under polygraph who they think committed the crime.
Their answers are as follows:
Terry : It wasn't Carl, It was Steve
Steve : It wasn't Matt, It wasn't Carl
Matt : It was Carl, It wasn't Terry
Ben : It was Matt, It was Steve
Carl : It was Ben, It wasn't Terry
The polygraph showed that
each suspect told one lie and one truth. Who committed the crime?
Following is my code:
(define (oneof a b)
(or (and a (not b)) (and b (not a))))
(for ((i 5))
(define templist (list #f #f #f #f #f)) ; make a temporary list of all false;
(set! templist (list-set templist i #t)) ; one by one keep one as true in this loop;
(define t (list-ref templist 0)) ; allocate each person according to above list (one kept true one by one)
(define s (list-ref templist 1))
(define m (list-ref templist 2))
(define b (list-ref templist 3))
(define c (list-ref templist 4))
(when ; test if all statements fit with above assignment:
(and
(oneof (not c) s) ; Terry's statement
(oneof (not m) (not c)) ; Steve's statement
(oneof c (not t)) ; Matt's statement
(oneof m s) ; Ben's statement
(oneof b (not t))) ; Carl's statement
(println (list "t" "s" "m" "b" "c")) ; print allocation if all statement fit in;
(println templist)))
Output indicates Matt committed the crime:
'("t" "s" "m" "b" "c")
'(#f #f #t #f #f)
It works but the code is imperative and not very functional (especially define t, define s, ... part). How can it can be improved? Thanks for your comments/answers.
This answer is based on #Oscar Lopez's answer, but modified to use more idiomatic features like filter with a helper function instead of for, when, and println.
This style of code returning a value is much more useful because the value it produces could be used in later code, where an imperative action like println would be much less reusable.
#Oscar Lopez's make-matrix function produces an initial list of possibilities, but we have to filter out the ones that are impossible, and leave only the ones that are possible. So write that down:
;; If there are no valid solutions, this will be an empty list,
;; if there's one, this will be a list of one element,
;; and if there are more, this will include all of them.
(filter valid-solution? (make-matrix 5))
;; Wish list:
;; valid-solution? : (Listof Boolean) -> Boolean
Now we just need to add a definition for valid-solution?
;; valid-solution? : (Listof Boolean) -> Boolean
;; Given a list containing booleans for whether Terry, Steve, Matt, Ben, and Carl did it,
;; this determines whether that combination is possible under the constraints in the problem.
(define (valid-solution? row)
; unpack each row into the corresponding variables
(match-define (list t s m b c) row)
; don't reinvent the wheel, `oneof` is called `xor`
(and (xor (not c) s)
(xor (not m) (not c))
(xor c (not t))
(xor m s)
(xor b (not t))))
And that's it. The full program including make-matrix is this:
#lang racket
;; make-matrix : Natural -> (Listof (Listof Boolean))
;; generate a matrix with possibilities
(define (make-matrix n)
(for/list ([i (in-range n)])
(build-list n (λ (j) (= i j)))))
;; valid-solution? : (Listof Boolean) -> Boolean
;; Given a list containing booleans for whether Terry, Steve, Matt, Ben, and Carl did it,
;; this determines whether that combination is possible under the constraints in the problem.
(define (valid-solution? row)
; unpack each row into the corresponding variables
(match-define (list t s m b c) row)
; don't reinvent the wheel, `oneof` is called `xor`
(and (xor (not c) s)
(xor (not m) (not c))
(xor c (not t))
(xor m s)
(xor b (not t))))
;; If there are no valid solutions, this will be an empty list,
;; if there's one, this will be a list of one element,
;; and if there are more, this will include all of them.
(filter valid-solution? (make-matrix 5))
This is an equivalent program written in idiomatic Racket - and avoiding all those pesky set! and list-ref which are frowned upon when writing functional-style code:
; generate a matrix with possibilities
(define (make-matrix n)
(for/list [(i (in-range n))]
(build-list n (λ (j) (= i j)))))
; iterate over each row
(for [(row (make-matrix 5))]
; unpack each row into the corresponding variables
(match-let ([(list t s m b c) row])
; don't reinvent the wheel, `oneof` is called `xor`
(when (and (xor (not c) s)
(xor (not m) (not c))
(xor c (not t))
(xor m s)
(xor b (not t)))
(println '(t s m b c))
(println row))))
Related
I am trying to define a function func->symbol that takes a function and returns its name as a symbol. For example:
(define (pythagoras a b)
(sqrt (+ (* a a) (* b b))))
;; #1
(func->symbol pythagoras) ; Returns: 'pythagoras
;; #2
(func->symbol (if #t pythagoras sqrt)) ; Returns: 'pythagoras
;; #3
(let ((f (if #t pythagoras sqrt)))
(func->symbol f)) ; Returns: 'pythagoras
;; #4
(let ((f (if #t pythagoras sqrt)))
(let ((g f))
(func->symbol g))) ; Returns: 'pythagoras
This is a follow-up question on How do I get a definition's name as a symbol? which only deals with case #1. For case #1, a simple macro def->symbol is sufficient:
(define-syntax def->symbol
(syntax-rules ()
((_ def) 'def)))
However, this macro definition does not pass cases #2, #3, #4. Is it possible to define func->symbol, or is Scheme not expressive enough for this?
In Racket, in many cases, you can get a function's name using object-name. But it is probably a bad idea to rely on this result for anything other than debugging.
Perhaps it's worth an answer which shows why this is not possible in any language with first-class functions.
I'll define what I mean by a language having first-class functions (there are varying definitions).
Functions can be passed as arguments to other functions, and returned as values from them.
Functions can be stored in variables and other data structures.
There are anonymous functions, or function literals.
Scheme clearly has first-class functions in this sense. Now consider this code:
(define a #f)
(define b #f)
(let ((f (lambda (x)
(+ x 1))))
(set! a f)
(set! b f))
Let's imagine there is a function-name function, which, given a function, returns its name. What should (function-name a) return?
Well, the answer is that there's simply no useful value it can return (in Racket, (object-name a) returns f, but that's clearly exposing implementation details which might be useful for debugging but would be very misleading as a return value for a function-name procedure.
This is why such a procedure can't exist in general in a language with first-class functions: the function which maps from names to values is many-to-one and thus has no inverse.
Here is an example of the sort of disgusting hack you could do to make this 'work' and also why it's horrible. The following is Racket-specific code:
(define-syntax define/naming
;; Define something in such a way that, if it's a procedure,
;; it gets the right name. This is a horrid hack.
(syntax-rules ()
[(_ (p arg ...) form ...)
(define (p arg ...) form ...)]
[(_ name val)
(define name (let ([p val])
(if (procedure? p)
(procedure-rename p 'name)
p)))]))
And now, given
(define/naming a
(let ([c 0])
(thunk
(begin0
c
(set! c (+ c 1))))))
(define/naming b a)
Then:
> (object-name a)
'a
> (object-name b)
'b
> (eqv? a b)
#f
> (a)
0
> (b)
1
> (a)
2
So a and b have the 'right' names, but because of that they are necessarily not the same object, which I think is semantically wrong: if I see (define a b) then I want (eqv? a b) to be true, I think. But a and b do capture the same lexical state, so that works, at least.
A friend of mine plays on a volleyball league and posed me with an interesting problem:
Each of the following letters represents a pair of players
; player pairs (24)
'(a b c d e f g h i j k l m n o p q r s t u v w x)
Create matches where 3 pairs are grouped to form a team (6 players on a team)
; teams
'((a b c) (d e f) (g h i) (j k l) (m n o) (p q r) (s t u) (v w x))
Combinations of teams will make up a match
; matches
'(((a b c) (d e f))
((g h i) (j k l))
((m n o) (p q r))
((s t u) (v w x)))
In a given night, they may play 8 to 12 matches, but before each match, the pairs of players will randomized. It is the facilitator's intentions to shuffle the teams as much as possible, but often times the result is far from a good distribution. 'a will get paired too many times with 'b etc.
In the scenario where '(a b c) form a team, in an ideal situation 'a would not play on a team with 'b or 'c again. Likewise, 'b would not play again with 'c, if possible.
Simply calculating the combinations for C(24 choose 3), there are 2,024 possible teams...
'((a b c)
(a b d)
(a b e)
...)`
I was thinking I could filter out non fully unique team combinations, but this does not really lead me closer to my solution.
Consider the two following
'(a b c) ; team1
'(a w x) ; team2
These are two fully unique team combinations, but of course we couldn't put them in a match because pair 'a cannot possibly play on two teams simultaneously. So these team combos should never be provided in a single match solution.
Another issue is, the player pairs may not be equally divisible by 6.
; player pairs (26)
'(a b c d e f g h i j k l m n o p q r s t u v w x y z)
; teams
'((a b c) (d e f) (g h i) (j k l) (m n o) (p q r) (s t u) (v w x))
; matches
'(((a b c) (d e f))
((g h i) (j k l))
((m n o) (p q r))
((s t u) (v w x)))
; sit-out this game
'(y z)
Question 1:
How can I generate a list of all possible matches composed of unique team combinations?
Question 2:
How can I expand the algorithm to accommodate the "sit out" players. In the event the list of player pairs is not divisible by 6, each player pair has to play/sit-out in an equal number of matches.
--
So I don't have much code to show for this because I keep hitting dead ends. The furthest I got was getting X choose Y implemented such that I had a list of all possible team combinations. I ran into trouble filtering out non-fully-unique combinations. Even if I were to succeed at that, I wouldn't know how to compose the fully unique combinations into matches.
Answers don't have to include a full implementation but pointing me in the right direction would be a lot of help. I don't have a lot of experience with this kind of computation.
You can build a solution to question 1 using the combinations function and some extra filtering. First some data definitions:
;; A Player-Pair is a Symbol.
;; A Team is a (List Player-Pair Player-Pair Player-Pair).
;; A Match is a (List Team Team) where the teams are disjoint.
;; Player-Pairs : (Listof Player-Pair)
(define player-pairs '(a b c d e f g h i j k l m n o p q r s t u v w x))
So, what we want is to find the matches, but to do that we need to find a set of teams from all the combinations of 3 player-pairs, and then filter that so that it satisfies your constraint that two player-pairs should never be on a team with each other more than once.
I don't know how to do that yet, but it sounds complicated, so make it a helper function called filter-team-combinations.
;; find-teams : (Listof Player-Pair) -> (Listof Team)
(define (find-teams player-pairs)
(filter-team-combinations (combinations player-pairs 3)))
;; filter-team-combinations : (Listof Team) -> (Listof Team)
;; Filters out teams where a player-pair would on a team with another
;; player-pair for the second time.
(define (filter-team-combinations teams) ....)
Hm. To know whether a given Team has two player-pairs that have already been on the team together, I'll need to keep track of that as well. It's probably going to be recursive, and the pairs of player-pairs that have already been together will change from one recursive call to the next. As we add to the result list, the list of pair-pairs will grow larger. So we need to add it as an argument, which starts out as an empty list.
;; find-teams : (Listof Player-Pair) -> (Listof Team)
(define (find-teams player-pairs)
(filter-team-combinations (combinations player-pairs 3) (list)))
;; A Pair-Pair is a (List Player-Pair Player-Pair)
;; filter-team-combinations : (Listof Team) (Listof Pair-Pair) -> (Listof Team)
;; Filters out teams where a player-pair would on a team with another
;; player-pair for the second time.
;; pair-pairs is an accumulator that stores the pair-pairs that we've
;; seen so far.
(define (filter-team-combinations teams pair-pairs) ....)
The filter-team-combinations function processes a list of teams, and a list can be either empty or the first team consed onto the rest of the teams:
(define (filter-team-combinations teams pair-pairs)
(cond [(empty? teams) ....]
[else .... (first teams) .... (rest teams) ....]))
For the base case, if there are no teams to filter, we return the empty list. For the recursive case, well, it will have to look at the pairs of player-pairs that the first team contains, check whether those conflict with the existing pair-pairs, and branch on that:
(define (filter-team-combinations teams pair-pairs)
(cond [(empty? teams) (list)]
[else
(define new-pair-pairs (combinations (first teams) 2))
(cond [(pair-pairs-conflict? new-pair-pairs pair-pairs)
.... (first teams) .... (rest teams) ....]
[else
.... (first teams) .... (rest teams) ....])]))
;; pair-pairs-conflict? : (Listof Pair-Pair) (Listof Pair-Pair) -> Boolean
(define (pair-pairs-conflict? as bs) ....)
So, pretending that pair-pairs-conflict? does the right thing, we'll fill in the ....s to finish filter-team-combinations. In the case where they conflict, we should drop the first team and recur on the rest. In the case where they don't conflict, we should cons the first team onto something.
(define (filter-team-combinations teams pair-pairs)
(cond [(empty? teams) (list)]
[else
(define new-pair-pairs (combinations (first teams) 2))
(cond [(pair-pairs-conflict? new-pair-pairs pair-pairs)
;; This team has a pair-pair that a previous team already had,
;; so don't include this team in the result; recur on the rest.
(filter-team-combinations (rest teams) pair-pairs)]
[else
;; Cons this team onto something.
(cons (first teams)
....)])]))
For the last ...., we need to recur on the rest, but we also need to make sure that the recursive call knows that the player-pairs in the first team shouldn't be on the same team again. To do that we can append them onto the pair-pairs argument.
;; filter-team-combinations : (Listof Team) (Listof Pair-Pair) -> (Listof Team)
;; Filters out teams where a player-pair would on a team with another
;; player-pair for the second time.
;; pair-pairs is an accumulator that stores the pair-pairs that we've
;; seen so far.
(define (filter-team-combinations teams pair-pairs)
(cond [(empty? teams) (list)]
[else
(define new-pair-pairs (combinations (first teams) 2))
(cond [(pair-pairs-conflict? new-pair-pairs pair-pairs)
;; This team has a pair-pair that a previous team already had,
;; so don't include this team in the result; recur on the rest.
(filter-team-combinations (rest teams) pair-pairs)]
[else
;; Add this team and add the new pair-pairs.
(cons (first teams)
(filter-team-combinations (rest teams)
(append new-pair-pairs pair-pairs)))])]))
So now we need to implement the pair-pairs-conflict? predicate.
;; pair-pairs-conflict? : (Listof Pair-Pair) (Listof Pair-Pair) -> Boolean
;; A team must be made up of sets of player-pairs that haven't been on the
;; same team yet. This function takes two lists of player-pair pairs.
;; Each pair-pair in the first list has two player-pairs that would now be
;; on the same team.
;; Each pair-pair in the second list has two player-pairs that have been
;; on the same team already.
;; This function returns true iff any player-pair would be on the same
;; team with anyone they have already been on the same team with.
(define (pair-pairs-conflict? as bs) ....)
It needs to take each pair-pair in the as and check whether it's in bs, and it conflicts if any a is in bs. One way to do that is with an ormap, and another way to do that is with for/or.
(define (pair-pairs-conflict? as bs)
(for/or ([a (in-list as)])
(member a bs)))
There's one problem with this though. The pair-pair (list 'a 'b) should be considered the same as the pair-pair (list 'b 'a). So we need a member function that doesn't care about this ordering thing. Luckily, member can take a third argument for it to use as an equality predicate.
(define (pair-pairs-conflict? as bs)
(for/or ([a (in-list as)])
(member a bs pair-pair=?)))
;; pair-pair=? : Pair-Pair Pair-Pair -> Boolean
(define (pair-pair=? a b)
(match-define (list a1 a2) a)
(match-define (list b1 b2) b)
(or (and (equal? a1 b1) (equal? a2 b2))
(and (equal? a1 b2) (equal? a2 b1))))
Now we have everything we need to find all the valid sets of teams.
(define teams (find-teams player-pairs))
To find matches, we need combinations of two teams, but we need to filter them to make sure that the teams are disjoint, so that a player-pair never plays against itself.
;; find-matches : (Listof Team) -> (Listof Match)
(define (find-matches teams)
(filter match-has-disjoint-teams? (combinations teams 2)))
;; match-has-disjoint-teams? : Match -> Boolean
(define (match-has-disjoint-teams? match)
(teams-disjoint? (first match) (second match)))
;; teams-disjoint? : Team Team -> Boolean
(define (teams-disjoint? team-1 team-2) ....)
To implement teams-disjoint?, we need to match every player-pair in team-1 against every player-pair in team-2 and make sure none of those are equal to each other. One way to do that would be with cartesian-product and andmap, but another way would be to use for*/and.
;; teams-disjoint? : Team Team -> Boolean
(define (teams-disjoint? team-1 team-2)
(for*/and ([p1 (in-list team-1)]
[p2 (in-list team-2)])
(not (equal? p1 p2))))
Using find-matches:
> (find-matches (list (list 'a 'b) (list 'b 'c) (list 'c 'd) (list 'd 'a)))
(list (list (list 'a 'b) (list 'c 'd))
(list (list 'b 'c) (list 'd 'a)))
> (find-matches (list (list 'a 'b 'c)
(list 'c 'd 'e)
(list 'e 'f 'g)
(list 'g 'h 'i)))
(list (list (list 'a 'b 'c) (list 'e 'f 'g))
(list (list 'a 'b 'c) (list 'g 'h 'i))
(list (list 'c 'd 'e) (list 'g 'h 'i)))
My attempted solution to question 1 was to compose find-matches with find-teams:
(find-matches (find-teams player-pairs))
With 24 different player-pairs, this produces 1,624 different match-ups.
Although, while two player-pairs would never be together on different teams, this includes match-ups where are together with the same team that they have been in in a different match-up.
That's probably not what you wanted. It might help you get there though, so I'll post it anyway.
I am trying to write a program that will check the structural equivalence of some list input, whether it includes just atoms or nested sub lists.
I am having trouble with using AND, I don't even know if its possible and I cant seem to understand documentation I am looking at.
My code:
(define (structEqual a b)
(cond
(((null? car a) AND (null? car b)) (structEqual (cdr a) (cdr b)))
(((null? car a) OR (null? car b)) #f)
(((pair? car a) AND (pair? car b))
(if (= (length car a) (length car b))
(structEqual (cdr a) (cdr b))
#f))
(((pair? car a) OR (pair? car b)) #f)
(else (structEqual (cdr a) (cdr b)))))
The idea is (i think): (when I say both, i mean the current cdr of a or b)
Check if both a and b are null, then they are structurally equal
Check if only either a or b is null, then they are not structually equal
Check if both of them are pairs
If they are both pairs, then see if the length of the pair is equal, if not they are not structurally equal.
If they are not both pairs, then if one of them is a pair and the other isnt then they are not structurally equivalent.
If neither of them are pairs, then they both must be atoms, so they are structurally equivalent.
So as you can see I am trying to recursively do this by checking the equivalence of the car of a or b, and then either returning #f if they fail or moving on to the cdr of each if they are equivalent at each step.
Any help?
There is no infix operators in Scheme (or any LISP) only prefix. Every time the operator comes first. (or x (and y z q) (and y w e)) where each letter can be a complex expression. Everything that is not #f is a true value. Thus (if 4 'a 'b) evaluates to a because 4 is a true value. car needs its parentheses.
When evaluating another predicate in cond you should make use of the fact that everything up to that has been false. eg.
(define (structure-equal? a b)
(cond
((null? a) (null? b)) ; if a is null the result is if b is null
((not (pair? a)) (not (pair? b))) ; if a is not pair the result is if b is not also
((pair? b) (and (structure-equal? (car a) (car b)) ; if b is pair (both a and b is pair then) both
(structure-equal? (cdr a) (cdr b)))) ; car and cdr needs to be structurally equal
(else #f))) ; one pair the other not makes it #f
(structure-equal '(a (b (c d e) f) g . h) '(h (g (f e d) c) b . a)) ; ==> #t
I am trying to write a function that can check whether or not some input is a quotation for a syntax checker.
I have the following code:
(define is-quote-expression?
(lambda (v)
(equal? (car v) 'quote)
(is-quotation? (cdr v)))))
(define is-quotation?
(lambda (v)
(or (number? v)
(boolean? v)
(char? v)
(string? v)
(symbol? v)
(null? v)
(and (pair? v)
(is-quotation? (car v))
(is-quotation? (cdr v)))))
When I try to evaluate, I get the following:
(is-quote-expression? '1)
#f
(is-quote-expression? (cons 'quote 1))
#t
I think my TA told me that the Scheme environment replaced all "'" with "'quote", however, this does not seem to be the case. We are running Petite Chez Scheme.
What am I not seeing?
Thanks in advance.
There are a couple of problems with your code, for starters the (lambda (pair? v) part in is-quote-expression? is almost certainly a mistake (you're defining a lambda with two parameters called pair? and v).
Also, I believe you intended to call is-quotation? from is-quote-expression? only if v isn't a pair, so it doesn't make sense to ask again if (pair? v) in is-quotation?. And who said that a pair is a quotation only if both its car and cdr are quotations?
Here, I believe this is what you intended:
(define is-quote-expression?
(lambda (v)
(if (pair? v)
(equal? (car v) 'quote)
(is-quotation? v))))
(define is-quotation?
(lambda (v)
(or (number? v)
(boolean? v)
(char? v)
(string? v)
(symbol? v)
(null? v))))
I agree with Óscar's post, though, is-quote-expression? accepts a list rather than a pair and returns whether it was a quotation.
(define is-quote-expression?
(lambda (v)
(and (proper-list-of-given-length? v 2)
(equal? (car v) 'quote)
(is-quotation? (cadr v)))))
Also, your original question shows some confusion as to what quote actually does. This is what really should happen:
> (is-quote-expression? '1)
#f
> (is-quote-expression? (cons 'quote 1))
#f
> (is-quote-expression? (quote 42))
#f
> (is-quote-expression? (quote (quote 42)))
#t
Note how the built-in quote procedure simply returns what it is passed. In the case of (quote 42) it simply returns 42. But (quote (quote 42)) returns (quote 42), which is what you wish to pass to is-quote-expression?.
The behavior of quote is specified in R6RS, appendix A.3. For '1, the relevant rule is 6sqv:
(store (sf1 ...) S1[ 'sqv1 ]) → (store (sf1 ...) S1[ sqv1 ])
Time to break this down.
The "S → T" notation defines one step in evaluating a term, where "S" evaluates to "T".
Since store and the sf1 non-terminals appear the same on both the left and right sides, you don't need to understand them to understand how '1 evaluates. If you need something, think of store as "storage environment" and the sfn as pairs of names and values; (store ((x 1) (y 2)) S) means the identifier x is associated with the value 1 and y with 2 when evaluating the term S.
If you're not familiar with the S[e] notation, it refers to a term with one "hole" (an term with a [] in it) filled with e. There are two related syntax elements: terms with holes (S[]) and terms with a hole filled by a value (S[e]). Holes are a little (but only a little) like unnamed variables. One important difference is that a term is allowed only one hole. Holes are perhaps best explained by example. All of the following are S[]:
(+ [] 1 2)
(list [] 'a "foo")
(cond ((= x 0) [])
((> x 0) 1)
(else -1))
Note that a hole can only appear where a sub-term is syntactically valid; [] 2) is not a term-with-hole. S[0] would be a term with 0 substituted into the hole:
(+ 0 1 2)
(list 0 'a "foo")
(cond ((= x 0) 0)
((> x 0) 1)
(else -1))
When a value is given for a hole, the term S[] is also called a "context". This comes from one of the primary uses for terms-with-holes: to match any term containing the given value. S[e] is any term that contains e as a valid sub-term, so S[] is the context that e appears in. In short, S1['sqv1] is a stand-in for any term that contains a quote.
(+ 'foo 1 2)
(list 'bar 'a "foo")
(cond ((= x 0) 'baz)
((> x 0) 1)
(else -1))
Note the second term provides two different contexts for quote-terms: (list [] 'a "foo"), (list 'bar [] "foo"). This suggests that you shouldn't think of holes too much as just being unnamed variables.
If you're wonder why context terms and holes are used, they're an alternative to recursive definitions. Without contexts, → would have to be defined recursively over the structure of terms (Scheme's grammar defines the structure). Substitution in lambda calculus is an example of structural recursion, as are any tree-processing functions you might define in Scheme (though Scheme syntax is quite different than the syntax used to define → and lambda calculus substitution).
(define (tree-depth tree)
(if (pair? tree)
(max (tree-depth (car tree))
(tree-depth (cdr tree)))
1
) )
Next, let's examine the meaning of sqv, which is short for "self-quoting values". This is a non-terminal from the Scheme grammar, given in appendix A.2.
sqv ::= n | #t | #f
n ::= [numbers]
sqv is simply a number or boolean.
All together, the 6sqv evaluation rule means that a quoted number or boolean evaluates to the number or boolean; the quote is simply discarded.
What this signifies for your homework is that you can't tell the difference between 1 and '1 with a normal function, since sub-terms are evaluated before the function is called. You'll need a macro.
Why go through all this just to say that "'1 evaluates to 1"? Firstly, answering "why" takes more than answering "what". Also, it will hopefully help you go beyond the question, learning a little bit how to read Scheme's formal semantics, give you a taste of computational theory concepts and lead to many more questions.
I notice that almost all scheme functions can only return one list as output.
In the following, I would like to return multiple values of all the adjacent nodes of neighbors.
(define (neighbors l w)
(if (and (= 1 l) (= 1 w))
(list (and (l (+ 1 w))) (and (+ 1 l) w)))) ; how to output 2 or more values?
In this case I'm first testing if the node is at corner, if so, return 2 values of the coordinates where (l and w+1), (l+1 and w) basically if I'm at (1,1) return me (1,2) and (2,1)
Same applies when the node has only 1 neighbor near the edge, in this case I will have 3 values.
When no edge is nearby I will have 4 return values.
I tried to use cons, append, list, display, write none of them seems working with additional values. I need this as a sub-function of this question. How should I implement it so I could pass on the return value and use it recursively to return me all the adjacent nodes?
Edit: I found the answer: use the keyword "values" to return multiple values. Example:
(define (store l w)
(values (write l)
(write w)
(newline)
(list (+ 1 w) l)
(list w (+ 1 l))))
values, continuation passing style, and list are at least three ways of returning multiple values:
(import (rnrs))
; let-values + values
(define (foo1)
(values 1 2 3))
(let-values (((a b c) (foo1)))
(display (list a b c))
(newline))
; cps
(define (foo2 k)
(k 1 2 3))
(foo2 (lambda (a b c)
(display (list a b c))
(newline)))
; list
(define (foo3)
(list 1 2 3))
(let ((result (foo3)))
(display result)
(newline))
The Guile implementation of Scheme has a receive syntax, which it says is "much more convenient" than values. I haven't used it yet, however, but this may be useful:
http://www.gnu.org/software/guile/manual/html_node/Multiple-Values.html
You can return a pair of values in a cons cell:
(define (foo)
(cons 'a 5))
(let* ((r (foo))
(x (car r))
(y (cdr r)))
(display x) (display y) (newline))
You can generalise this to return multiple values in a list, too.