|
home—lectures—recipe—exams—hws—D2L—breeze (snow day; distance)
In racket,
Returning something un-evaluated can be applied to more than just identifiers:
What does it mean to return a list, un-evaluated?
It means "don't treat it as a function call".
Furthermore, the
This is handy, if you want to make (nested) lists, and don't want to have to
keep calling
'(html (head (title "backquoting, explained")) (body (h1 "How to Quote") (p "In racket, " (tt "'x") " is a symbol."))) |
(list 'html (list 'head (list 'title "backquoting, explained")) (list 'body (list 'h1 "How to Quote") (list 'p "In racket, " (list 'tt "'x") " is a symbol."))) |
By the way, such lists are a convenient way to represent XML, especially if you add in an association-list of attributes and attribute-values. See “X-expressions”. The one drawback of using this for XML is that we find ourselves writing lots of double-quote-marks for strings. See “@-expressions” for a notation to help with that.
Lispers like to point out the beautiful symmetry: take any racket/lisp code, throw a quote on the front of it, and now you have the program-source, as data! In essence, the S-expression is the syntax-tree of the code. This means you can manipulate it yourself — for example, write a program that walks through the expression and returns a new (different-but-related) expression. This is the idea behind macros.
Indeed, there is a lisp/scheme/racket function
Using quote (“
Recall the example:
(define x 5) `((amy ,(+ 2 5)) (ian ,x) (sammy ,(+ x (string-length "sammy") -1)) (eric 8)) |
Unquoting/re-quoting nests, exactly like you'd expect:
`((amy ,(+ 2 5)) (ian ,(assoc 'hello '((bye 3) (hello 5) (aloha 5)))) (sammy ,(+ (string-length "ciao") (assoc 'hello `((bye 3) (hello ,x) (aloha 5))))) (eric 8)) |
This is remiscent of switching between text-mode and php-mode in php programs,
except they can't nest.
In php, your file starts in text-mode,
and then enter php-mode with a processing instruction “
This is text mode <?php $greeting = "hello"; ?> and we want to say <?php if (strlen($greeting) === 3) { echo $greeting; ?> Ugh, now we're back in top-level text mode, but we're also in the middle of a php `if`! <?php } else {?> Okay, now back in text mode again. This just <em;>feels</em> wrong. It's bad enough when you think about copying/pasting code that has possibly-dangling php structure, or trying to write automated-tools for detecting php errors. When you realize that it's common to require/include other files which have dangling php blocks, it just makes you want to cry. #phpsadness (.com). <?php }?> |
The following discussion refers to ways you might want to use backquote in the particular example of implementing ../Homeworks/Project/P0.html.
#| Note: The 'cond' has a bunch of repeated patterns that it'd be nice to factor out. The first pass would have the cond just choose +,*,-, and we'd apply the result: ((cond [(string=? (bin-expr-op e) "add") +] [(string=? (bin-expr-op e) "mul") *] [(string=? (bin-expr-op e) "sub") -]) left-value right-value)) This is pretty good, but we can do better. Imagine we had a 'lookup' function: ((lookup (bin-expr-op e) (list (list "add" +) (list "mul" *) (list "sub" -))) left-value right-value)) ; Turns out lookup isn't *quite* built in, ; but it's easy to make, out of "association lists" ; and the built-in function 'assoc' ; (define (lookup key a-list) (second (assoc key a-list))) ; Or just : (define lookup (compose second assoc)) ; I'll leave it for further reading, about how 'assoc' works exactly. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Digression: backquote, unquote: We saw that a quote can be used to make a symbol: 'hello And now, a secret: If you try to "quote a list", the quote distributes over the list: '(3 4 hi 8) = (list 3 4 'hi 8) ; (Note that 'hi is quoted) It even works recursively: '(3 4 (5 6 bye 7) hi 8) = (list 3 4 (list 5 6 'bye 7) 'hi 8) ; That's a list-of-length-five, the middle of which is itself a list-of-length-four. ; "Lisp" = "list processing" ; ; Back to quoting a list: What if one of the things in the list is a variable, like pi? '(hi 3 "howdy" pi) = (list 'hi 3 "howdy" 'pi) ; Rats, we get the *symbol* 'pi (just like we did for 'hi), not 3.14. ; ; THe cool solution: We can use back-quote, which allows *unquote* (comma): `(hi 3 "howdy" ,pi) = (list 'hi 3 "howdy" 3.14159) ; We can unquote *any* expression: `(hi 3 "howdy" ,(* pi 100)) = (list 'hi 3 "howdy" 314.159) ; ; Anything being unquoted is a perfectly fine expression. ; It might even contain a backquote itself (which can of course contain an unquote (comma) ... `(hi 3 ,(map sqrt `(16 25 ,(* 100 pi))) "hello") = ??? ; [typographically, note how command and backquote do look kinda opposite/mirror-image...] ; Once you've digested all that, you can read about unquote-splice. ; Note that quoting a list, unquote and unquote splice ; All get rewritten into (primitive)quote-symbol, `list`, and `append` functions. ; They're just shortcuts -- handy, but nothing we couldn't do before. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; Where were we? Oh right, ((lookup (bin-expr-op e) (list (list "add" +) (list "mul" *) (list "sub" -))) left-value right-value)) The association-list (list of key/value pairs) can be written more concisely using backquote: ((lookup (bin-expr-op e) `(("add" ,+) ("mul" ,*) ("sub" ,-))) left-value right-value)) ; Note that that (a) we really need the comma there: ; we want the list to contain the-actual-multiplication-function, ; not just an asterisk-symbol. ; and (b) an association-list containing functions is very convenient ; (esp. w/ λ). |#
1 This is true in both Lisp and in racket/scheme; it's just that the racketeers/schemers prefer to think of the symbol as an end-value, whereas lispers prefer to think of it as unevaluated-lisp-code. With all due deference, the lispers have it a bit wrong. ↩
2 Most programmers would view it as a serious safety flaw, if running code modified (at run-time) their own functions. But others delight at the thought of self-modifying code. It's fun as a toy, but not what you want in a language (like, say, javascript...). ↩
home—lectures—recipe—exams—hws—D2L—breeze (snow day; distance)
©2016, Ian Barland, Radford University Last modified 2016.Nov.11 (Fri) |
Please mail any suggestions (incl. typos, broken links) to ibarlandradford.edu |