From 6fdff75ae03b4bc52e0368259a5fe9fa93e43027 Mon Sep 17 00:00:00 2001 From: Xe Iaso Date: Mon, 23 Jan 2023 20:59:16 -0500 Subject: add JSX quasi-quoting post Signed-off-by: Xe Iaso --- blog/jsx-quasi-quoting.markdown | 139 ++++++++++++++++++++++++++++++++++++++++ static/css/hack.css | 69 +++----------------- 2 files changed, 147 insertions(+), 61 deletions(-) create mode 100644 blog/jsx-quasi-quoting.markdown diff --git a/blog/jsx-quasi-quoting.markdown b/blog/jsx-quasi-quoting.markdown new file mode 100644 index 0000000..5315ec3 --- /dev/null +++ b/blog/jsx-quasi-quoting.markdown @@ -0,0 +1,139 @@ +--- +title: "JSX is quasi-quoting" +date: 2023-01-23 +tags: + - JSX + - JavaScript + - Lisp +--- + +I've been writing a fair bit of JSX/TSX code lately and something has felt oddly +familiar about that programming model. It was something that I couldn't really +place until I had a breakthrough after hacking at my Emacs config again. When +you are using JSX to write HTML in your JavaScript functions, you are using +quasi-quoting. + +Quasi-quoting? What's +that? + + + +I think one of the easiest ways to explain this is to use Emacs Lisp. Emacs Lisp +is the extension language for [GNU Emacs](https://www.gnu.org/software/emacs/), +the text editor that I ~~am horribly addicted to using~~ have used for the last +ten years. + +One of the major concepts in Lisp is that code is data, and data is code. When +you are writing in Lisp, you are writing linked lists that the computer +interprets as code. For example, consider this small bit of Lisp: + +```lisp +(quote (+ 3 4)) +``` + +You can evaluate this with `ielm` in Emacs by using `M-x ielm`: + +`M-x` is Emacs-speak for +"alt-x". + +``` +*** Welcome to IELM *** Type (describe-mode) for help. +ELISP> (quote (+ 3 4)) +(+ 3 4) +``` + +Quoting code into data is something you do very often in Lisp, so there's a +shortcut for doing this using the single quote character `'`: + +``` +ELISP> '(+ 3 4) +(+ 3 4) +``` + +This works great, but sometimes you need to put the value of a variable into a +bit of data. Let's say you have this snippet of Lisp code: + +```lisp +(let ((filename "foobar.txt")) + '(filename)) +``` + +`(let ((var1 value) (var2 +value)) code)` is how you declare temporary variables in Lisp. Here the variable +name `filename` is set to `"foobar.txt"`. Each variable declaration is a list of +two elements: the variable name and its value. Values can be data or code that +is evaluated down to data. + +If you put this into the Emacs Lisp interpreter, you won't get back what you +think: + +```lisp +ELISP> (let ((filename "foobar.txt")) + '(filename)) +(filename) +``` + +You need to have some way to quote code you want to be data, and then some way +to unquote data back into code. Luckily, Emacs Lisp lets you do this with a +construct they call +[Backquoting](https://www.gnu.org/software/emacs/manual/html_node/elisp/Backquote.html): + +```lisp +ELISP> (let ((filename "foobar.txt")) + `(,filename)) +("foobar.txt") +``` + +The backtick ` lets you quote everything like the single quote +', but you can also _unquote_ data using the comma , +to turn your data back into code. This lets you construct complicated data +structures like an attribute list to convert into HTTP form data: + +```lisp +ELISP> (let ((fname (buffer-name)) + (content "Hi there")) + `((fname . ,fname) + (content . ,content))) +((fname . "*ielm*") + (content . "Hi there")) +``` + +So quasi-quoting lets you mix data and +code, but how does this relate to JSX? +JSX is the same thing with slightly +different syntax. + +[JSX](https://reactjs.org/docs/introducing-jsx.html) is a syntax extension for +JavaScript that lets you mix HTML data with JavaScript code. It's a lot like +quasi-quoting in Lisp. Consider this small block of JSX code: + +```typescript +const name = "Aoi"; +const header = ( +
+

{name}

+

Hi there, {name}! How are you doing today?

+
+); +document.write(header); +``` + +This writes the equivalent of this HTML to the current page: + +```html +
+

Aoi

+

Hi there, Aoi! How are you doing today?

+
+``` + +You quote HTML data inside parentheses `()` and use curly braces `{}` to unquote +JavaScript code into HTML data. + +So JSX does the same thing for +HTML in JavaScript that quasi-quoting does for lists in Lisp! It lets you mix +code and data so that you can assemble whatever you want easily. +Yep! You end up finding a lot of these +things across different programming tools. A lot of tools steal ideas from +eachother and there are many more similar patterns across the industry. What +other ones can you find? diff --git a/static/css/hack.css b/static/css/hack.css index e6d0406..5d1b506 100644 --- a/static/css/hack.css +++ b/static/css/hack.css @@ -8,24 +8,15 @@ html { text-rendering: geometricPrecision; } body { - font-size: 1rem; - line-height: 1.5rem; + font-size: 1.125rem; + line-height: 1.75rem; margin: 0; - font-family: Menlo, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono, - Bitstream Vera Sans Mono, Courier New, monospace, serif; + font-family: "Helvetica Neue", Helvetica, Verdana, Arial, sans-serif; word-wrap: break-word; } ::selection { background: #d3869b; } -h1, -h2, -h3, -h4, -h5, -h6 { - line-height: 1.3em; -} fieldset { border: none; padding: 0; @@ -164,26 +155,20 @@ a:hover { flex: 0 0 auto; } } -.hack, +.hack p, +.hack .conversation-chat, .hack blockquote, -.hack code, .hack em, -.hack h1, -.hack h2, -.hack h3, -.hack h4, -.hack h5, -.hack h6, .hack strong { - font-size: 1rem; + font-size: 1.125rem; font-style: normal; - font-family: Menlo, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono, - Bitstream Vera Sans Mono, Courier New, monospace, serif; + font-family: "Helvetica Neue", Helvetica, Verdana, Arial, sans-serif; } .hack blockquote, .hack code, .hack em, .hack strong { + font-size: 1rem; line-height: 20px; } .hack blockquote, @@ -206,30 +191,12 @@ a:hover { padding: 0; } .hack blockquote, -.hack h1, .hack ol, .hack p, .hack ul { margin-top: 20px; margin-bottom: 20px; } -.hack h1 { - position: relative; - display: inline-block; - display: table-cell; - padding: 20px 0 30px; - margin: 0; - overflow: hidden; -} -.hack h1:after { - content: "==============================================================================================================================================================="; - position: absolute; - bottom: 10px; - left: 0; -} -.hack h1 + * { - margin-top: 0; -} .hack h2, .hack h3, .hack h4, @@ -245,21 +212,6 @@ a:hover { .hack h6:before { display: inline; } -.hack h2:before { - content: "## "; -} -.hack h3:before { - content: "### "; -} -.hack h4:before { - content: "#### "; -} -.hack h5:before { - content: "##### "; -} -.hack h6:before { - content: "###### "; -} .hack li { position: relative; display: block; @@ -306,11 +258,6 @@ a:hover { .hack code { font-weight: 700; } -.hack code:after, -.hack code:before { - content: "`"; - display: inline; -} .hack hr { position: relative; height: 20px; -- cgit v1.2.3