Advertisement
Guest User

racket-powered.md

a guest
Dec 19th, 2019
194
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.14 KB | None | 0 0
  1. <page title="I Built This Website Using Racket. Here's What I Can Do Now." />
  2.  
  3. It looks like there's not much to see here. Isn't it great?
  4. Barring exceptional cases, every page on this website takes up fewer than
  5. 20 kibibytes on disk and runs no JavaScript. Throttle your connection and
  6. hit refresh a few times. It loads in _milliseconds_. No one does that
  7. anymore.
  8.  
  9. It's funny. I spent years learning the ins and outs of front-end
  10. web development, only to feel _happy_ making a tiny, 90s-looking
  11. page that loads in a blink of an eye with nothing to do but
  12. make a point. Is that ironic? I haven't decided yet.
  13.  
  14. But I did not just write vanilla HTML and give up my shiny toys.
  15. I use [Racket][racket] to shape content using any language I want.
  16. What better tool for starting with a blank slate?
  17.  
  18. ## A Website With Superpowers
  19.  
  20. Racket is a programming language programming language.
  21. Racket allows you to write your own languages in terms of itself, and
  22. it is a _joy_ to use. I released [`unlike-assets`][ua]&mdash;an open
  23. source build tool that functions as an alternative to Webpack for my
  24. purposes&mdash;to say thank you and to show off what it can do.
  25.  
  26. I built a specific configuration for `unlike-assets` called [`polyglot`][rc]
  27. that lets me write web content with arbitrary DSLs.
  28.  
  29. This snippet computes a Sierpinsky Triangle when building this page.
  30. A cool part about that is that I expressed the code only once. My
  31. system knows to display the code for you to read, and then run it.
  32.  
  33. <script type="text/racket" id="tri">
  34. #lang racket/base
  35.  
  36. (require racket/format racket/list)
  37. (provide sierpinsky-triangle)
  38.  
  39. (define (sierpinsky-triangle iterations color id-prefix)
  40. (define (gid n) (format "~a~e" id-prefix n))
  41. (define (rf n) (format "#~a" (gid n)))
  42. (define (iter n)
  43. `(g ((id ,(gid n)))
  44. ,@(map
  45. (λ (matrix)
  46. `(use ((xlink:href ,(rf (- n 1))) (transform ,matrix))))
  47. '("matrix(0.5 0 0 0.5 0 0)"
  48. "matrix(0.5 0 0 0.5 1 0)"
  49. "matrix(0.5 0 0 0.5 0.5 0.866)"))))
  50.  
  51. `(svg ((xmlns "http://www.w3.org/2000/svg")
  52. (xmlns:xlink "http://www.w3.org/1999/xlink")
  53. (style "display: block; margin: 0 auto")
  54. (width "200")
  55. (height "175"))
  56. (defs
  57. (path ((id ,(gid 0)) (fill ,color) (d "M0 0,2 0,1 1.732 z"))))
  58. ,@(map
  59. iter
  60. (range 1 (+ iterations 1)))
  61. (use ((xlink:href ,(rf iterations)) (transform "scale(100)")))))
  62. </script>
  63. <script type="application/racket" id="code-sample">
  64. #lang racket/base
  65. (require "project/assets/macros.rkt" polyglot)
  66. (provide replace-page)
  67.  
  68. (define (replace-page page-tx)
  69. (tx-replace-me
  70. page-tx
  71. (λ (x)
  72. `(,(racket-code-sample "fractal-example"
  73. "#lang racket"
  74. "(require \"tri.rkt\" polyglot)"
  75. "(provide replace-page)"
  76. "(define (replace-page page-tx)"
  77. " (tx-replace-me"
  78. " page-tx"
  79. " (λ _ `((div ((style ,(string-join "
  80. " '(\"margin: 0 auto\")"
  81. " \";\")))"
  82. " ,(sierpinsky-triangle 4 \"#800\" \"tri\"))))))")))))
  83. </script>
  84.  
  85. Here I use [rash][rash]&mdash;a shell dialect by William Hatch&mdash;to compute the download size
  86. of Bootstrap. Honestly, I did it just because I can. I'd have to configure Webpack
  87. for countless hours to get this kind of flexibility.
  88.  
  89. <script type="application/racket" id="other-code">
  90. #lang racket/base
  91. (require "project/assets/macros.rkt" polyglot)
  92. (provide replace-page)
  93.  
  94. (define (replace-page page-tx)
  95. (tx-replace-me
  96. page-tx
  97. (λ (x)
  98. `(,(racket-code-sample "alt-measure"
  99. "#lang rash"
  100. "(require polyglot)"
  101. "(provide replace-page)"
  102. "(define size-box (box \"Unknown\"))"
  103. ""
  104. "curl -so /dev/null -w '\"%{size_download}\" \\"
  105. " https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css \\"
  106. " |>> set-box! size-box"
  107. ""
  108. "(define (replace-page page-tx)"
  109. " (tx-replace-me page-tx"
  110. " (λ _ `((span ((style \"color: rebeccapurple\"))"
  111. " \"The total download size of Bootstrap v4.3.1 is \""
  112. " ,(unbox size-box) \" bytes\")))))")))))
  113. </script>
  114.  
  115. Here are some drum samples from [`rsound`][] translated into an
  116. `<audio>` element without opening a sound editor on my PC.
  117.  
  118. <script type="application/racket" id="audio-example">
  119. #lang racket/base
  120. (require "project/assets/macros.rkt" polyglot)
  121. (provide replace-page)
  122.  
  123. (define (replace-page page-tx)
  124. (tx-replace-me
  125. page-tx
  126. (λ (x)
  127. `(,(racket-code-sample "drum-sample"
  128. "#lang racket/base"
  129. "(require polyglot)"
  130. "(provide replace-page)"
  131. ""
  132. "(define (replace-page page-tx)"
  133. " (tx-replace-me page-tx"
  134. " (λ _ `((audio ((style \"width: 100%\")"
  135. " (controls \"\")"
  136. " (src \"audio/drums.rkt\"))"
  137. " (code \"<audio>\") \"unsupported.\")))))")))))
  138. </script>
  139.  
  140. This page starts as a Markdown file. Since Markdown supports use of HTML tags,
  141. I use `<script>` elements to express Racket modules that are available only
  142. within a page.
  143.  
  144. * `text/racket` modules act as libraries.
  145. * `application/racket` elements write content and define page layout.
  146.  
  147. I parse the Markdown, process the Racket code in a sensible order, and then
  148. scan for dependencies in `href` and `src` attributes (such as other pages) to
  149. automagically build the rest of the website until all dependencies are fulfilled.
  150.  
  151. Things get fun when I can "drop down" from prose at any time to prepare
  152. a deeply integrated application that sits snug in any surrounding context.
  153. So if you are interested in using this kind of engine for your code, give
  154. [`polyglot`][rc] a try. If you want to start from a lower level, then use [`unlike-assets`][ua].
  155.  
  156. [`rsound`]: https://docs.racket-lang.org/rsound/index.html
  157. [rash]: https://docs.racket-lang.org/rash/index.html
  158. [racket]: https://racket-lang.org/
  159. [ua]: https://github.com/zyrolasting/unlike-assets
  160. [rc]: https://github.com/zyrolasting/polyglot
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement