[HN Gopher] Clio: A functional, distributed programming language...
       ___________________________________________________________________
        
       Clio: A functional, distributed programming language that compiles
       to JavaScript
        
       Author : ibraheemdev
       Score  : 125 points
       Date   : 2021-03-17 16:06 UTC (1 days ago)
        
 (HTM) web link (github.com)
 (TXT) w3m dump (github.com)
        
       | zemnmez wrote:
       | How do you make a parallel language that transpiles to a
       | reentrant one?
        
         | chrisseaton wrote:
         | Can you use the Web Workers API and lower to a message passing
         | model?
        
         | twiss wrote:
         | It seems like it uses Web Workers
         | (https://developer.mozilla.org/en-
         | US/docs/Web/API/Web_Workers...)
        
           | brundolf wrote:
           | To get more specific for those who may not be as familiar
           | with the nuances of JS: JS can start parallel threads, it
           | just - importantly - cannot _share memory_ between them
           | (instead it must pass messages, copying data at boundaries).
           | This eliminates a large number of benefits and usecases that
           | tend to be associated with  "multithreaded programming", but
           | saying JS "isn't multi-threaded" isn't quite true.
        
             | twiss wrote:
             | For what it's worth, there's some limited ability to share
             | memory (https://developer.mozilla.org/en-
             | US/docs/Web/JavaScript/Refe...), though you can only share
             | binary data, not other types, and it only works in secure
             | and cross-origin isolated contexts, due to security
             | concerns.
             | 
             | That being said, at first glance it doesn't look like Clio
             | is using this, instead it's passing messages as you
             | suggest. It might actually be interesting to use
             | SharedArrayBuffers as a compilation target, as they're
             | probably hard to use correctly manually. That being said,
             | WebAssembly threads
             | (https://github.com/WebAssembly/threads) may be more
             | appropriate for this.
             | 
             | For completeness, Workers can also transfer memory
             | (https://developer.mozilla.org/en-
             | US/docs/Web/API/Transferabl...) with less security
             | restrictions. They can also collaborate by accessing a
             | shared database (https://developer.mozilla.org/en-
             | US/docs/Web/API/IndexedDB_A...) though this is obviously
             | slower than shared memory.
        
             | [deleted]
        
       | coolreader18 wrote:
       | Hmm, I'm not sure about this at the moment, at least based on the
       | available documentation - the first thing I tried to do was
       | extend the "parallel fib" example to be fully parallel inside
       | `fib` itself[0] but I wasn't able to figure out how to create a
       | `sum :: [int] -> int` function at first (it wasn't clear that
       | arrays are just JS Arrays, and I can just call methods on them)
       | and I'm still not sure why my code doesn't output anything.
       | 
       | [0]: https://clio-playground-pouyae.vercel.app/ with code:
       | fn fib n:           if n < 2: n           else: [n-1 n-2]
       | -> * await |fib|             -> *               console.log
       | sum              fn sum arr:           arr.reduce add 0
       | fn add a b:           a + b              export fn main args:
       | [5 6]             -> * await |fib|             -> * item:
       | console.log item
        
       | avinassh wrote:
       | What is a distributed programming language?
        
         | mirekrusin wrote:
         | btw. julia implements fantastic idea in its ssh cluster manager
         | - such a simple thing yet so powerfull; without knowing much
         | about the language I was able to distribute some computation
         | across all computers I had at home, really awesome. As a side
         | note it was also so easy to drop it on GPU. I'm really
         | impressed by julia, I'd love to use it more at work.
        
         | keithalewis wrote:
         | A distributed system is one in which the failure of a computer
         | you didn't even know existed can render your own computer
         | unusable. - Leslie Lamport
        
         | capableweb wrote:
         | Distributed computing is when you take a bunch of tasks one
         | computer (or CPU/computing units of choice) usually do and
         | spread it out to many computers (or CPU/computing units of
         | choice). This is to give faster execution compared to if you
         | did the work sequentially and is generally a pattern that is
         | gaining more and more popularity as of late.
         | 
         | A distributed programming language in this context means that
         | the programming facilitates this paradigm so it's easy to do
         | distributed programming with the language. In the case of Clio,
         | it also means it is distributed by default, so you write code
         | like normal and it's executed in a distributed fashion.
        
       | ubertaco wrote:
       | As a heads up, on the front page for the language (https://clio-
       | lang.org/), there's a "Visit our tutorial page" link that 404's.
       | There _is_ a tutorial though, if you go to the  "Learn" link, so
       | prolly the other link just needs to be updated.
        
       | toolslive wrote:
       | I couldn't find any information on the type system, But by the
       | look of it, there's no type inference. Is that correct?
        
       | montebicyclelo wrote:
       | Would be interesting to see a discussion of this vs Elm, which I
       | guess is the incumbent functional programming language that
       | compiles to Js (?).
        
       | efdb wrote:
       | i really like the syntax, very intuitive use of ->
        
         | runeks wrote:
         | I wonder if there's such a thing as intuitive syntax.
         | 
         | As far as I can see, the arrow signifies function application.
         | Why do you consider "a -> f" more intuitive than, say, "f(a)"
         | or "f a"?
        
           | aloisdg wrote:
           | because a -> f -> g -> h is better than h(g(f(a))). It is the
           | functional way of doing the OOP fluent builder pattern:
           | a.f().g().h()
           | 
           | It is the pipe operator (F#, Elixir, Haxe, etc.). There is a
           | proposal to add it to js too.
        
             | mlajtos wrote:
             | On top of that, it is a symmetrical to fat arrow functions,
             | which is a shorthand for lambda:
             | 
             | fun: x => x * 2
             | 
             | res: 4 -> fun
        
             | vorticalbox wrote:
             | I have always used ramdajs for this.
             | 
             | const R = require('ramda');
             | 
             | R.pipe(a,f,g,h)
        
       | dvh wrote:
       | I made something similar (temporal distribution rather than
       | spatial) an it was 70x slower than javascript, how slow compared
       | to JS is clio?
        
         | speedgoose wrote:
         | I wrote the fib example in plain JavaScript without async, just
         | old recursively in a loop, and it ran twice as slow compared to
         | Clio.
         | 
         | It's not a very high quality benchmark, but the overhead
         | doesn't seem bad on tiny examples.
        
           | [deleted]
        
           | SamBam wrote:
           | Since Clio compiles to JS, that speed up must be available in
           | vanilla JS as well.
           | 
           | Is it the use of web workers that makes that twice as fast?
        
             | chrisseaton wrote:
             | Clio has automatic parallelisation. JavaScript does not.
        
               | mcherm wrote:
               | How is generation of fibonacci numbers parallelized? I
               | mean, I can think of some ways to do it but I have
               | trouble believing that any compiler could generate them.
        
               | chrisseaton wrote:
               | > How is generation of fibonacci numbers parallelized?
               | 
               | Not sure if you're joking or not? Fib is the _classic_
               | first parallel benchmark, especially for functional
               | languages. The two tasks in each step are embarrassingly
               | parallel.
               | 
               | > I have trouble believing that any compiler could
               | generate them
               | 
               | Hah! I'd say I'd have a hard time believing compilers can
               | automatically parallelise anything else... because fib is
               | usually the only thing they're shown being able to do!
        
               | spenczar5 wrote:
               | Uh, Fibonacci is not embarrassingly parallel. That term
               | has a precise technical meaning; it is that the parallel
               | processes have no dependencies and require no
               | communication.
               | 
               | Fibonacci computations depend upon prior results, which
               | is why it is a poor fit for parallelization in general.
               | While, yes, it is possible to fork on every recurrence
               | and join to wait for the result, the overhead of that is
               | gigantic and dwarfs any benefits.
        
               | [deleted]
        
               | chrisseaton wrote:
               | > Fibonacci is not embarrassingly parallel
               | 
               | Just take a look at the code we're talking about
               | yourself. See the operator a + b between the two
               | recursions? There are zero data or control dependencies
               | between a and b. They can be perfectly distributed, which
               | is why it's been used as an example here.
               | 
               | Also read the note directed at the 'algorithms police'
               | here https://cilk.mit.edu/programming/ which I think will
               | pre-empt the point you're going to make next.
        
               | throwaway4good wrote:
               | Really? Can you expand on that? I have seen Fibonacci
               | being the poster child of the usefulness of memoization
               | and maybe tail recursion, but never parallelization.
        
               | chrisseaton wrote:
               | > I have seen Fibonacci being the poster child of the
               | usefulness of memoization and maybe tail recursion, but
               | never parallelization.
               | 
               | That baffles me. I think I've hardly read a paper on
               | parallel functional programming that doesn't start with
               | fib.
               | 
               | Here's example that agrees that it's the hello-world of
               | parallelisation.
               | 
               | https://wiki.haskell.org/Haskell_for_multicores
               | 
               | It's trivial for a compiler to automatically parallelise
               | it - for every binary operator evaluate the two operands
               | in parallel - done.
        
               | firebacon wrote:
               | Interesting to consider the total complexity of that
               | approach though.
               | 
               | An iterative fibonacci solution runs in linear time.
               | Calculating the N'th fibonacci number requires O(N)
               | serial operations.
               | 
               | A fully parallel, recursive solution without memoization
               | requires that each value in the sequence is computed more
               | than once. Consider the example of fib(4):
               | fib(4) = fib(3) + fib(2)        fib(3) = fib(2) + fib(1)
               | fib(2) = fib(1) + fib(0)
               | 
               | You can see, that if we run this in parallel, the value
               | of fib(1) has to be calculated twice. As the tree of
               | operation branches out, more and more duplicate
               | calculations are required.
               | 
               | A quick google suggests that the time complexity of the
               | recursive approach is O(2^N).
        
               | chrisseaton wrote:
               | > An iterative fibonacci solution runs in linear time.
               | 
               | Absolutely nobody is under the impression that the naive
               | parallel implementation of fib is actually useful code or
               | the most efficient way to do it. You're missing the point
               | if you're suggesting a different way to do it in the
               | first place.
               | 
               | It's just something to use as a running example... like
               | on the original article this whole thread is about.
        
               | SamBam wrote:
               | Ok, but it's a bit odd that you kept reacting with
               | incredulity at people not knowing that fib was _THE_
               | parallel example to know, and then it turns out it 's a
               | poor example because synchronous fib with memoization
               | (which is the way many people learn it in any early CS
               | class, and which wouldn't be possible async) is so much
               | faster.
               | 
               | I think maybe if there hadn't been such a vibe of "what,
               | you don't know X?!?" then it would have just been an
               | interesting fact to mention that parallelization demos
               | often use fib, because it's an easy example to grok
               | (though a confusing one if you already understand the
               | faster method).
        
               | [deleted]
        
               | [deleted]
        
               | johnday wrote:
               | The reason `fib` is a useful benchmark here is not
               | because `fib` is an inherently parallel problem, but
               | because the functionality is obvious and it's easy to
               | parallelise.
               | 
               | Computing fib with memoisation from 1 will _certainly_ be
               | faster than (parallel) recursion without memoisation and
               | data sharing.
        
               | cepher wrote:
               | I know that a parallel prefix algorithm [1] can be used
               | to calculate fib(n), since we can use repeated matrix
               | multiplications (a formulation appropriate for a prefix
               | sum algorithm). The computation time can be O(n/p + log
               | p), where p is the number of processors. However, I'm not
               | sure what other approaches there are.
               | 
               | [1] https://en.m.wikipedia.org/wiki/Prefix_sum
        
               | wccrawford wrote:
               | So far as I can tell, they typically "parallelize" it by
               | not memoizing it. It looks like they actually calculate
               | the whole thing recursively, twice.
               | 
               | That said, I found a parallel solution that was
               | interesting and should provide a speedup, but with a
               | large increase in complexity of the code.
               | 
               | https://stackoverflow.com/a/16464865/388173
        
               | nonameiguess wrote:
               | Great link and I like the mention of the fact there is
               | actually an analytical formula for the Fibonacci number
               | as well that allows computing it in constant time.
               | Unfortunately, machine precision issues make it nearly
               | impossible to accurately calculate anything large enough
               | to be worth the speedup you get as there is no practical
               | way to store enough of the digits in square root of 5, so
               | you need a symbolic algebra implementation that can
               | compute an exact answer and reduce it to a natural
               | number.
        
               | vlovich123 wrote:
               | Why symbolic algebra vs infinite precision floating point
               | which is comparatively much cheaper computationally (&
               | memory wise too?)?
        
         | capableweb wrote:
         | This language compiles to JavaScript, so it's 0x slower than
         | JavaScript. Comparing similarly named functions between Clio
         | and vanilla JS obviously wouldn't be fair as the feature-set
         | between the two are not equal.
        
           | elwell wrote:
           | The benchmark should be based on _idiomatic_ code in both
           | languages for a same (or similar) input - > output.
        
             | capableweb wrote:
             | You could do that but then your comparison is obviously
             | biased and not very useful.
        
               | dandellion wrote:
               | Picking a language is very subjective, so that's exactly
               | the kind of biased comparison that I want to judge
               | something like this.
        
               | kangalioo wrote:
               | Arguing that two programming languages must be considered
               | to have the same performance just because they compile
               | down to the same technology, is flawed.
               | 
               | Otherwise you couldn't make performance comparisons
               | between C, Rust, Go, Haskell, Julia, because they all
               | compile to assembly
        
               | capableweb wrote:
               | I'm not saying you can't, I'm saying that since the code
               | that eventually gets executed the same way just one layer
               | down, it's not useful to JUST consider the performance.
               | 
               | You're not using TypeScript to get faster JS execution.
               | You're using TypeScript to get types in JS. Compare
               | development speed and avoiding bugs together with
               | performance in that case. Same for Clio.
        
               | Fellshard wrote:
               | And what if every statement I write in the upper language
               | compiles down to one loop that runs a hundred times? The
               | target language is a lower bound, not an upper bound.
        
               | spenczar5 wrote:
               | Ok, but I still want to know how much of a performance
               | tax I am paying to know whether it's the right tool for
               | the job. If it's a thousand times slower, maybe that
               | overwhelms the benefits of extra features.
        
           | path411 wrote:
           | Every language compiles to assembly so it must be as fast as
           | assembly?
        
       | lelanthran wrote:
       | So many programming languages popping up like mushrooms
       | overnight...
       | 
       | That does it - I'm creating my own programming language (again)
       | which is going to be a mashup of C++ and Lisp; I shall call it
       | "Thee-Pluth-Pluth".
        
         | egonschiele wrote:
         | Is this a bad place to post my language that compiles to JS and
         | PHP?
         | 
         | https://github.com/egonschiele/salty
        
         | dunefox wrote:
         | https://github.com/clasp-developers/clasp
        
         | wealthyyy wrote:
         | I built my own language recently and called it Casi-no.
        
         | dastx wrote:
         | Don't forget the blackjack and hookers.
        
       | e-clinton wrote:
       | Beautiful syntax indeed. Has a very rustie feel
        
       | transfire wrote:
       | I just want to know what the `-> *` is all about. I assume `->`
       | is a pipe like sugar, but what about the asterisk?
        
         | [deleted]
        
         | liminal wrote:
         | I think I worked out it's an array.map function that takes the
         | same three arguments: (value, index, array)
        
       | crowdhailer wrote:
       | I'm struggling to get my head around why this is a distributed
       | programming language.
       | 
       | I saw the await key word for parallel fib but would like a bit
       | more information about what's actually happening to be parallel.
        
       | cies wrote:
       | > Suitable for scientific programming
       | 
       | How's that possible? JS does not have a good reputation in sci
       | prog, why would clio have?
        
         | capableweb wrote:
         | Because Clio is not JS, it compiles to JS?
         | 
         | There is plenty of ways of making JS handle any "scientific
         | programming" you can throw at it. It'll probably run slower
         | than what you can do by default in python-land or Julia, but
         | since Clio seems to automatically parallize your code, it might
         | have a chance.
        
           | hctaw wrote:
           | I'd be interested to see at what scale parallel evaluation in
           | Clio beats serial evaluation that has been compiled to native
           | machine code with basic compiler optimizations, for
           | scientific computing (say, solving nonlinear differential
           | equations).
           | 
           | My guess is it's enormous, but I could be wrong since
           | contemporary JS engines do quite well with numeric computing.
           | 
           | But there's a wealth of scientific computing that can't be
           | magically made to be parallel and the parallel equivalents
           | are often slower due to duplicated arithmetic and overhead in
           | setting up the computation (recursive computations are
           | particularly bad about this) - finding a parallel evaluation
           | strategy that is actually faster is nontrivial.
           | 
           | It's really not a safe assumption that parallel = faster.
        
           | cies wrote:
           | Sorry that's just an unfair claim. With this explanation
           | every general purpose programming language handles
           | "scientific programming".
        
             | capableweb wrote:
             | No, that's a weird conclusion if I ever saw one.
             | 
             | What can be claimed though is that any general purpose
             | programming language "can be made to" handle scientific
             | programming. I'm not saying you should, but it's possible
             | for sure.
             | 
             | Libraries like big.js for example make arbitrary-precision
             | decimal arithmetic possible on JS, which many considered
             | impossible to do in JS.
        
           | mgerullis wrote:
           | V8 is quite a lot faster than python (in most comparisons,
           | not all)
        
             | cies wrote:
             | We're talking specifically about sci prog here. I think for
             | one the ecosystem is just not there on JS.
        
             | Garlef wrote:
             | isn't python fast because it uses specific c++ (or c?)
             | modules in the background?
             | 
             | for example keras is a wrapper for tensorflow (c++). numpy
             | relies on c if i understand this correctly.
        
               | hctaw wrote:
               | I think it's more apt to say that Python isn't fast, but
               | it has FFI that can be used to interface with things that
               | are fast.
               | 
               | The same is true of JS though, and most interpreted
               | languages that have an escape hatch for FFI. The
               | difficulty of getting it to work may vary.
        
         | vmchale wrote:
         | It sounds way too slow too.
        
       ___________________________________________________________________
       (page generated 2021-03-18 23:01 UTC)