Fork me on GitHub
#clojurescript
<
2017-01-07
>
udhan02:01:06

I am trying to convince people to use clojurescript/reagent for new project instead of react/angular2 . I demoed an application everyone seem liked it. I also paired with couple of engineers who were on fence and now back clojurescript. There are no technical opposition as such however popularity and issues with hiring talent is big argument against it. Anyone wants to share some experience or suggestions? Do we have a better story on that front to tell?

olslash02:01:12

ive thought of trying to introduce it, but the hiring argument is a tough one -- if youre lucky you can find a small greenfield project to test it on and maybe thatll convince people

olslash02:01:28

fwiw JS react/redux is a good compromise and at least you wont be using angular

potetm03:01:17

@udhan I've never had trouble finding devs. The opposite actually.

potetm03:01:26

People really want to work with better technology.

potetm03:01:46

Especially if you're willing to take time to train people in clojurescript. (Which, honestly, is an order of magnitude easier than training people on a codebase.)

emccue03:01:03

I consider myself hireable

olslash03:01:20

glad to hear youve had good experience hiring for it

emccue03:01:26

(backs up slowly)

olslash03:01:38

i hate being a front lead and still feeling like i cant do anything but js

potetm03:01:20

Yeah getting a company w/ and existing codebase to change things is hard.

potetm03:01:28

And, probably, unwise.

olslash03:01:36

i just joined a new company and they're doing mostly angular 1.x

potetm03:01:38

If I'm being brutally honest.

olslash03:01:58

i know its not good but change is political

potetm03:01:22

Good, bad... it's just how people work 🙂

udhan03:01:48

@potetm: Yes! On a lighter note my manager equated pitching for new technology to startup pitching to investers!

udhan03:01:12

Good thing is project fresh and there is no baggage as well as existing components to reuse. So thought it's worth a shot.

potetm03:01:28

Yeah. In my mind, not using clojure(script), or at least something of a similar caliber, for a new project is an out and out mistake.

potetm03:01:39

Maybe not a make-or-break mistake, but a mistake nonetheless.

potetm03:01:08

In this case, you're basically signing up to spend a ton of time over the life of the entire project thinking about the intricacies of JavaScript, when you could just a well-designed tool for a low one-time fee.

emccue03:01:25

Okay so, from a rhetoric perspective, and something I think will affect your efficacy in convincing people, I'm concerned about the fact that you brought up your manager's thoughts.

emccue03:01:28

What is your position at your company? And the better question is how many people do you need to bring on board to tilt the ship

udhan03:01:12

@emccue: I am principal. However I don't think it's question of bringing more people onboard but to address valid concerns and making a strong objective case. About managers thought, it was just light comment which I found interesting way of looking at problem.

emccue03:01:19

Yeah I'm sorry, that was my bad. I misread connotation and I apologize.

emccue03:01:33

Ignore what I just said

udhan03:01:58

@emccue: no problem !

emccue04:01:35

My two cents on the hiring issue is this: It breaks down into two issues; finding new developers and training new developers. The JavaScript developer pool is large, so if you were to hire a good frontend developer from the mix; can you train them quickly enough to have traction and not negate the cost benefits of using ClojureScript for your architecture. The answer the people here will give you will probably be yes. Your answer might be different depending on no small number of factors.

udhan04:01:37

@emccue: fair point.

verma04:01:40

fwiw, I do some consulting work for people with somewhat complete independence and choose my own stack etc. which for the past few projects has been Clojure(script). I think it was great to show great progress and show how well the whole thing worked for developers as well (figwheel, repl driven development etc.). But eventually when its time to off load work to other people, I’ve faced considerable resistance. Eventually in my experience, it boiled down to people not really caring about improving their development experience or trying out new things, most just want to get done and go home. This resistance also led to the higher ups questioning my choices 🙂.

udhan04:01:21

I am finding that there are less resources like blog posts etc which compare clojurescript ecosystem with js. Clojurescript for skeptics is great ! We need more :)

verma04:01:25

In my most recent project, 90% of it is Javascript and source of my problems and bugs, but 10% Clojure(Script) is always blamed as being a black box.

verma04:01:14

not sure I am contributing to the discussion here though 🙂

udhan04:01:09

@verma it's adding more perspective 👍

verma04:01:16

:thumbsup:

tbaldridge04:01:04

@udhan one of the biggest problems I see is making sure devs are competent with Clojure(Script). On one project with Clojure beginners, I was told time and again "we'd be done by now if we had used JavaScript". That wasn't true (it was really management issues).

tbaldridge04:01:52

Contrast that with another project, were we were told "We're giving your team (of 4 devs) yet another project because you've shown you can get Clojure code out in a few weeks compared to 6 months we keep hearing from the Java team of 12+ devs".

