ec changed the topic of #elliottcable to: a π•―π–Šπ–“ 𝖔𝖋 π•―π–Šπ–™π–Šπ–—π–’π–Žπ–“π–Šπ–‰ π•―π–†π–’π–˜π–Šπ–‘π–˜ slash sΝ”ΜžuΝ•Ν™pΝ™Ν“e̜̺rΜΌΜ¦i̼̜oΜ–Μ¬rΜ™Μ™ c̝͉α»₯Μ§Ν˜αΈ·Μ‘Ν™Ε£Ν“Μ€ || #ELLIOTTCABLE is not about ELLIOTTCABLE
muelleme has joined #elliottcable
muelleme has quit [Ping timeout: 256 seconds]
mylesborins has quit [Quit: farewell for now]
mylesborins has joined #elliottcable
mylesborins has quit [Quit: farewell for now]
<purr\GH> [ocameel] ELLIOTTCABLE pushed 8 new commits to sedlex-w-o-menhir: https://github.com/ELLIOTTCABLE/ocameel/compare/991e58205860...75df71832a00
<purr\GH> ocameel/sedlex-w-o-menhir c5d8f46 ELLIOTTCABLE: + stop stomping on Pervasives.failwith in the lexer
<purr\GH> ocameel/sedlex-w-o-menhir 75cf8e1 ELLIOTTCABLE: + including comments in the AST
<purr\GH> ocameel/sedlex-w-o-menhir ce2f5ba ELLIOTTCABLE: + tests for basic comments
mylesborins has joined #elliottcable
mylesborins has quit [Remote host closed the connection]
<ELLIOTTCABLE> holy shit this eldritch horror *works*
<ELLIOTTCABLE> fucking look at this lexer lmao.
<ELLIOTTCABLE> it, badly, handles nested block-comments.
mylesborins has joined #elliottcable
mylesborins has quit [Client Quit]
mylesborins has joined #elliottcable
muelleme has joined #elliottcable
muelleme has quit [Client Quit]
<jfhbrook> what the frick is that >:O
<jfhbrook> ocaml's match/case syntax is kinda gross
<jfhbrook> but I like that it has fall-through
<ELLIOTTCABLE> what!
<ELLIOTTCABLE> and … it doesn't have fall-through …
<ELLIOTTCABLE> and gross compared to what?
<ELLIOTTCABLE> :P
<ELLIOTTCABLE> anyway it's not actually OCaml
<ELLIOTTCABLE> it's an OCaml macro / preprocessing extension, known as a PPC
<ELLIOTTCABLE> PPX
<ELLIOTTCABLE> it's actually a really fucking smart system: preprocessors aren't allowed to *arbitrarily* modify the document, or even the AST β€” they're only allowed to operate inside blocks that the user explicitly specifies
<ELLIOTTCABLE> *but* that explicit specification takes a few forms, all of them are very brief / of light syntactic weight
<ELLIOTTCABLE> further, with one specific exception (the `{| … |}` form), all prepossessing must still lex/parse *as OCaml code*.
<ELLIOTTCABLE> so no matter what you do, everything still hilights in editors, blah blah blah.
<ELLIOTTCABLE> so for instance the syntax extensions in heavy use in that file are from two tools: Sedlex (well, technically, ppx_sedlex) up in the top half of the file, and ppx_expect/ppx_inline_test down in the bottom half
<ELLIOTTCABLE> so a normal `match … with` statement *looks*, syntactically, pretty similar to those blocks; but because I wrote `match%sedlex`, the sedlex extension is allowed to hook into that extension-point in the AST, and completely rewrite anything in or below that node
<ELLIOTTCABLE> so a `match%sedlex … with` statement actually works nothing like a standard match-statement. it is, instead, compiled down into a state-machine lexing engine.
<ELLIOTTCABLE> it's *just* using the match format as a familiar-feeling language in which to write, and allowing arbitrary OCaml in the match bodies
<ELLIOTTCABLE> (a bit like quasiquotation β€” in this example, everything to the right of each `->`is plain OCaml.)
<ELLIOTTCABLE> I thought it was a really weird system at first β€” it felt less powerful/flexible than Scheme macros, and *also* less powerful/flexible than Ruby-style metaprogramming / DSLs, at first
<ELLIOTTCABLE> but obv. this is all still *strongly typed*, which took a while to settle in.
<ELLIOTTCABLE> now that I get it tho. woahdamn, son.
<ELLIOTTCABLE> anyway
<ELLIOTTCABLE> also rly cool is the ppx_expect testing down below
<ELLIOTTCABLE> I can do pretty standard boolean-equality chains and predicates (`let%test`), as well as simple β€˜this should execute imperatively and not throw an exception’ (`let%test_unit`),
<ELLIOTTCABLE> but `let%test_expect` is a fucking neato, special beast
<ELLIOTTCABLE> better shown than explained.
<ELLIOTTCABLE> if I type this in a file:
<ELLIOTTCABLE> `let%test_expect "test doubling" = printf "%d" (2 * 2)`
<ELLIOTTCABLE> notice, I don't say *anything* about what that *should equal* β€” I just directly exercise some code, printing results or intermediate values as I please
<ELLIOTTCABLE> and then invoke it,
<ELLIOTTCABLE> I get this:
<ELLIOTTCABLE> the test "failed", predictably. but, way more interestingly, it literally gave me a *diff* that I can execute, to make it pass.
<ELLIOTTCABLE> in this case, it adds another (unfortunately, much uglier β€” though I plan to do something about that, by the by) line after the last line of code
<ELLIOTTCABLE> but here's the kicker: since that format allows automatic generation of fixes, like that … I can just tell my testing framework or whatever to *fix everything for me*.
<ELLIOTTCABLE> without opening my editor, confirming values, or ever bothering to explain in code what `2 * 2` is *supposed* to be/mean/match/equal
<ELLIOTTCABLE> I can just let my testing-framework *generate* that information and record it right there, in the test, on its own.
<ELLIOTTCABLE> with one command. feels like fucking magic.
<ELLIOTTCABLE> *definately* bringing something like this back to JavaScript with me. 🀣
<ELLIOTTCABLE> here's a more concrete example of it in action:
<ELLIOTTCABLE> ignore ↓
<purr\GH> [ocameel] ELLIOTTCABLE pushed 4 new commits to sedlex-w-o-menhir: https://github.com/ELLIOTTCABLE/ocameel/compare/75df71832a00...162f92495591
<purr\GH> ocameel/sedlex-w-o-menhir eb15121 ELLIOTTCABLE: + more regexen for numerics
<purr\GH> ocameel/sedlex-w-o-menhir da08b85 ELLIOTTCABLE: + refining lexer regexen, preparing to lex numerics
<purr\GH> ocameel/sedlex-w-o-menhir cddee50 ELLIOTTCABLE: + adding lexing of the hash-semi for sexp-commenting
<ELLIOTTCABLE> two tests, three expectations
<ELLIOTTCABLE> and I didn't have to put any effort into thinking β€œwhat *should* happen here, how do I encode that into the test …”
<ELLIOTTCABLE> I just wrote (in that case, copy-pasted, actually) some code that exercised the unit-under-test, hit run, and saw if I liked the output
<ELLIOTTCABLE> and when I did, `dune promote`, and all three tests were passing.
<ELLIOTTCABLE> *deep breath*
<ELLIOTTCABLE> </rant> but hey it's fucken cool
<ELLIOTTCABLE> Β―\_(ツ)_/Β―
<jfhbrook> ELLIOTTCABLE: reading up but I misspoke--multiple matchers per case, where you have | whatever on contiguous lines
<ELLIOTTCABLE> ahhhhh. yeah, it's very haskell-y in that way, I suspect. and those *could* be all on one like; I just made a stylistic choice.
<jfhbrook> gross compared to scala ^__^ and like I know I don't have room to talk but I'm used to it and I appreciate its use of keywords and c-ish sometimes syntax
<ELLIOTTCABLE> heh I love my JS
<ELLIOTTCABLE> OCaml's syntax is weeeeeeird, for suresies
<ELLIOTTCABLE> but that's why we have ReasonML / refmt!
<jfhbrook> I'm really really shitty at reasoning about true macros
<jfhbrook> I did a little bit of it when I worked through Land of Lisp
<jfhbrook> (and hacked on common lisp for like 6 weeks before realizing the libraries are nonexistent, the runtimes are a mess and the people are just god-awful)
<jfhbrook> but I sucked at it then, and every time I've seen it since I've just gotten more confused
<jfhbrook> like lisp at least has a really simple syntax, which lends itself to a simple-looking macro system
<jfhbrook> a friend of mine wrote some nifty scala macros
<jfhbrook> in scala by default regular expressions are constructed at runtime because .r is a method on arbitrary strings that returns a regular expression object
<jfhbrook> so if you pull in macrame's regexp macro, then you can use the string interpolation thinger instead and go r"some regexp"
<jfhbrook> does the babel preprocessor count as a macro engine?
<jfhbrook> like that's how people implement things like jsx and flow no?