This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2018-06-25
Channels
- # beginners (33)
- # cider (40)
- # clara (28)
- # cljs-dev (38)
- # cljsrn (5)
- # clojure (197)
- # clojure-greece (1)
- # clojure-italy (7)
- # clojure-losangeles (1)
- # clojure-nl (10)
- # clojure-spec (32)
- # clojure-uk (154)
- # clojurescript (48)
- # core-async (33)
- # cursive (32)
- # datomic (19)
- # duct (1)
- # fulcro (10)
- # graphql (6)
- # jobs (1)
- # lumo (1)
- # mount (6)
- # off-topic (48)
- # onyx (12)
- # other-languages (2)
- # re-frame (77)
- # reagent (19)
- # reitit (4)
- # ring (5)
- # ring-swagger (18)
- # rum (4)
- # shadow-cljs (52)
- # specter (12)
- # tools-deps (47)
Good morning
You look distinctly ‘grown up’ in that profile pic!
Bore da
morning
Morning!
@jonpither - I didn't realise that was still a thing... I looked at it a couple of years ago and heard nothing more about it and assumed it had died... I mean I am not using it, but I do know what it is...
...suffice it to say, I'd be interested in learning if you have some good results with it, as say an in-process cache... 😉
So, is anyone in here using Datomic at the moment..? I want to use it, mostly because the accretion-over-time approach is interesting and the Immutability / Point in Time stuff is useful to our domain as well, but I can't quite shake the feeling that people think it's neat, but aren't using it...
If I can't run it on my machine that's pretty much a dealbreaker imo
(also, morning)
We still use it. I'd question it for data at scale, as the sweet spot seems to be human generated data in a reasonable volume.
Interesting
What size of data are we talking?
Would it scale as an opdb for a webapp for example?
Not the way we’re using it, but if you do stuff with Kafka streams and I think KSQL it uses RocksDB to store the stream state or something
it uses rocksdb by default for the stream-table-equivalence stuff doesn't it @carr0t ?
Operational database
We use it for Web apps. If you've got large amounts of machine generated data then it might have trouble scaling.
How difficult have you found it to develop against?
@mccraigmccraig Thassit
I am hoping that you are talking about Datomic, as I am basically considering it for internal domain data as a way to have a datastore for business data, client info, some rarely-changed, domain data, that kind of thing. Large amounts of machine generated data would have other targets...
So i was thinking about helping a friend learn Clojure. I was wondering what you folks thought the top 10 most important functions were?
I’d say the most important things aren’t the functions but the core datastructures & the 7(+6) special forms and the R and E of REPL. If you understand that core, all else follows.
^ this guy knows what he’s on about
lol thanks Alex
no tbf you’ve trained, what now? 5-6 clojure devs? I’ve only successfully introduced one person (and weirdly they were a designer)
probably a dozen - but it doesn’t mean I’m doing it right… lol
the juxt folk will be orders of magnitude higher than me
Based on my “every day is a school day” From last week, apply should deffo be on the list. I wish I had grokked that sooner...
the only thing I’d add is you often need to shock people out of their ways a bit
like, it’s too easy for people to go “oh I can do that in x language” without thinking through the implications of all the new stuff fully e.g. lambdas, immutability - some of it can be found elsewhere and looks familiar
I’ve had python devs pretty interested in fp just tune out because they decided to just take a couple of new things back to python, I guess
and that’s cool but that’s not what I was trying to do
@guy: TBF it depends what you want to teach them, and what they need to know… but I’d argue clojure has a pretty small core; which is kinda fundamental to its design. The interesting things about clojure are that it’s a lisp, so it builds itself up from a small core, it has a functional bias with immutable data and it runs on the JVM.
I’d agree with @sundarj, eval
& apply
are kinda fundmental to lisp… seq
is pretty fundamental to the clojure sequence library and the abstractions it contains… first
/`rest` are probably less fundamental than in other lisps… or rather if we’re to include first
/`rest` then you should also include assoc
dissoc
conj
etc, as lists in clojure aren’t really any more special than hash-maps, vectors, sets etc… except that lists happen to also map onto function call syntax, but regardless Clojure is defined in terms of those core datastructures… other lisps are really just defined in terms of lists.
also thinking in terms of map
and reduce
is pretty fundamental
FWIW this blog post which recently resurfaced on HN is pretty good when it comes to understanding the abstractions in clojure collections: http://insideclojure.org/2016/03/16/collections/ Though I’d not recommend starting here; you can probably just summarise it all by saying how clojure forms are all the literals (including symbols) plus maps, sets, lists, vectors.
when I show people clojure I show them filter
map
and reduce
as those are three operation you might want to do with some data.
Yes map
and reduce
are good when you get to teaching functional programming in clojure; lazy sequences etc… They’re fundamental to writing idiomatic clojure, but not actually so fundamental to clojure itself… i.e. map
is defined on line 2719 of clojure.core; whilst reduce
is defined on line 6745! clojure.core
is 7824 LOCs, so the bulk of clojure.core
itself doesn’t use reduce
.
and the data structures as well together with conj
to show them what immutability means
Not that I’m literally implying you have to teach clojure in order of its definitions; but it does give a good indicator of what is really fundamental to clojure… i.e. the things that aren’t defined in clojure.core
are really the core language; that includes data structures and reader/evaluation/compilation.
personal preference, but I’d show ->
and ->>
- I know they’re sugar, but they significantly improve readability of code for me
this this this
couldn’t agree more
(and then, yes, basic data structure operations, map
, reduce
, first
, rest
, conj
, get-in
and such)
Yeah… I’d introduce ->
->>
only after sequences and FP, and after basic macros
see, I disagree since I think ->
and ->>
make it read more like imperative code, and thus make for an easier transition
I tend to agree. Thread macros were one of the first things I learned. I didn't even know what macros were, but I was using thread macros and assoc/dissoc because a lot of what we were doing was manipulating hashmaps
Not true
Look at comment
which is how I teach macros
yeah but if you introduce ->
->>
too early, and before you get to macros/special-forms you’ve confused the evaluation story… i.e. teach people those macros when after you’ve written things worse than:
(into #{} (map str (filter odd? (range 10))))
I find that horrendous to read 😉 If I hadn't known thread macros existed early on I would have been writing
(let [result (range 10)
result (filter odd? result)
result (map str result)]
(into #{} result))
Which is actually what our XQuery code is full of (although we do often name each intermediate var separate things even if they're just going to be thrown away, for clarity), because it doesn't do thread macros or similar
> I find that horrendous to read
But that is how all forms are actually evaluated, so you need to be able to read it. ->>
makes people think some functions are magic - because they don’t realise how they differ from macros.
I’m not saying don’t teach it… you definitely should… just leave it till after you’ve done the basics; which yes include understanding macros (even if you don’t actually show the writing of anything more complex than comment
or when
.)
I'm a bit late here, but if I was avoiding threading I would write it over a few lines like this:
(into #{}
(map str
(filter odd?
(range 10))))
i think the order in which aphyr teaches it is pretty good https://aphyr.com/tags/Clojure-from-the-ground-up
jinx 😆
Re collections (I'm not sure if anyone else has already mentioned this, but Eric shared an extensive article here https://purelyfunctional.tv/guide/clojure-collections/
ultimately I guess it comes down to whether you want to teach it top down or bottom up… I’ve had excellent results with bottom up, people who’ve gone top down have struggled in my opinion. It’s purely anecdotal evidence granted… Having said that bottom up is also the way the classic lisp literature is taught
Part of the problem is that I learned this stuff more than 2 weeks ago, so I can't actually guarantee I'm remembering how I learned it correctly 😉
Having said all this, I’d be very curious to see what a learning clojure top down curriculum would look like. I think such an approach would be easier if clojure had a Rails; but it doesn’t; so there’s no good “top” to pick… I think you can only really settle for the middle; or if you’re a company your existing stack which you can take as the top… but clojure’s error messages etc, require knowledge of the bottom to debug etc, and understand why certain design choices are logical… and the basic syntax mistakes beginners make require knowledge of evaluation to understand the errors or just trial and error to debug.
@guy @rickmoynihan I think the data structures are fundamental, which is why I think map
(and friends) and reduce
are fundamental functions (and teach higher order FP). Then assoc
I think as maps and seqs are the fundamental things in clojure
I think learning how to use map and reduce introduces people to first, assoc, rest et al.
what about specter based data transformation? Did anyone try showing that to newbies?
I still object to (seq coll)
being the Clojure idiomatic way instead of (not (empty? coll))
though 😉 A non-Clojure coder can immediately see what the latter does. The former requires knowledge of what seq
does
Once you look into empty it really feels like a waste to use it vs just seq.
(defn empty?
"Returns true if coll has no items - same as (not (seq coll)).
Please use the idiom (seq x) rather than (not (empty? x))"
{:added "1.0"
:static true}
[coll] (not (seq coll)))
Like i used to argue the same thing, then my friend showed me the functions under it and i was convinced begrudginglynot sure optimising for people unfamiliar with the language is the best approach 😉
seq
means 'try to get a sequence out of this thing'; you naturally can't get a sequence of things from an empty collection, so it makes intuitive sense in my book
@otfrom Completely agree. But I think when you teach those, you’re teaching FP on clojure, or rather you’re starting to teach people how to program clojure for real… rather than introduce them to the fundamental semantics. And this is all good; I’m just arguing don’t neglect teaching people the basic stuff at the bottom - it pays dividends later on. And also I think the fundamentals are what make clojure interesting and exciting to people. map
/`reduce` - well javascript has them too 🙂
I didn't feel like I could use Clojure until I grokked reduce - once I had really got my head around it the rest came pretty quickly.
@carr0t - It's a doozy... @seancorfield opened mine eyes to it and I have to say I was greatly impressed by it.
me too
@rickmoynihan I'm gonna think about that. I think it depends on whether you are teaching someone an experienced coder new to clojure or a new coder.
I’ve only really taught people with at least one other language under their belt; so can’t comment on teaching clojure as a first language.
though I’d probably still teach fundamentals 🙂
agree. Teaching to Java programmers is different. Teaching programming using clojure is different.
Were any of those people, people who already did/knew FP? Or was Clojure basically "Intro to FP", even for the experienced coders?
But SICP does a great job at it.. I am learning-teaching to my colleagues
so my audience are java programmers. It makes easy job..Show how to do typical operations
that's all I am doing
@carr0t probably 50/50 split between having some FP experience and no FP experience
but java / non-FP programmers are still used to writing things like String s = dosomethingElse(doSomething("foo"))
yeah, going from fluent interfaces to FP is a lot easier (it still mutates, but at least returns the mutated self each time, if that is what your example is showing)
just intended to show 1st order composition is not unfamiliar
Indeed. I can read it, I just think it's kinda horrible. I prefer patterns where you can do s.doSomething("foo").doSomethingElse()
, for example. So each function returns self
, effectively, and other functions can then chain off that
Most of the time if I have to nest functions like in your example I use intermedia vars to make it clear what is happening
Sure, I’m only saying imperative programmers are used to putting arguments into procedures and getting results out the LHS; and that it’s not uncommon to wrap a call over them without having an intermediate binding. Most developers I’ve met can read and write that kinda thing. return self and chaining is in my experience a less fundamental pattern… i.e. it comes from OOP not procedural programming… Perhaps I’m getting old, but programmers are still taught if
and for
and procedures before OOP and class hierarchies… aren’t they?!? 🙂
I am working on creating screen casts of clojure. I started reading core.clj
the order of things in that looks good to me
I started with seq operations
I am planning to show specter based data transformations and regular reduce/reduce-kv operations..
For our internal teams I shared an internal ClojurePrimer git repo that I created from the lessons I learned on http://www.agilelearner.com
Coming back to @rickmoynihan's comment (https://clojurians.slack.com/archives/C064BA6G2/p1529933515000091)... although possibly completely unrelated... I found understanding destructuring to be a massive help https://clojure.org/guides/destructuring
TBH, working through most of the official guides is probably a great starting point
destructuring is awesome, but you can get a long way without it
you rarely need it
oh mine too! I wouldn’t want to give it up.
my 2 pennies worth is that I found it very confusing to have multiple ways to do something when I was first starting, eg. why use ;
to comment things out when there’s (comment ...)
which a) does the job and b) is syntacticly consistent with the rest of the language?
I've never used (comment ,,,)
as a comment as it returns nil, so can do strange things if the comment gets nested.
I prefer the the brutalness of ;;
for classic commenting. Or the elegance of #_
reader macro comment, for commenting expressions, even when nested inside other comments.
yeah destructuring is important to know & to use real world clojure & beginners seem to struggle with it initially; but it’s really built on top of let*
which is one of the special forms I mentioned… so again I’d probably introduce it with macros… let
is a very good example of what macros can do.
thanks @yogidevbear!
You deserve the thanks 🙂 After all, you were the author 👍