
Learn ClojureScript: Discovering Sequence Operations - kendru
https://www.learn-clojurescript.com/section-3/lesson-17-discovering-sequence-operations/
======
bikeshaving
I stopped using clojurescript around 2015, primarily because I was tired of
searching for/implementing clojure-idiomatic wrappers around the many
javascript libraries out there. Put another way, I left clojure on good terms,
and often missed its core functions, immutable data structures and lisp syntax
when writing front-end applications. However, since then, javascript has
changed a lot, specifically in terms of execution-suspending operators like
async/await/yield/yield*. Meanwhile, the core clojurescript team has almost
completely ignored these developments, preferring the immutable seq
abstraction over iterators, and the core.async channel abstraction over
promises/async iterators.

For this reason and this reason alone, I’ve personally stopped considering
clojurescript as a viable technology or recommending it to others. I have no
idea how comtemporary clojurescript developers interoperate with javascript
libraries and built-ins which are now overwhelmingly promise-based when async.
I am also incredibly skeptical of the core.async channel abstraction as an
alternative to promises/async iterators insofar as I think it is strictly
inferior to both promises and async iterators because:

1\. There’s no standard way to communicate error conditions.

2\. There’s no logical separation between data producers and data consumers,
and any code with access to a channel can take or put values.

3\. There’s no way to communicate nil values insofar as core.async chose to
use nil to represent end of iteration.

I do not understand the decision by the core clojure team not to support
promises or iterators, because one of clojure’s main selling points was
pragmatic interopability with host language features. Nevertheless, I infer it
must be an intentional decision not to support them, insofar as it’s so easy
to support new language features in clojure with macros. Maybe it comes from a
desire to adhere to “functional programming principles,” but I’ve found
async/await, promises, and iterators/generators to be incredibly useful, so
much so that I am unwilling to give it up for clojure’s immutability or nicer
syntax.