udhan04:01:24

@potetm: how hard/easy you think it is to objectively quantify failures due to js intricacies? Making case with backing stats generally works much better

udhan04:01:23

@tbaldridge: are you in a way saying take some competent devs and take leap of faith and deliver! 😀

tbaldridge04:01:50

pretty much, don't try to take a team that knows JS and convert them in the middle of the project.

potetm04:01:26

@tbaldridge That sounds like a competency issue. Do you think those same 4 clj devs could do the same project in Java in 4-6 weeks.

potetm04:01:18

@udhan Honestly, if someone were to come up with numbers, I probably wouldn't trust them 🙂

tbaldridge04:01:05

That does play into it, good engineers can work in almost any language, don't think so in this case. It really was a situation were Clojure was so concise that we were able to be much more agile. Changing requirements meant changing 20 lines of code instead of 200.

potetm04:01:24

That assessment is based more on logic and reason than on any sort of empirical evidence.

potetm04:01:12

That's the kind of pitch I would love to be able to give with a straight face... 😕 I tend to believe that concision, while impactive, is orders of magnitude less impactful than well-designed code.

potetm04:01:13

And I've found that it's pretty easy to create poorly designed code in Clojure. Slightly harder than in other languages perhaps, but all too easy just the same.

tcarls04:01:34

There's certainly much to be said for being able to use good tools enhancing the developer pool

tcarls04:01:02

There's someone I'm (hopefully) in the process of hiring who wouldn't be considering the position if we weren't a Clojure shop, but who brings a great deal of general-purpose experience and skill to the table

tcarls04:01:31

OTOH, for JavaScript specifically, there's a big pool of UI/UX folks who are good at what they do, but specifically focused on JavaScript

potetm04:01:50

Yeah, that's one massive upside of choosing Clojure that's hard to quantify: Self selection of the more driven developers.

udhan04:01:16

@potetm: Agreed. Even while pitching for cljs, I didn't advocated it diretly. In fact I pitched for an architecture. Then it was easy to say cljs fits out need in best possible way. However other concerns are hard to address.

potetm04:01:16

If the people you're talking with are familiar with programming, Simple Made Easy is the best pitch I know of for Clojure(Script).

tcarls04:01:19

(re: "good developers can work in almost any language" -- the retraining bump in switching paradigms can be a nasty one for folks who haven't yet worked in a functional language... though once you've got experience with any language inside a class/paradigm, yup, I agree)

potetm04:01:11

If not: I might say something along the lines of "Programming is hard. This removes some of the common problems. In my professional assessment, it's top tier tooling, and it's free."

potetm04:01:55

But I'm no salesman. @tbaldridge has loads more experience than I with that. You should probably say what he said 🙂

tbaldridge04:01:15

Lol, I'm not sure about that

tbaldridge04:01:38

Concise code and immutabilty are the two major wins

tbaldridge04:01:16

I'd also mention "data-first" code. No other language I know (perhaps R I've been told) puts data first. And rich data at that. Sets, maps, vectors, etc. They are all first class citizens in the language

tbaldridge04:01:39

This means that simple things like CRUD apps remain simple. Data ingestion just becomes a transformation pipeline of hashmaps from a to b

potetm04:01:51

Yeah, the unfortunate part for FP (and for all good programming), is that it's not hip or easy to reason through why certain things are good and certain things are poor.

potetm04:01:11

That's actually an argument I use alot: Think about what it is your programs do!

potetm04:01:27

They read some data from the user, transform it, write some data to the database.

qqq04:01:32

I'm still undecided on data-first vs types; I feel like a subset of schema that is compile time checkable would be ideal.

potetm04:01:42

They read some data from the database, transform it, and write some data to an API.

potetm04:01:47

etc, etc, etc

qqq04:01:58

s/schema/spec/

potetm04:01:04

And FP gives you tools that are hyper-optimized for that.

tbaldridge04:01:11

sure that'd be nice @qqq, but that doesn't exist. And as Clojure is the only language with first class open data, I'm not about to change 😉

potetm04:01:13

For that thing every program you write does.

qqq04:01:12

@tbaldridge: I think https://github.com/arohner/spectrum is a step in the right way -- I'm not using it yet -- but I think it has interesting ideas

potetm04:01:51

Is there some reason first class data and types are mutually exclusive?

qqq04:01:13

there's also function level programming, like J/Haskell: https://en.wikipedia.org/wiki/Function-level_programming which I feel are a bit difficult to do given all the ()'s and apply/partial being not as elegant as J/Haskell's partial pplication

qqq04:01:41

@tbaldridge: lol, reading that now

tbaldridge04:01:35

