I was confusing about the difference between match and case. In the document, it mentions that match supports general pattern matching.
> (define (m x)
(match x
[(list a b c)
#:when (= 6 (+ a b c))
'sum-is-six]
[(list a b c) 'sum-is-not-six]))
> (m '(1 2 3))
'sum-is-six
> (m '(2 3 4))
'sum-is-not-six
For this example, I thought I could rewrite it using case expression. But seems it's quite complicated. I have to get the length of the input x, and maybe a lambda function to get the sum of the elements of x and compare it with 6.
So I guess we prefer match when doing pattern matching. Is it true? Any difference other than that?
You said it yourself, match does general pattern matching (a very powerful concept!) whereas case only checks if a value belongs in one of several lists of possible (implicitly quoted) values. All that case does is syntactic sugar for a cond with multiple conditions, for example:
(case (+ 7 5)
[(1 2 3) 'small]
[(10 11 12) 'big]
[else 'other])
... is roughly equivalent to:
(let ((val (+ 7 5)))
(cond ((or (equal? val 1) (equal? val 2) (equal? val 3))
'small)
((or (equal? val 10) (equal? val 11) (equal? val 12))
'big)
(else 'other)))
Whereas match does some complex matching; it checks if a value is one of several possible patterns, it's not only about comparing values for equality, it also checks the type and "shape" of the value against the pattern, and we can even add additional constraints using #:when. To see how complex this can be check under the grammar part of match's documentation.
There are two differences:
match is a lot more powerful than case. case doesn't have "patterns" in the way match does, and it implicitly quotes the datums in each "branch question". It only compares the quoted form of the datum against the value, like a switch statement. match has a different and much richer pattern language.
The x in each branch-question of these two examples
(case 5
[(x) 10]
[else 'fail])
;=> 'fail
(case 'x
[(x) 10]
[else 'fail])
;=> 10
Is implicitly quoted, as the symbol 'x. In match terms, this is equivalent to
(match 5
['x 10]
[_ 'fail])
;=> 'fail
(match 'x
['x 10]
[_ 'fail])
;=> 10
Where quoting is one of many options for creating patterns, not the default. If you leave out the quote in a match, x is no longer a symbol; it is a wildcard that matches anything and defines x as the result.
(match 5
[x (+ x 1)])
;=> 6
This could never happen with case because of case's implicit quoting.
case branch-questions have multiple datums per branch.
These datums must be wrapped in parentheses.
(case expr
[(datum ...) answer]
...)
Where match has only one pattern per branch (no parentheses)
(match expr
[pattern answer]
...)
Related
I'm new to Racket and I was hoping to get more insights in the these two operators: , & ,#.
There's very little documentation of these new operators, however, to my understanding the former (,) unquotes everything if its is followed by a list. And the latter (,#) splices the values.
For example if the following is typed in the Dr. Racket interpreter:
(define scores '(1 3 2))
(define pets '(dog cat))
and then the following query is made:
`(,scores ,#pets)
this would yield : '((1 3 2) dog cat)
It would be appreciated if I could get more details, definitions and more examples about these operators.
Thanks in advance.
A single quote followed by the written representation of a value
will produce that value:
Example:
'(1 x "foo")
will produce a value that prints as (1 x "foo").
Suppose now that I don't want a literal symbol x in the list.
I have a variable x in my program, and I want to insert
the value to which x is bound.
To mark that I want the value of x rather than the symbol x,
I insert a comma before x:
'(1 ,x "foo")
It won't work as-is though - I now get a value that has a literal comma as well as a symbol x. The problem is that quote does not know about the comma convention.
Backtick or backquote knows about the comma-convention, so that will give the correct result:
> `(1 ,x "foo")
(1 3 "foo") ; if the value of x is 3
Now let's say x is the list (a b).
> `(1 ,x "foo")
(1 (a b) "foo") ; if the value of x is (a b)
This looks as expected. But what if I wanted (1 a b "foo")
as the result? We need a way so show "insert the elements of a list".
That's where ,# comes into the picture.
> `(1 ,#x "foo")
(1 a b "foo") ; if the value of x is (a b)
They are "reader abbreviations" or "reader macros". They are introduced in the section of the Racket guide on quasiquotation. To summarize:
`e reads as (quasiquote e)
,e reads as (unquote e)
,#e reads as (unquote-splicing e)
Because Racket's printer uses the same abbreviations by default, it can be confusing to test this yourself. Here are a few examples that should help:
> (equal? (list 'unquote 'abc) (read (open-input-string ",abc")))
#t
> (writeln (read (open-input-string ",abc")))
(unquote abc)
A more exhaustive description of the Racket reader is in the section on The Reader in the Racket Reference. A list of reader abbreviations is in the Reading Quotes subsection.
To construct the transitive and reflexive closure R *.
The binary relation R = {(1,1), (1,2), (2,1), (2,2), (3,1), (3,4), (4,1), (4,2), (4,4)}
What we can do is turn the data into some graph structure, like an adjacency hash table. Then we can traverse it and back-fill the missing transitive and reflexive relationships.
TXR Lisp program:
;; association data
(defvar rel-pairs '((1 1) (1 2) (2 1) (2 2) (3 1) (3 4) (4 1) (4 2) (4 4)))
;; turn data into hash table associating each domain value
;; with its range values.
(defvar rel [group-reduce (hash) car (op cons (cadr #2) #1) rel-pairs])
(defun ensure-trans-reflex (hash)
;; ensure reflexivity: if [hash key] maps to some values,
;; each of those values should appears as keys mapping
;; back to the key.
(dohash (key values hash)
(each ((val values))
(pushnew key [hash val])))
;; ensure transivity: individually starting at each
;; key in the hash, we recursively traverse the graph,
;; and associate that key with values thus reachable.
(dohash (key values hash hash)
(let ((visited (hash)))
(labels ((transitivize (key value)
(each ((next-val [hash value]))
(when (test-set [visited next-val])
(pushnew next-val [hash key])
(transitivize key next-val)))))
(each ((val values))
(transitivize key val))))))
(prinl rel)
(ensure-trans-reflex rel)
(prinl rel)
Output:
$ txr rel.tl
#H(() (1 (2 1)) (2 (2 1)) (3 (4 1)) (4 (4 2 1)))
#H(() (1 (4 3 2 1)) (2 (3 4 2 1)) (3 (2 3 4 1)) (4 (3 4 2 1)))
Basically, the example data ends up associating every key with every key including itself.
Here is an implementation in Common Lisp which exhibits a problem with a naïve approach to this sort of question.
First of all some definitions.
The kernel of the relation is a map with entries which look like (x . y). R(a, b) if there is an entry in the kernel like (a . b). I am not sure if 'kernel' is the correct mathematical term (I'm pretty sure it's not), but it's what I'm going to use.
The relation R is reflexive if R(a, a) for any a which occurs either in the domain or the range of the relation.
The transitive closure of R, R* is the relation such that R*(a, b if R(a, b) or (R(a, c) and R*(c, b)).
So I'm going to implement the kernel of the map just as a list, and I will explicitly use car, cdr, and cons to extract the parts of entries in the kernel. This is grotty old-fashioned Lisp, but in this case it's pretty much fine, since the natural objects in this part of the language (conses) map very nicely onto the objects in the problem. Note also that I have not tried to use any fancy data structures at all: everything is just walking down lists. This would make the thing slow if the kernel was very large. But it's not very large.
Here is the kernel you are given:
(defparameter *kernel*
'((1 . 1)
(1 . 2)
(2 . 1)
(2 . 2)
(3 . 1)
(3 . 4)
(4 . 1)
(4 . 2)
(4 . 4)))
This kernel is not reflexive: (3 . 3) is missing for instance. Here is a function which, given a kernel, returns a reflexive version of it. This function has very poor complexity, but the kernel is small and the function gets called once.
(defun reflexifize-kernel (kernel)
;; given the kernel of a map, return a reflexive version of it
;; This has pretty grotty complexity but it gets called only once
(loop for element in (loop with d/r = '()
for e in kernel
do (pushnew (car e) d/r)
do (pushnew (cdr e) d/r)
finally (return d/r))
for ik = (cons element element)
unless (member ik kernel :test #'equal)
collect ik into identities
finally (return (append kernel identities))))
And we can check this:
> (reflexifize-kernel *kernel*)
((1 . 1)
(1 . 2)
(2 . 1)
(2 . 2)
(3 . 1)
(3 . 4)
(4 . 1)
(4 . 2)
(4 . 4)
(3 . 3))
You can see it's added the appropriate entry at the end (and it would have added more entries if it needed to).
Now I'll write a function which, given the left-hand-side of a mapping and a kernel returns two things:
the first match for this left-hand-side in the kernel, or nil if there is none;
the remainder of the kernel after this match, or () if there is one (note that nil and () are the same in Common Lisp, but they might not be in other Lisps).
The nice thing here is that we can just use the remainder of the kernel to look for more matches, and this function works really nicely with the implementation of the kernel above: this is a case where Lisp's data structures really work well for us.
(defun next-match (lhs kernel)
;; return the next match (as (lhs . rhs)) for lhs in kernel, and the
;; remainder of the kernel, or nil and () if there is no match
(let ((found (member lhs kernel :key #'car)))
(if found
(values (first found) (rest found))
(values nil '()))))
So, now we can write a function, Rp which is true if R(a, b) is true:
(defun Rp (lhs rhs kernel)
;; is R(lhs, rhs) true
(multiple-value-bind (entry remaining-kernel) (next-match lhs kernel)
(cond ((null entry)
nil)
((eql (cdr entry) rhs)
t)
(t (Rp lhs rhs remaining-kernel)))))
This is called Rp because it's a predicate (ending in p in the usual Lisp convention), and it tells us if two elements satisfy R. And of course since CL is case-insensitive by default, this is the same function as rp.
And this function works fine:
> (rp 1 1 (reflexifize-kernel *kernel*))
t
> (rp 1 3 (reflexifize-kernel *kernel*))
nil
And now we can write R*p: it's clearer, I think and certainly more efficient to write a 'unified' version of R*p which does not rely on Rp, but is very similar code with it: it's really just got a final step which searches for the transitive closure.
(defun R*p (lhs rhs kernel)
;; is lhs related to rhs in kernel? (See note below!)
(multiple-value-bind (entry remaining-kernel) (next-match lhs kernel)
(if (null entry)
nil
(let ((match-rhs (cdr entry)))
(if (eql rhs match-rhs)
t
(or (R*p lhs rhs remaining-kernel)
(R*p match-rhs rhs kernel)))))))
OK, so this looks obviously correct, right?
first we look for a match for lhs;
if there's a match, and its rhs is rhs then we're done;
if there isn't then
first search for more matches in the kernel and check them
if that fails look for matches for the rhs we found whose rhs is rhs.
And this is just transparently the definition of the transitive closure, right? So if we feed it a reflexive kernel (which we can create now), it will work.
Well, no, it won't work. It won't work because there are loops in the kernel you've been given. Let's say we want to call (R*p 1 3 (reflexivize-kernel *kernel*)). It's obvious from the kernel that this should be false.
But in fact the function fails to terminate. It fails to terminate because it finds there's an entry for R(1, 2) and so it starts looking for R*(2, 3): it then finds R(2, 1), starts looking for R*(1, 3) ... oops.
(Note that the implementation above does depth-first search. Breadth-first search doesn't help: it will help find a mapping when there is one but when there isn't it will just loop in the same way.)
The way to deal with this is to use what's called an occurs check: when searching we keep track of the things we have already looked at up the search tree. If we find we're looking at a lhs which we have already looked at we fail immediately, as this is a loop. Here is an implementation of a version of R*p which does that, using a local function so we don't need to provide the so-far list in the interface, whichh would be annoying.
(defun R*p (lhs rhs kernel)
;; is lhs related to rhs in kernel, with an occurs check.
(labels ((R*p-loop (lhs rhs kernel so-far)
(if (member lhs so-far)
;; we've looped, give up
nil
(multiple-value-bind (entry remaining-kernel)
(next-match lhs kernel)
(if (null entry)
nil
(let ((match-rhs (cdr entry)))
(if (eql rhs match-rhs)
t
(or (R*p-loop lhs rhs remaining-kernel so-far)
(R*p-loop match-rhs rhs kernel
(cons lhs so-far))))))))))
(R*p-loop lhs rhs kernel '())))
And this version works:
> (R*p 1 3 (reflexifize-kernel *kernel*))
nil
> (R*p 1 1 (reflexifize-kernel *kernel*))
t
> (R*p 1 2 (reflexifize-kernel *kernel*))
t
> (R*p 2 1 (reflexifize-kernel *kernel*))
t
> (R*p 2 3 (reflexifize-kernel *kernel*))
nil
I was asked in an internship interview to do a R5RS program that creates a function, let's say two-subsets. This function has to return #t if the list L contains two subsets with equal sums of elements and with equal numbers of elements, otherwise it returns #f. It takes in entry the list L (only positive numbers) and some parameters (that I judge useful. There is no conditions on the number of parameters) all equal to 0 at the beginning.
The requirements as I still remember were as follow:
- Do not define other functions and call them inside the "two-subsets" function.
- It can only use the following constructs: null?, cond, car, cdr, else, + ,=, not, and, #t, #f, two-subsets (itself for recursive call), the names of the parameters, such as list, sum, ...etc, numeric constants and parentheses.
There were some given examples on the results that we are supposed to have, let's say:
(two-subsets '(7 7) 0 0 0) returns #t. The two subsets are {7} and {7}.
(two-subsets '(7 7 1) 0 0) returns #t. The two subsets are {7} and {7}.
(two-subsets '(5 3 2 4) 0 0) returns #t. The two subsets are {2, 5} and {3, 4}.
(two-subsets '(1 2 3 6 9) 0 0) returns #f.
I started by writing the signature that it looks to me it should be something like this:
(define two-subsets (lambda (L m n ... other parameters)
(cond
The problem is really complicated and it's complexity is obviously more than O(n), I read on it on https://en.wikipedia.org/wiki/Partition_problem .
I tried to start by defining the algorithm first before coding it. I thought about taking as parameters: sum of the list L so in my conditions I'll iterate only on the combinations which sum is <= sum(L)/2. By doing that I can reduce a little bit the complexity of the problem, but still I couldn't figure out how to do it.
It looks like an interesting problem and I really want to know more about it.
Here is a version which does not depend on the numbers being all positive. I am reasonably sure that, by knowing they are, you can do much better than this.
Note this assumes that:
the partition does not need to be exhaustive;
but the sets must not be empty.
I'd be very interested to see a version which relies on the elements of the list being +ve!
(define (two-subsets? l sl sld ssd)
;; l is the list we want to partition
;; sl is how many elements we have eaten from it so far
;; sld is the length difference in the partitions
;; ssd is the sum difference in the partitions
(cond [(and (not (= sl 0))
(= sld 0)
(= ssd 0))
;; we have eaten some elements, the differences are zero
;; we are done.
#t]
[(null? l)
;; out of l, failed
#f]
;; this is where I am sure we could be clever about the set containing
;; only positive numbers, but I am too lazy to think
[(two-subsets? (cdr l)
(+ sl 1)
(+ sld 1)
(+ ssd (car l)))
;; the left-hand set worked
#t]
[(two-subsets? (cdr l)
(+ sl 1)
(- sld 1)
(- ssd (car l)))
;; the right-hand set worked
#t]
[else
;; finally drop the first element of l and try the others
(two-subsets? (cdr l) sl sld ssd)]))
I am trying to understand pattern match document of racket and have some questions like the following, I can't parse it.
(quasiquote qp) — introduces a quasipattern, in which identifiers match symbols. Like the quasiquote expression form, unquote and unquote-splicing escape back to normal patterns.
http://docs.racket-lang.org/reference/match.html
Example:
> (match '(1 2 3)
[`(,1 ,a ,(? odd? b)) (list a b)])
'(2 3)
It doesn't explain this example, and how "identifiers match symbols"? I guess it is match '(1 2 3) to pattern '(1, a, b) and b is odd, but why `(,1 ,a ,(? odd? b)) not `(1 a (? odd? b)), whey it needs commas in between list members? Especially `(,? Why that way? So string!
Thanks!
If you're not familiar with quasiquoting, then you might to get comfortable with list patterns in match, then learn about quasiquoting in general. Then putting the two together will be easier to understand.
Why? Because quasiquote is "only" a shorthand or alternative for what you can write with list. Although I don't know the actual development history, I imagine that the author(s) of match started off with patterns like list, cons, struct and so on. Then someone pointed out, "hey, sometimes I prefer to describe a list using quasiquoting" and they added quasiquoting, too.
#lang racket
(list 1 2 3)
; '(1 2 3)
'(1 2 3)
; '(1 2 3)
(define a 100)
;; With `list`, the value of `a` will be used:
(list 1 2 a)
; '(1 2 100)
;; With quasiquote, the value of `a` will be used:
`(1 2 ,a)
; '(1 2 100)
;; With plain quote, `a` will be treated as the symbol 'a:
'(1 2 a)
; '(1 2 a)
;; Using `list` pattern
(match '(1 2 3)
[(list a b c) (values a b c)])
; 1 2 3
;; Using a quasiquote pattern that's equivalent:
(match '(1 2 3)
[`(,a ,b ,c) (values a b c)])
; 1 2 3
;; Using a quote pattern doesn't work:
(match '(1 2 3)
['(a b c) (values a b c)])
; error: a b c are unbound identifiers
;; ...becuase that pattern matches a list of the symbols 'a 'b 'c
(match '(a b c)
['(a b c) #t])
; #t
I have a list of elements '(a b c) and I want to find if (true or false) x is in it, where x can be 'a or 'd, for instance. Is there a built in function for this?
If you need to compare using one of the build in equivalence operators, you can use memq, memv, or member, depending on whether you want to look for equality using eq?, eqv?, or equal?, respectively.
> (memq 'a '(a b c))
'(a b c)
> (memq 'b '(a b c))
'(b c)
> (memq 'x '(a b c))
#f
As you can see, these functions return the sublist starting at the first matching element if they find an element. This is because if you are searching a list that may contain booleans, you need to be able to distinguish the case of finding a #f from the case of not finding the element you are looking for. A list is a true value (the only false value in Scheme is #f) so you can use the result of memq, memv, or member in any context expecting a boolean, such as an if, cond, and, or or expression.
> (if (memq 'a '(a b c))
"It's there! :)"
"It's not... :(")
"It's there! :)"
What is the difference between the three different functions? It's based on which equivalence function they use for comparison. eq? (and thus memq) tests if two objects are the same underlying object; it is basically equivalent to a pointer comparison (or direct value comparison in the case of integers). Thus, two strings or lists that look the same may not be eq?, because they are stored in different locations in memory. equal? (and thus member?) performs a deep comparison on lists and strings, and so basically any two items that print the same will be equal?. eqv? is like eq? for almost anything but numbers; for numbers, two numbers that are numerically equivalent will always be eqv?, but they may not be eq? (this is because of bignums and rational numbers, which may be stored in ways such that they won't be eq?)
> (eq? 'a 'a)
#t
> (eq? 'a 'b)
#f
> (eq? (list 'a 'b 'c) (list 'a 'b 'c))
#f
> (equal? (list 'a 'b 'c) (list 'a 'b 'c))
#t
> (eqv? (+ 1/2 1/3) (+ 1/2 1/3))
#t
(Note that some behavior of the functions is undefined by the specification, and thus may differ from implementation to implementation; I have included examples that should work in any R5RS compatible Scheme that implements exact rational numbers)
If you need to search for an item in a list using an equivalence predicate different than one of the built in ones, then you may want find or find-tail from SRFI-1:
> (find-tail? (lambda (x) (> x 3)) '(1 2 3 4 5 6))
'(4 5 6)
Here's one way:
> (cond ((member 'a '(a b c)) '#t) (else '#f))
#t
> (cond ((member 'd '(a b c)) '#t) (else '#f))
#f
member returns everything starting from where the element is, or #f. A cond is used to convert this to true or false.
You are looking for "find"
Basics - The simplest case is just (find Entry List), usually used as a predicate: "is Entry in List?". If it succeeds in finding the element in question, it returns the first matching element instead of just "t". (Taken from second link.)
http://www.cs.cmu.edu/Groups/AI/html/cltl/clm/node145.html
-or-
http://www.apl.jhu.edu/~hall/Lisp-Notes/Higher-Order.html
I don't know if there is a built in function, but you can create one:
(define (occurrence x lst)
(if (null? lst) 0
(if (equal? x (car lst)) (+ 1 (occurrence x (cdr lst)))
(occurrence x (cdr lst))
)
)
)
Ỳou will get in return the number of occurrences of x in the list. you can extend it with true or false too.
(define (member? x list)
(cond ((null? list) #f)
((equal? x (car list)) #t)
(else (member? x (cdr list)))))
The procedure return #t (true) or #f (false)
(member? 10 '(4 2 3))
output is #f