The code and data behind xeiaso.net
5
fork

Configure Feed

Select the types of activity you want to include in your feed.

add JSX quasi-quoting post

Signed-off-by: Xe Iaso <me@christine.website>

Xe Iaso 6fdff75a a063bc97

+147 -61
+139
blog/jsx-quasi-quoting.markdown
··· 1 + --- 2 + title: "JSX is quasi-quoting" 3 + date: 2023-01-23 4 + tags: 5 + - JSX 6 + - JavaScript 7 + - Lisp 8 + --- 9 + 10 + I've been writing a fair bit of JSX/TSX code lately and something has felt oddly 11 + familiar about that programming model. It was something that I couldn't really 12 + place until I had a breakthrough after hacking at my Emacs config again. When 13 + you are using JSX to write HTML in your JavaScript functions, you are using 14 + quasi-quoting. 15 + 16 + <xeblog-conv standalone name="Aoi" mood="wut">Quasi-quoting? What's 17 + that?</xeblog-conv> 18 + 19 + <xeblog-hero ai="Waifu Diffusion" file="sky-sigils" prompt="glowing sigils, sigils, zen, yin yang, taoism, landscape, world trade center, peaceful, arknights, scifi, runic energy, spellcraft"></xeblog-hero> 20 + 21 + I think one of the easiest ways to explain this is to use Emacs Lisp. Emacs Lisp 22 + is the extension language for [GNU Emacs](https://www.gnu.org/software/emacs/), 23 + the text editor that I ~~am horribly addicted to using~~ have used for the last 24 + ten years. 25 + 26 + One of the major concepts in Lisp is that code is data, and data is code. When 27 + you are writing in Lisp, you are writing linked lists that the computer 28 + interprets as code. For example, consider this small bit of Lisp: 29 + 30 + ```lisp 31 + (quote (+ 3 4)) 32 + ``` 33 + 34 + You can evaluate this with `ielm` in Emacs by using `M-x ielm`: 35 + 36 + <xeblog-conv standalone name="Mara" mood="hacker">`M-x` is Emacs-speak for 37 + "alt-x".</xeblog-conv> 38 + 39 + ``` 40 + *** Welcome to IELM *** Type (describe-mode) for help. 41 + ELISP> (quote (+ 3 4)) 42 + (+ 3 4) 43 + ``` 44 + 45 + Quoting code into data is something you do very often in Lisp, so there's a 46 + shortcut for doing this using the single quote character `'`: 47 + 48 + ``` 49 + ELISP> '(+ 3 4) 50 + (+ 3 4) 51 + ``` 52 + 53 + This works great, but sometimes you need to put the value of a variable into a 54 + bit of data. Let's say you have this snippet of Lisp code: 55 + 56 + ```lisp 57 + (let ((filename "foobar.txt")) 58 + '(filename)) 59 + ``` 60 + 61 + <xeblog-conv standalone name="Mara" mood="hacker">`(let ((var1 value) (var2 62 + value)) code)` is how you declare temporary variables in Lisp. Here the variable 63 + name `filename` is set to `"foobar.txt"`. Each variable declaration is a list of 64 + two elements: the variable name and its value. Values can be data or code that 65 + is evaluated down to data.</xeblog-conv> 66 + 67 + If you put this into the Emacs Lisp interpreter, you won't get back what you 68 + think: 69 + 70 + ```lisp 71 + ELISP> (let ((filename "foobar.txt")) 72 + '(filename)) 73 + (filename) 74 + ``` 75 + 76 + You need to have some way to quote code you want to be data, and then some way 77 + to unquote data back into code. Luckily, Emacs Lisp lets you do this with a 78 + construct they call 79 + [Backquoting](https://www.gnu.org/software/emacs/manual/html_node/elisp/Backquote.html): 80 + 81 + ```lisp 82 + ELISP> (let ((filename "foobar.txt")) 83 + `(,filename)) 84 + ("foobar.txt") 85 + ``` 86 + 87 + The backtick <code>`</code> lets you quote everything like the single quote 88 + <code>'</code>, but you can also _unquote_ data using the comma <code>,</code> 89 + to turn your data back into code. This lets you construct complicated data 90 + structures like an attribute list to convert into HTTP form data: 91 + 92 + ```lisp 93 + ELISP> (let ((fname (buffer-name)) 94 + (content "Hi there")) 95 + `((fname . ,fname) 96 + (content . ,content))) 97 + ((fname . "*ielm*") 98 + (content . "Hi there")) 99 + ``` 100 + 101 + <xeblog-conv name="Aoi" mood="cheer">So quasi-quoting lets you mix data and 102 + code, but how does this relate to JSX?</xeblog-conv> 103 + <xeblog-conv name="Mara" mood="aha">JSX is the same thing with slightly 104 + different syntax.</xeblog-conv> 105 + 106 + [JSX](https://reactjs.org/docs/introducing-jsx.html) is a syntax extension for 107 + JavaScript that lets you mix HTML data with JavaScript code. It's a lot like 108 + quasi-quoting in Lisp. Consider this small block of JSX code: 109 + 110 + ```typescript 111 + const name = "Aoi"; 112 + const header = ( 113 + <div> 114 + <h2>{name}</h2> 115 + <p>Hi there, {name}! How are you doing today?</p> 116 + </div> 117 + ); 118 + document.write(header); 119 + ``` 120 + 121 + This writes the equivalent of this HTML to the current page: 122 + 123 + ```html 124 + <div> 125 + <h2>Aoi</h2> 126 + <p>Hi there, Aoi! How are you doing today?</p> 127 + </div> 128 + ``` 129 + 130 + You quote HTML data inside parentheses `()` and use curly braces `{}` to unquote 131 + JavaScript code into HTML data. 132 + 133 + <xeblog-conv name="Aoi" mood="grin">So JSX does the same thing for 134 + HTML in JavaScript that quasi-quoting does for lists in Lisp! It lets you mix 135 + code and data so that you can assemble whatever you want easily.</xeblog-conv> 136 + <xeblog-conv name="Mara" mood="happy">Yep! You end up finding a lot of these 137 + things across different programming tools. A lot of tools steal ideas from 138 + eachother and there are many more similar patterns across the industry. What 139 + other ones can you find?</xeblog-conv>
+8 -61
static/css/hack.css
··· 8 8 text-rendering: geometricPrecision; 9 9 } 10 10 body { 11 - font-size: 1rem; 12 - line-height: 1.5rem; 11 + font-size: 1.125rem; 12 + line-height: 1.75rem; 13 13 margin: 0; 14 - font-family: Menlo, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono, 15 - Bitstream Vera Sans Mono, Courier New, monospace, serif; 14 + font-family: "Helvetica Neue", Helvetica, Verdana, Arial, sans-serif; 16 15 word-wrap: break-word; 17 16 } 18 17 ::selection { 19 18 background: #d3869b; 20 - } 21 - h1, 22 - h2, 23 - h3, 24 - h4, 25 - h5, 26 - h6 { 27 - line-height: 1.3em; 28 19 } 29 20 fieldset { 30 21 border: none; ··· 164 155 flex: 0 0 auto; 165 156 } 166 157 } 167 - .hack, 158 + .hack p, 159 + .hack .conversation-chat, 168 160 .hack blockquote, 169 - .hack code, 170 161 .hack em, 171 - .hack h1, 172 - .hack h2, 173 - .hack h3, 174 - .hack h4, 175 - .hack h5, 176 - .hack h6, 177 162 .hack strong { 178 - font-size: 1rem; 163 + font-size: 1.125rem; 179 164 font-style: normal; 180 - font-family: Menlo, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono, 181 - Bitstream Vera Sans Mono, Courier New, monospace, serif; 165 + font-family: "Helvetica Neue", Helvetica, Verdana, Arial, sans-serif; 182 166 } 183 167 .hack blockquote, 184 168 .hack code, 185 169 .hack em, 186 170 .hack strong { 171 + font-size: 1rem; 187 172 line-height: 20px; 188 173 } 189 174 .hack blockquote, ··· 206 191 padding: 0; 207 192 } 208 193 .hack blockquote, 209 - .hack h1, 210 194 .hack ol, 211 195 .hack p, 212 196 .hack ul { 213 197 margin-top: 20px; 214 198 margin-bottom: 20px; 215 199 } 216 - .hack h1 { 217 - position: relative; 218 - display: inline-block; 219 - display: table-cell; 220 - padding: 20px 0 30px; 221 - margin: 0; 222 - overflow: hidden; 223 - } 224 - .hack h1:after { 225 - content: "==============================================================================================================================================================="; 226 - position: absolute; 227 - bottom: 10px; 228 - left: 0; 229 - } 230 - .hack h1 + * { 231 - margin-top: 0; 232 - } 233 200 .hack h2, 234 201 .hack h3, 235 202 .hack h4, ··· 245 212 .hack h6:before { 246 213 display: inline; 247 214 } 248 - .hack h2:before { 249 - content: "## "; 250 - } 251 - .hack h3:before { 252 - content: "### "; 253 - } 254 - .hack h4:before { 255 - content: "#### "; 256 - } 257 - .hack h5:before { 258 - content: "##### "; 259 - } 260 - .hack h6:before { 261 - content: "###### "; 262 - } 263 215 .hack li { 264 216 position: relative; 265 217 display: block; ··· 305 257 } 306 258 .hack code { 307 259 font-weight: 700; 308 - } 309 - .hack code:after, 310 - .hack code:before { 311 - content: "`"; 312 - display: inline; 313 260 } 314 261 .hack hr { 315 262 position: relative;