Spec is built on arbitrary predicates however, so it's more flexible from the start, may have to give some of that up to statically type it

udhan04:01:20

Thank you @tbaldridge @potetm @tcarls @verma @emccue . I got lots of points to talk about on Monday 😀

ambrosebs04:01:24

I'm planning to add spec syntax to core.typed, and allow overrides for non-typeable specs.

qqq04:01:44

@tbaldridge: I fully agree with thepoint on converting UIPerson to DBPerson and back -- dealing with Clojure has been very nice in that regard compared to Haskell

qqq04:01:27

I do wish I had the option to (1) give up full predicates in spec, (2) have a "regex for recursive data structures" language that is compile time checked, and somehow works with things like assoc, map, filter, dissoc

tbaldridge04:01:12

yeah, and I think core.typed would to most of what I want.

ambrosebs04:01:14

@qqq that shouldn't be too far off

potetm04:01:21

Thank you @udhan. Enjoyed the convo!

qqq04:01:10

@ambrosebs: I (2 years ago?) tried core.typed; I never figured out what I was doing wrong, but it was really slow to type check, and I gave up

ambrosebs04:01:41

@qqq I'm getting serious about the user experience finally

ambrosebs04:01:54

still slow, but I'm working on it

qqq04:01:52

I wish someone (core.typed? spectrum?) would separate the "nitty gritty of parsing the code" from "running the type checker" -- so we can have 1000 different type checkers trying different ideas and seeing what works

qqq04:01:09

at the moment, it seems like the barrier of even parsing via tools.analyzer.jvm is blocking many ppl from being able to write type checkers

tbaldridge04:01:39

nah, it's just super hard to write a type checker

potetm04:01:40

@ambrosebs I have a left-field question for you: Do you happen to have a write-up about why you think static typing is important, particularly for the clojure community?

potetm04:01:55

I'm assuming this exists and I just haven't stumbled across it.

qqq05:01:20

@tbaldridge: I was under the impression that unless you were writing a dependent-type checker or haskell extensions, it's just a matter of setting up constraints and running a logic solver, like prolog/minikanren/core.logikc

potetm05:01:43

I'd be super interested in what you have to say about it. I'm sure you've thought about it quite a bit, especially give then dispensation of the clojure community.

ambrosebs05:01:28

@potetm I have a lot to say about it, I'll think about a good angle in light of spec and write a blog

ambrosebs05:01:33

thanks for asking 🙂

qqq05:01:31

does cljs have it's own pprint, where i nstead of printing to the console, I point it at a div, and it allows me to interactively explore the clojure data structure?

tcarls05:01:52

@qqq, ...I've seen such a widget someone's built, though I'd need to poke around to see where.

qqq05:01:43

@tcarls: it would be much appreciated 🙂

tcarls05:01:58

Huh. Thought it was part of devcards, but doesn't seem to be...

qqq05:01:43

woul dnot surprise me, devcards/figwheel is one productive dude

qqq05:01:56

probably single handedgly doubled cljs productivity worldwide

tcarls05:01:58

...is that about what you're looking for?

qqq05:01:12

tcarb: well, frisk certainly has that feature as part of it

dottedmag13:01:26

Which cljs app template for Electron is the most current/fully-featured? I have found descjop, electron-template, cljs-electron and electron-and-clojurescript.

pesterhazy14:01:44

@anmonteiro good catch on the (js/console.log (str (js/Symbol "asdf"))) issue

pesterhazy14:01:31

I'm not sure I understand the issue in http://dev.clojure.org/jira/browse/CLJS-1628 100%

pesterhazy14:01:17

So (.-$$typeof (r/as-element [:div])) returns a js/Symbol (because React expects that?)

pesterhazy14:01:54

And cljs can't currently print js/Symbol's (though it can print cljs.core/Symbol's)

anmonteiro14:01:35

@pesterhazy js/Symbol is a JavaScript thing, not related to Clojure(Script)'s symbols at all

anmonteiro14:01:54

and $$typeof is something that's on every React element

anmonteiro14:01:04

the problem is really just the printing part

pesterhazy14:01:07

is there a way to monkey-patch printing to support symbols?

anmonteiro14:01:47

there probably is, but I can't recall right now

anmonteiro14:01:06

some multimethod you could implement or something

anmonteiro14:01:14

isn't there a patch in CLJS-1628?

anmonteiro14:01:52

@pesterhazy dumb attempt:

~  lumo
Lumo 1.0.0
ClojureScript 1.9.293
 Docs: (doc function-name-here)
 Exit: Control+D or :cljs/quit or exit

cljs.user=> (extend-protocol IPrintWithWriter
       #_=>  js/Symbol
       #_=>  (-pr-writer [this writer opts]
       #_=>   (pr-sequential-writer writer pr-writer "(" " " ")" opts "foo")))
#object[Function "function (this$,writer,opts){
var this$__$1 = this;
return cljs.core.pr_sequential_writer.call(null,writer,cljs.core.pr_writer,"("," ",")",opts,"foo");
}"]
cljs.user=> (js/Symbol)
("f" "o" "o")
cljs.user=>

pesterhazy14:01:29

cljs.user=> (extend-protocol IPrintWithWriter js/Symbol (-pr-writer [this writer opts] (-write writer (.toString this))))
#object[Function "function (this$,writer,opts){
var this$__$1 = this;
return cljs.core._write.call(null,writer,this$__$1.toString());
}"]
cljs.user=> (js/Symbol "asdf")
Symbol(asdf)

