1,295 karma · joined March 19, 2013
(I’m assuming you meant to convey a slightly negative connotation through “mathematical”. Though I myself do like PS too)
I’ve also noticed that it “pivoted” to focus more on math; is that intentional?
Anyway, good to see it on HN again. Anything that pushes more pattern matching research is a plus for me =). Mainstream languages barely started to adopt first-order pattern matching!
But I believe the topic here was about runtime performance of using a language to compile JS, not about the build speed of working in that language itself. In which case you’ll still get some wins writing a JS toolchain in BuckleScript (compiled to JS), just from the JiT-friendliness of the BuckleScript JS output.
But realistically, you’d be compiling to native OCaml through the same codebase. We did see a 10-25x perf jump from converting a part of a Babel pipeline to native OCaml. I mean, these languages are basically designed over decades with AST manipulation in mind, so that’s not surprising.
> the compiler is designed to remain on-line at runtime so that functions can be recompiled when the need arises, and generated machine code can adapt to the instruction set present on the target machine. This also diminishes the need for a build system
Diminishing the need for a build system is nice! Any other language with such philosophy in mind?
I work on Reason so I’m biased, but I believe the Reprocessing flappy bird clone live coding session at https://github.com/Schmavery/FlappyBird/blob/master/README.m... was one of the only times where I see folks work on a single codebase in native from scratch, compile _once_ to web, and have everything _truly_ work first shot, during a live demo nonetheless.
It's a single codebase and build system. There's platform-specific code buried in some conditional compilation in the Reprocessing drawing lib he uses: https://github.com/Schmavery/reprocessing
Here's a livestream of the Reprocessing folks making a flappy bird clone (https://github.com/schmavery/flappybird) from scratch: https://www.youtube.com/watch?v=5aD3aPvNpyQ&feature=youtu.be...
Explicitly inspired by the former, same build paradigm, doesn't use FUSE. Has some neat git integrations. Doesn't work on macOS/Windows yet though.
One funny feature that falls from the design is that you can just keep running & failing a fac build, and it'll nudge you toward the correct build.
Lack of names: this deserves to be solved. OCaml in particular pays a bit more attention to it than others. Labeled arguments, inline records, objects, variant constructors, etc. are all solutions to this. Tuple's usually the target of criticism when it comes to lack of names, and I do think the criticism is mostly valid. The convenient-ness of a language feature dictates its usage. When you can trivially return an obj/map from js/clojure you wouldn't resort to returning an array of 2 elements. But when these alternatives are heavier in a language (ocaml objs are rather heavy visually and have no destructuring; records need upfront declaration), you do see a bit more of the proliferation of tuples. This can be solved, but since it's deemed an "uninteresting" problem, it stays as one of the low-hanging fruits. In general, though, I've come to appreciate OCaml's pragmatism regarding these matters. It does try to solve these language usability concerns. The other offender is parametric types, but the situation is the same in typed JS solutions.
Hard to track "mutations": tangentially related, but in parallel universe where FP is pervasive, I can see how folks might say "hey this pattern of passing a self-like argument first is used so often, we should create a new syntax for it (dot access) and optimize it specially for perf & tooling". Anyway, uniformity by definition erases distinguishability; sometimes the distinguishability is appreciated for e.g. perf and ease of grepping. Note how recent JS syntactical features are almost always faster than their polyfilled equivalent (obj spread, async, generator, arrow function).
Partial evaluation: the "monad" of beginner FP experience basically, in terms of social effects. From watching the community for so long, currying often seem to elicit a period of "this is weird -> oh I get it -> this is the greatest thing and I'll violently defend it against naysayers -> you know what, it's not all great; it's fine". Currying in an eager, side-effectful language is actually troublesome to implement & use. Some compilers don't optimize them, or worse don't even get them semantically right. Won't cite examples.
Higher-order functions: same problem in JS. But yeah, combined with partial app this isn't immediately clear: `Foo.bar(baz(qux))`. What's the arity of `baz`? More importantly, at what "stage/state" of the function's logic are we at now? For that specific example, you can argue that the name `x` isn't that much more indicative (which ties back to the first point). But these are the exceptions rather than the norm. I'm sure people are fine reading `map(foo)`. The general point's still valid.
===========
I'll stop here because I'm bored, but you can see how these things aren't black and white once everyone just take a deep breath, think a little, and find a way to communicate a bit more nicely with each other. In some of the above points, I'm playing the devil's advocate because I feel it's needed to balance the overwhelmingly negative sentiment. Sorry if my emotions come through a bit here, but it's a bit sad to see that that some of the less polite replies I've seen come from FP folks who actually barely started FP, through ReactJS/React Native, got overly excited to finally find a target to criticize in an act of catharsis, without realizing they're criticizing the co-author of said frameworks. Look, people are watching; disregarding whether the author's points are right, you'll be judged on how you react to them. And your collective reaction is a good assessment of how resilient the paradigm is against the real-world's sometimes nitpicky, sometimes serious, criticisms. The best engineers I've worked/am working with, are able to cite tradeoffs and admit that their paradigm isn't perfect. It's an indicator that you've finally "got it", that you're able to assess a subject's nuances rather than seeing it as a binary thing.
I'm a bit frustrated to see that vjeux's post had to be retracted and that he had to apologize. Imagine the potential improvements we could have collectively made had these issues not been casually/emotionally dismissed. Now once again the gist and this reply will be forgotten and we'll have to move on and count on word-of-mouth to propagate solutions to these criticisms rather than codify it somewhere like the programmers we should be. On the other hand, I am glad to see that most of the harsh replies don't come from the Reason community. Ultimately, I wish the community to learn to welcome newcomers, to learn _how_ to educate (and not just what), to understand FP's tradeoffs, to stay mature to get work done.
- Fast dev workflow. The dependencies are kept relatively minimal, which is very appreciated. - Very little magic. Doesn't opt you into a particular e.g. css paradigm. I personally appreciate the sweet spot where things "Just Work", but thanks to simplicity and obviousness, rather than explicitly architecting (though I'm sure the team actually put lots of thoughts into the design). - Generates clean, idempotent static output, that you can manually introspect. A small source change leads to a small artifact change. A nice consequence derived from its simplicity. - Generates static sites that work without JS, naturally. You can also progressively enhance it through regular JS. - i18n! Super grateful we didn't need to handle that ourselves.
Haven't tried versioning, but we'd love to look into that as well.
Thank you Docusaurus team =)
> As a bonus, you also get "constructors with equations" for free. E.g., suppose that we want lists to automagically stay sorted and eliminate duplicates. In Pure we can do this by simply adding the following equations for the : constructor:
> x:y:xs = y:x:xs if x>y; x:y:xs = x:xs if x==y;
> [13,7,9,7,1]+[1,9,7,5];
[1,5,7,9,13]
(The point about this global override is addressed later. The rewriting can be lexically scoped.)Maybe you're hitting a pathological use-case because of the nature of your API. In which case you can always wrap it inside a single function and just do `<MyMarkdown text={bla} />`
BuckleScript's author and I collaborate on a daily basis, btw. So you're definitely welcome to use _just_ BuckleScript. I'm not too sure your reaction is genuine happiness for vanilla OCaml, but if it really is, then our mission's accomplished (https://reasonml.github.io/guide/what-and-why#why-reason). If not, sorry about that.
_This_, I do think, is a fair argument. It's indeed an accidental drawback of the syntax revamp. Though there are very realistic way to prevent the confusion: https://github.com/reasonml-community/error-message-improvem...
Regarding optimization: see the BuckleScript link on explicit uncurrying. The impact is very visible: the compiler analysis for specializing for uncurrying best-effort, and when it bails, it looks like this: https://reasonml.github.io/try/?reason=PQKgBA5g9lAmYGMCGBnAp... which calls https://github.com/BuckleScript/bucklescript/blob/2a66960b5a.... How many function calls did your curried call just turn into, in the second case?
Unless you introspect the output (which is actually viable to do in a compiler with clean output, such as BuckleScript), you wouldn't know that your higher-order function accidentally became pretty much 4+ calls instead of one. Now imagine quadrupling every high-order function calls or so. BucklesScript (and native OCaml) do a crazy good job of avoiding this when possible, more so than most, as shown in the snippet's first scenario; the manual even shows guaranteed uncurry if you put the right annotation. But if you want to take advantage of _that_ (and please do), there are other tradeoffs as well, but I digress. In general, the compiled code's speed is as good as you can get for JS output.
The perf point alone is not a pedantic argument as you can see. And you might start wondering about other languages' output for currying. Regarding your other comment: yes, from a typing perspective, currying indeed works out wonderfully for pure languages like Elm and PureScript. But OCaml's not a pure language; we've made other tradeoffs; and context matters.
Not sure about your comment about the AST, but I think you're saying that the situation doesn't get better/worse in the new syntax: this is true, since the syntax revamp is really just that: a syntax change. Which is why I said earlier that I was arguing beside the point. But currying seems to attract so much unbalanced attention in this context that I felt I should address it so that it doesn't overwhelm the rest of the syntax change's purpose. Looking at the rest of the threads, it still did, but I'm glad your reaction has been doubt rather than unreasoned negativity, so thanks for that.
From an individual standpoint, there are some unique aspects of OCaml that we like a lot. The properties of BuckleScript for example (tiny output, great js interop, fast simple compilation).
No doubt that the ecosystem could be improved, but that's what we're here for and what we're willing to do.
Don't take my words for it: https://github.com/facebook/reason/pull/1299#issuecomment-30... https://realworldocaml.org/v1/en/html/imperative-programming... https://drup.github.io/2016/08/02/difflists/ https://bucklescript.github.io/bucklescript/Manual.html#_cal...
I'm jumping into this conversation early on because too often this point is raised and turns into an uncharitable interpretation of our motivations, e.g. "look at these js programmers, not understanding the beauty of currying". Rest assured that we do (and that we're not just js programmers), and that the Merlin and BuckleScript authors know very well what they're doing. Hope this clarifies things a bit.
The JS part of messenger.com bugs a lot more.
In short, every part works, but the workflow is a bit contorted atm
We'll try to make it into a proper compiler plugin, but it's not trivial right now
But the thing to realize is that this syntax change isn't for folks and you and me. We'll be fine with either.