ec changed the topic of #elliottcable to: a 𝕯𝖊𝖓 𝖔𝖋 𝕯𝖊𝖙𝖊𝖗𝖒𝖎𝖓𝖊𝖉 𝕯𝖆𝖒𝖘𝖊𝖑𝖘 slash s͔̞u͕͙p͙͓e̜̺r̼̦i̼̜o̖̬r̙̙ c̝͉ụ̧͘ḷ̡͙ţ͓̀ || #ELLIOTTCABLE is not about ELLIOTTCABLE
<alexgordon> it's suuuuuper nice
<alexgordon> have you seen the async{} syntax?
<alexgordon> ec: so I'm making a language that compiles to python but doesn't suck
<alexgordon> actually it should compile to JS too no problem
<alexgordon> but I have no desire to implement that
<alexgordon> syntax design is done, gonna start on the tokenizer
<alexgordon> but first...
alexgordon is now known as drparse
<drparse> I put on my lab coat and my wizard hat
<jfhbrook> ahahaha
<drparse> I can practically write a tokenizer blindfolded these days
<drparse> also LOL at the difference writing one in JS vs writing one in C++
<drparse> so nice
<drparse> especially with ES2018 unicode regexes
<drparse> woohoo my tokenizer works
Sgeo has quit [Read error: Connection reset by peer]
Sgeo has joined #elliottcable
drparse has quit [Quit: Textual IRC Client: www.textualapp.com]
<ec> you're writing a tokenizer manually …
_whitelogger has joined #elliottcable
alexgordon has joined #elliottcable
<alexgordon> ec:
alexgordon has quit [Quit: My MacBook Pro has gone to sleep. ZZZzzz…]
alexgordon has joined #elliottcable
alexgordon has quit [Quit: My MacBook Pro has gone to sleep. ZZZzzz…]
alexgordon has joined #elliottcable
<ec> alexgordon: 00:00:36 <+ec> you're writing a tokenizer manually …
<alexgordon> yeah how else?
<ec> lexer generators?
<alexgordon> those are pretty old fashioned nowadays
<alexgordon> the problem is that many languages have very complex tokenization state machines, especially wrt string literals
<ec> ¯\_(ツ)_/¯ not exactly complicated to handle
<alexgordon> like you can `foo ${ bar ` baz ${ ham } ` } `
<ec> modal lexer, duh?
<alexgordon> easier to just do it manually, I mean I still use regexes lol
<ec> lolol
<alexgordon> the y flag is a lifesaver
<ec> I do a lot of both
<alexgordon> also it means I get proper unicode support
<ec> the one I linked is half generative, actually
<alexgordon> implementing unicode identifiers using a lexer generator would be HELL
<ec> oh honey.
<alexgordon> I can just do \p{L}
<ec> click the link lol
<ec> been there done that learned about the viramas. :P
<alexgordon> lolol
<ec> luckily, OCaml. also luckily, not the first. basically just had to glue together a lot of battle-class libraries like uucd and uunf and sedlex and menhir.
<ec> (sorry, the "oh honey" was uncalled for — but I *am* pretty proud of my solution to that *exact* problem 🤣)
<ec> tt?
<alexgordon> tokentype
<alexgordon> basically I just wrote a syntax highlighter lol, this is how textmate grammars work
<ec> and what's /y — can't believe there's something about regex that I don't know, but,
<alexgordon> y means match only at lastIndex
<alexgordon> it's new
<ec> ahhhhhhhhh relief
<alexgordon> pretty awesome for writing tokenizers
<ec> quote Mr. Incredible — “They changed *math!?* Who changes *math!?*”
<ec> I mean, issues with Earley gens aside, why not just use the pretty-standard Nearly/Moo combination?
<alexgordon> just realised that my nesting comments don't actually nest lol
<ec> I've only used it once for a job interview, and like, I prefer very strict, explanatory LR(1) generators that handle shift/reduce conflicts predictably at compile-time, but … it wasn't a *bad* experience
<alexgordon> yeah I have to figure out my parser next
<alexgordon> but I will hand write a recursive descent for that too
<ec> “It uses the new ES6 sticky flag where possible to make things faster” hey look it uses the /y, there ya go
<ec> lord alex why, why
<alexgordon> because I want to handle arbitrary operator tables
<ec> don't you have better things to be doing w/ your life
<ec> hahahaha
<alexgordon> ec: oh yeah I just did it while I was waiting for a database dump to import
<ec> every time I talk to you you're hand-rolling another parser
<alexgordon> it's this channel
<alexgordon> it inspires me
<ec> at this point you could have spent all that time hand-rolling a *parser generator* -_-
<ec> hahahahaha
<alexgordon> nah I'm done with parser generators
<alexgordon> I've spent so much time fighting parser generators
<alexgordon> at some point, it's better to just learn how to do it yourself
<ec> for good reason! they tell you useful things.
<alexgordon> then you can get perfect error handling
<ec> a good gen (… menhir …) gives you good introspection, error-handling, and interactive driving, when and where you need them, *and* the safety and analysis of a gen
<ec> also, perfect error-handling is a static property of any state-machine parser. keyword static! derivable at compile-time! I mean, lookit dis stuff, you'll love it. http://gallium.inria.fr/~fpottier/menhir/manual.html#sec67
<ec> things I say out loud, in real life, to people: “I feel that parser generators are inherently redneck.”
<alexgordon> hand written recursive descent all the way man
<ec> so much time
<ec> so much time.
<alexgordon> not really
<alexgordon> this tokenizer took me less time than using a generator
<alexgordon> a couple of hours
<alexgordon> I have to figure out the syntax before I can write the parser though
<ec> lolol also why are you wasting time designing syntaxes
<ec> nobody cares about syntax ;)
<alexgordon> I care!
<jfhbrook> I like me a good syntax
<alexgordon> see!
<alexgordon> I'm trying to figure out what the best syntax for a list comprehension would be
<jfhbrook> well python nailed it obvs
<jfhbrook> just copy python ;D
<alexgordon> nahhh
<alexgordon> well generator comprehensions are the more basic concept
<alexgordon> ( f(x) for x in y if p(x) ) is just (function*(){ for (let x of y) { if(p(x)) yield f(x); })()
<ec> gotta say I still don't grasp python's list comprehensions
<ec> CoffeeScript had them, and I still haven't used them *once* in my, like, five-ish years with CoffeeScript
<alexgordon> a generator comprehension is just something that implicitly wraps (function*(){ })() around the outside
<alexgordon> python's are better
<alexgordon> ec: it's simple the idea is that it allows you to do both map and filter at the same time efficiently
<alexgordon> the question is how can you integrate that into a language
<alexgordon> python has its own kind of meta language for list comprehensions which is annoyingly different
<alexgordon> C# is even worse with linq
<ec> show me
<alexgordon> the ideal is that the comprehensions just fit in
<alexgordon> which? python or C#?
<alexgordon> python is like [ x for x in y ]
<jfhbrook> I thought linq was supposta be ok?
<alexgordon> oh yeah it's fine
<jfhbrook> haven't used, thought about doing so once though
<alexgordon> but it's very _separate_
<alexgordon> like it doesn't look like the rest of C#
<jfhbrook> I had a project idea around making an app that runs a win10 start menu tile
<alexgordon> you are going into a separate mode of the language
<jfhbrook> the framework around it is super smooth but I ran out of steam
<jfhbrook> oh, yeah, I see why you made the comparison to comps in python
<jfhbrook> what if for loops returned an iterable?
<alexgordon> linq is like SQL select x from y blah blah blah
<alexgordon> yeah that's one thing I'm thinking about
<jfhbrook> like in scala an if statement will evaluate to the last statement in the branch that got executed
<jfhbrook> a lot like a javascript ternary
<alexgordon> hm yeah
<alexgordon> see what I would love to do in python comprehensions is make new variable bindings
<alexgordon> [ for x in y let z = x * 2 if z > 4 yield z ]
<ec> oh my fucking lord, annex b strikes again
<alexgordon> what's annex b?
<alexgordon> I'm not suggesting that as a real syntax, just thinking aloud
<ec> re: parsing things line /\1/ or /\11/ or /\400/
<ec> “The rule is that the whole number is taken as a decimal backreference number, but if it has leading zeros or it is out of range (there are not enough capture parentheses) we abandon that interpretation, switch number base, and reinterpret it as up to 3 digits of octal escape up to 255 (\377), possibly followed by literal numbers.”
<ec> holy shitfuck, javascript.
<alexgordon> wow that's horrible
<ec> alexgordon: annex b, the ECMAScript standard for "staying fucky enough to continue to be The Web"
<alexgordon> sometimes it's better just to break people's code
<alexgordon> ec: why would you write a backreference in octal?!
<alexgordon> nobody in the history of the world has done that
<alexgordon> I think that comprehensions are connected to threading operators |>
<alexgordon> if you have [ f(x) for x in y ] that's like a pointy version of y |> map f
<alexgordon> [ f(x) for x in y if p(x) ] would be y |> filter p |> map f
<alexgordon> but the advantage is you can declare a variable
<alexgordon> and have multiple loops
<alexgordon> like [ f(x) for y in z for x in y ] is ummm
<alexgordon> z |> map (fun y -> y |> map f) |> flatten
<alexgordon> I wish micah was here :(
<alexgordon> ok I wonder if you can meet in the middle
<alexgordon> write a comprehension as [ for x in y filter p(x) map f(x) ]
<alexgordon> [ y for x filter p(x) map f(x) ]
<alexgordon> that's strictly less powerful though
<alexgordon> the thing is you can intersperse conditionals and loops...
<alexgordon> [ for y in z if p1(y) for x in y if p2(x) yield f(x) ]
<alexgordon> so I think map is the wrong abstraction
<alexgordon> it's more like: _for z (fun y -> _if p1(y) (fun -> ...etc ) )
<alexgordon> like imagine there was a threading operator ||> such that arr ||> f executed f for each item in arr
<alexgordon> and imagine it would give you a lambda as well
<alexgordon> then you could do: z |y|> f(y)
<ec> alexgordon: micah's around, in general
<ec> I'd have more to say if you explained what a comprehension was, and what problem it solves :P
<alexgordon> ec: what don't you understand about comprehensions exactly
<ec> otherwise, I'm just reading about structural-vs-physical-equality, and encoding comparison functions into the type-system
<ec> like literally anything. I find the syntax as opaque as I used to find the type-arrow syntax.
<ec> what is *the point*. Maybe show me a standard (in JavaScript) operation of some sort, and how comprehensions make that better?
<alexgordon> okay
<alexgordon> [1,2,3,4].filter(x => x % 2 === 0).map(x => x * 10)
<alexgordon> is with comprehensions
<alexgordon> [ x * 10 for x in [1, 2, 3, 4] if x % 2 === 0 ]
<alexgordon> but with advantage that only one array is allocated, it's one operation
<ec> I find that nigh-unreadable, and it's like, even literally the same number of characters, ish … but way more importantly, it's *conceptually heavyweight* — the former uses only simple (well, not simple. but *the same*.) concepts used pervasively elsewhere in the language … functions, scope … and the latter involves teaching something *new*?
<ec> idk I just dgi
<ec> ¯\_(ツ)_/¯
<ec> oh lord it's a microop. okay, now I see.
<alexgordon> well it generalizes...
<alexgordon> that's just a simple example
<alexgordon> for you to understand the concept :P
<ec> lodash tried and failed to do the same thing for javascript and failed horribly 🤣
<alexgordon> anyway it's actually doing something more like: Array.from((function*() { for (let x of [1, 2, 3, 4]) { if (x % 2 === 0) { yield x; } })())
<alexgordon> but you can have multiple loops, so you can write flatten as: def flatten(xss): return [ x for xs in xss for x in xs ]
<ec> so it can fuse multiple iterations, not just *one* map and *one* filter?
<alexgordon> yeah
<ec> that sounds a lot more useful 😄
<alexgordon> which is equivalent to Array.from((function*() { for (let xs of xss) { for (let x of xs) { yield x; } })())
<alexgordon> and also it works for sets and maps
<alexgordon> I use a lot of dictionary comprehensions
<ec> betcha there's either an ES proposal, or Sweet.js macro, for that in JS :P
<alexgordon> e.g. you could do { k: f(v) for k, v in zip(keys, values) }
<alexgordon> ec: it was rejected from es6 :P
<ec> jfhbrook: you're a big Scala guy, right?
<alexgordon> removed from the standard
<alexgordon> { k: f(v) for k, v in zip(keys, values) } would be equivalent to new Map((function*(){ for (let [k, v] of _.zip(keys, values) { yield [k, f(v)] })())
<alexgordon> ec: check out https://norvig.com/spell-correct.html
<alexgordon> anyway while I like the power of list comprehensions i lament that they are kind of a separate meta language inside python
<alexgordon> considering that the transformation to non-comprehension code is so mechanical it's a shame that you have to go into a separate syntax mode to use them
<alexgordon> it would be much better if the main language was extended to make comprehensions possible in normal code
<jfhbrook> ec: I do scala stuff sometimes at work and was pretty pleased with it yeah
<jfhbrook> ec: I don't do enough fp to argue its merits and weaknesses as compared to ocaml or haskell, though
<alexgordon> stick to ocaml :P
<alexgordon> I find scala kind of weird, I mean if I had to do FP in a jvm environment, it would be pretty cool
<alexgordon> but if I could choose between scala and F# I would pick F# every time
<alexgordon> if you are doing FP
<ec> jfhbrook: not that
<ec> jfhbrook: just thought you might enjoy this!
<ec> it's a really cool real-world application of staged programming; and it's fully dually implemented in both OCaml (via BER) and Scala (via LMS)
<alexgordon> ooh
<alexgordon> I've figured it out
<alexgordon> basically you have calls interspersed with lambdas in a very regular pattern
<alexgordon> O1 a1 (\p1 -> O2 a2 (\p2 -> ... ))
<alexgordon> and the parens are not really necessary
<alexgordon> O1 a1 \p1 -> O2 a2 \p2 -> ...
<alexgordon> then eventually you get to yield and the chain stops
<alexgordon> so the "natural" way to write it would actually be to have Oi be an infix operator
<alexgordon> a1 `O1` \p1 -> a2 `O2` \p2 -> ... yield an
<alexgordon> z for y ▷ p1(y) if ▷ y for x ▷ p2(x) if ▷ yield f(y)
<alexgordon> but that just looks weird haha
<jfhbrook> oh, uh
<jfhbrook> idk what staged programming is in this context, but
<ec> aw fuck
<ec> I thought you'd be the only one who could maybe appreciate how cool that is v.v
<ec> supermacros, I guess? but fully type-safe, across compilation stages? and with arbitrary N separate stages, instead of just "compiletime" and "runtime"?
<jfhbrook> this is kinda the standard-ish thing for streams in scala? kind of? the scala ecosystem for fp is super fucked up
<ec> this is very relevant to what alexgordon's talking about, I think, but idk if he knows much scala or ocaml to read it
<jfhbrook> because the scalaz founder went off the deep end and started telling everybody to use haskell instead and just became super sour, then went on an anti-CoC kick and so
<jfhbrook> you know how that shit goes
<alexgordon> ec: sounds like lisp
<ec> well only in that anything with macros "sounds like lisp"
<jfhbrook> they're not necessarily lambdaconf attendees but those people would feel more welcomed there vs cats, which is what typelevel built when they realized they wouldn't be able to build their platform on top of scalaz
<ec> lisp is untyped, so it's not really relevant ¯\_(ツ)_/¯
<alexgordon> ec: I mean the multiple compilation stages
* ec nods
<ec> hygienic macros are cool and nice, but vastly more interesting/difficult to do well in a strongly-typed environment — especially while achieving soundness
<ec> a lot of the solutions basically have a `unevaluated` 2nd-level type, so you can have something like `unevaluated(list(integer))` or w/e. that doesn't solve unquote and elision though …
<ec> LMS, I understand, is one of the most powerful implementations of all of that (woo Scala, I guess? I don't know Scala, so I can't comment well); and MetaOCaml is a more-academic-but-less-widely-used-in-the-real-world implementation of the same concepts, plus a proof of correctness
<ec> LMS = Lightweight Modular Staging for Scala, BER = "BER MetaOCaml", I think BER is the university or some shit
<ec> oh, weird, nope, it's just … the name. With no explanation.
<ec> “Walid Taha suggested to name the new, bare-minimum line of MetaOCaml as BER MetaOCaml.”
<ec> oh..kay?
<ec> lol.
<ec> good lord Scala's syntax what the fuck
<alexgordon> hahah
<alexgordon> welcome to scala
alexgordon has quit [Quit: My MacBook Pro has gone to sleep. ZZZzzz…]
alexgordon has joined #elliottcable