pesterhazy14:01:52

cljs.user=> (extend-protocol IPrintWithWriter js/Symbol (-pr-writer [obj writer opts] (write-all writer "#object[Symbol \"" (.toString obj) "\"]")))
#object[Function "function (obj,writer,opts){
var obj__$1 = this;
return cljs.core.write_all.call(null,writer,"#object[Symbol \"",obj__$1.toString(),"\"]");
}"]
cljs.user=> (js/Symbol "asdf")
#object[Symbol "Symbol(asdf)"]

pesterhazy14:01:36

by the way, I wish the default behavior was to not print the entire function body

pesterhazy14:01:14

now reagent.core/as-element works:

cljs.user=> (r/as-element [:div])
#js {:$$typeof #object[Symbol "Symbol(react.element)"], :type "div", :key nil, :ref nil, :props #js {}, :_owner nil, :_store #js {}}

anmonteiro14:01:37

@pesterhazy can I close the Lumo issue then?

pesterhazy14:01:33

closed it, thanks

pesterhazy14:01:45

shouldn't that be js/reagent.debug.has-console?

pesterhazy14:01:44

or I guess reagent.debug/has-console?

pesterhazy14:01:15

the latter works fine

martinklepsch16:01:08

@dottedmag electron-and-clojurescript should at least be up to date but doesn’t ship with any extras

tcarls16:01:48

@dottedmag, ...if you come to a conclusion, let me know -- I might be converting a project being prototyped as a webapp to run on Electron at some point.

pandeiro19:01:15

i was playing with lumo the other day and wanted to load core.async but couldn't due to one of the macro namespaces referencing a java import

pandeiro19:01:57

i wondered a) if there's a workaround for that, probably not, and b) why that core async ns actually includes the import (it's not referenced anywhere)

anmonteiro19:01:13

@pandeiro Mike Fikes has ported core.async to be bootstrapped compatible: https://github.com/mfikes/andare

pandeiro19:01:52

wow, a full fork? so i assume that the import there really is necessary?

mfikes19:01:27

The full fork covered much more than just removing the import 🙂

pandeiro19:01:29

cool, i will work with that then for lumo; but i am curious what other dragons there were lurking in there...

pandeiro19:01:36

i presume that the issues were mostly an artifact of core.async being written in java first and the cljs port being done in the most expedient matter possible...

pandeiro19:01:56

(not some actual reason core.async couldn't be written for JS hosted clojure)

mfikes19:01:45

In self-hosted ClojureScript, macros need to be compiled as if written in ClojureScript. The original macros in core.async took advantage of things you can do only on Clojure, like defining a macro and using it in the same compilation stage. Rearranging things to abide with the staged compilation model, and addressing some host interop calls were sufficient to get it to work properly, IIRC.

pandeiro19:01:33

ah, yeah that makes sense, thanks for the insight

pandeiro19:01:42

is there any interest in backporting it so that core.async itself can work with those two different compilation models? or this too specialized a use case?

pandeiro19:01:18

i'm hoping to do a lot of my personal scripting with lumo instead of bash, hence my interest

mfikes19:01:45

Ambrose is working on an experimental update to core.async which would make use of a unified compiler analysis metadata model, and would also hopefully target boostrapped ClojureScript as well, using the ideas we learned with Andare. If that pans out, we could end up with the official core.async supporting bootstrapped ClojureScript and Andare could be retired.

pandeiro19:01:26

you guys are amazing 🙂 thanks again

scknkkrer19:01:12

Guys, I need a technical defination. What is re-natal library, what does do generally ?

kim022:01:59

@scknkkrer .. I was looking for an answer to that the other day .. The best I could figure out, is that re-natal is mostly a template and some build configuration to allow working with re-agent and/or react-native

ejelome22:01:58

yeah, re-natal is more of a boilerplate than a library

ejelome22:01:34

... but I'm still angry why they jammed pack it with re-frame when they literally say reagent6, doesn't make sense tbh