~~~
yogthos
My team has been working with ClojureScript for close to 5 years now, and we
haven't had any of these problems. Promises work just fine, you don't need any
additional support for them. For example, this works just fine:

    
    
        (defn parse-image-links [pages]
          (-> (map #(js/Promise. (parse-page %)) pages)
              (js/Promise.all)
              (.then #(->> % (map :Images) (apply concat) (map parse-image-url) set save-links))
              (.catch js/console.error)))
    

[https://gist.github.com/yogthos/d9d2324016f62d151c9843bdac3c...](https://gist.github.com/yogthos/d9d2324016f62d151c9843bdac3c0f23)

Here's another example working with async Ajax calls from re-frame
[https://github.com/ClojureTO/JS-Workshop/blob/re-
frame/src/r...](https://github.com/ClojureTO/JS-Workshop/blob/re-
frame/src/reddit_viewer/events.cljs)

Furthermore, we find that we rarely need things from Js ecosystem. Here's [1]
a talk I recently copresented on an app my team built. I has around 50kloc
ClojureScript, and we barely had to use anything in Js ecosystem for it.

[https://www.youtube.com/watch?v=IekPZpfbdaI](https://www.youtube.com/watch?v=IekPZpfbdaI)

~~~
Scarbutt

      (defn parse-image-links [pages]
            (-> (map #(js/Promise. (parse-page %)) pages)
                (js/Promise.all)
                (.then #(->> % (map :Images) (apply concat) (map parse-image-url) set save-links))
                (.catch js/console.error)))
    

And you have gone full circle, bact to writing Javascript but with
parentheses.

~~~
altanil
Yes. At its worst it's just Javascript (with parentheses), especially when
dealing with libraries and promises.

In other cases you can benefit from all the features of ClojureScript.

That's pretty magical in my experience.

------
vikeri
Great to see people putting effort into making Clojure(Script) more
accessible! As much as I like the language and the community, it historically
wasn't a very beginner friendly place in my opinion. Not that people weren't
friendly towards beginners but just a lack of resources targeted at beginners.

------
Zelphyr
I’ve been going through this book lately and it is very well written. It’s one
of the best introductions to Clojure and ClojureScript that I’ve found.

------
jwr
Having read most comments under this post, my conclusion is that the Blub
Paradox is very real. I am surprised that otherwise sophisticated HN readers
fall prey to it. I see a lot of comments which are outright dismissive, from
people clinging to what they know, and in most cases not knowing much about
what they are criticizing.

Over the years I've learned that if there is something very different about a
language or a solution, or if there is something I do not understand, it is a
strong indicator that it's something worth learning about. Sure, it might be
worse than what I'm using, or might not be applicable to my use case, but
usually there is something there worth investigating, and sometimes you
discover a better way to program.

------
lbj
As someone who has been doing Clojure/Cljs for a long time, I really
appreciate it whenever someone goes the extra mile in explaining the basics -
All the things clojurians take for granted in their every day work. Kudos to
the author!

------
js4ever
Closure seems to focus on purity instead of productivity. When I read this
article I imagine my team spending days to implement basic features they could
implement in few minutes with vanilla JS. Business don't care about code
purity. Only security, performance and correctness really matter.

~~~
iLemming
With respect, you honestly seem to have no idea what you're talking about. I,
just like many other front-end developers and just like you, was pretty
skeptical about Clojure and Clojurescript for quite a long time. But at some
point, it felt like I've done enough Javascript to make me feel tired of
dealing with its peculiarities. After working with Coffeescript, Typescript,
LiveScript, GorillaScript, IcedCoffeescript, Babeljs, Traceur, Fay, Haste,
GHCJS, after looking at Elm, Reason, and Scalajs I felt like I exhausted all
possible alternatives. Finally, I got to try Clojurescript.

Honestly, I wasn't very impressed right away.

I hated the fact that Clojure hosts on JVM. I had not done enough Java at that
point to know that JVM is a pretty solid piece of technology. People hate Java
and sometimes don't even bother checking out JVM because they hate Java.

I did not like the fact that Clojure is a Lisp dialect. I had only shallow
exposure to some emacs-lisp and wasn't even sure why people so excited about
Lisp.

I did not like the fact that Clojure is a dynamically typed language. Learning
some Haskell turned me into a big fan of typed programming, and naturally, I
was quite skeptical. It was before Clojure.Spec, so until Spec was announced,
I was still somewhat not sure if Clojure as a language is suited for large
codebases.

It turned out - all my skepticism was unwarranted. I had worked with more than
a few languages throughout my career - my first toy language was Basic, and my
first "real" PL Turbo Pascal. Yeah, I guess I'm getting a bit old. Anyhow,
Clojure turned out to be not just pure joy; it brought a lot of sense and
clarity to my work. I never felt as productive with any other language before.
Sometimes I try to rethink my positive thinking about Clojure and ask myself,
maybe that's what Stockholm syndrome looks like? And I try to compare it with
other languages and over and over again still feel like for me, right now,
Clojure and Clojurescript make sense more than any other option. Sure,
someday, it will stop making sense, and I will switch to something else, just
like I did with many languages before. But until that day I will be using
Clojure. Because for the type of work I'm doing today, it is probably the best
option - it is nicely balanced between pragmatism and theoretical, idealistic
language, hypothetical "silver bullet," which does not exist and never will.

~~~
dorian-graph
> .. after looking at Elm, Reason, and Scalajs I felt like I exhausted all
> possible alternatives.

As someone who has been using Elm at work for the last almost 2 years, but
wants to move on, I’m curious about this line. I’ve been thinking PureScript
or ClojureScript but admittedly I also have the strong concern of dynamically
typed languages.

~~~
iLemming
Although I'm curious, I wouldn't ask you to explain why. You probably have
your reasons. But I want to note that I love Elm. Elm is a fantastic language.
For what is it made for - to build single-page web app frontends, it is hard
to think of a better choice.

And I'm not going to tell you that Clojurescript is necessarily better.
However, if your choice is dictated by academic curiosity, by all means, do
try Purescript. But if you're seeking a tool that allows you to move fast but
at the same time to be not too sloppy, maybe give Clojure a try. Beware
though: you will encounter things you probably won't like:

\- You will hate JVM startup times until you figure out that you don't have to
restart REPL. I have some REPL sessions running for days and weeks.

\- You will hate error messages. To be fair though, after using Elm, you will
hate error messages in any language. Spec and libraries like Expound do
improve things, but error messages never get to the level of Elm-awesome.

\- If you have never used Lisp before, you will struggle with parentheses
until you find a structural editing tool/plugin that works best for you. But
after that, it is tough to live without them.

\- And yes, you will miss the static type checker, even after learning Spec.
Spec is fantastic, and you can do some pretty neat tricks with it, where for
something equivalent in Haskell, you'd have to go Liquid. I missed type
inference and static type checker in pretty much every dynamically typed
language I've used. Clojure minimizes that feeling, but unfortunately, it
never dissipates completely.

Historically, there are two camps of languages with roots in lambda-calculus:
ML/Haskell and Lisp.

Clojure from the Haskellers' point of view is "worse is better" of Haskell.
Haskell from Clojurists' perspective is "too ceremonial and bureaucratic."

But the truth is - you try to learn Haskell, maybe use for a bit, but the
chance that you ever get to the point where you can comfortably use Haskell in
production is not great. Admittedly, not too many of us developers ever get
there.

With Clojure, you can get there pretty quickly. It is way more pragmatic. And
every time I go back to Haskell/ML - there are things I miss that exist in
Clojure, and whenever I write Clojure, there are things I miss from Haskell.
My life is never will be the same

~~~
dorian-graph
First of all, I appreciate the reply!

> Although I'm curious, I wouldn't ask you to explain why. You probably have
> your reasons. But I want to note that I love Elm. Elm is a fantastic
> language. For what is it made for - to build single-page web app frontends,
> it is hard to think of a better choice.

I'm happy to answer! Elm has been a fantastic introduction to functional
programming. At work, we're very happy that we took the risk on it early on in
our startup. What I'm looking for more is a more advanced language, that has
things like type classes. A more open development plan would be great too.

> And I'm not going to tell you that Clojurescript is necessarily better.
> However, if your choice is dictated by academic curiosity, by all means, do
> try Purescript. But if you're seeking a tool that allows you to move fast
> but at the same time to be not too sloppy, maybe give Clojure a try. Beware
> though: you will encounter things you probably won't like:

Are the downsides of PureScript, similar to those for Haskell?

I can definitely imagine your other points being so true.

Do Clojure(Script) apps often have runtime errors because of the lack of
static type checking? With Elm, there is that nice guarantee that if it
compiles, then it simply won't have any runtime errors.

I'm looking to spend more time with a Lisp, before trying out Haskell.

> My life is never will be the same

I struggle to put into words why functional programming (and Elm) are are so
good, it's sort of you just need to try it for a few months. Is that your
experience with Clojure, or are you able to put it into words a bit more?

