[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)