Fork me on GitHub
#clojure-uk
<
2018-06-25
>
thomas07:06:15

mogge 😼

agile_geek07:06:44

You look distinctly ‘grown up’ in that profile pic!

otfrom08:06:32

just old, not grown up

danielneal08:06:43

HELLO EVERYONE 📣

🙉 4
morning 4
otfrom08:06:17

<whispers>good morning @danieleneal</whispers>

🙂 4
hyankov09:06:56

Morning everyone 🙂

jonpither09:06:13

Anyone using RocksDB?

guy09:06:46

Morning!

maleghast10:06:45

Morning All 🙂

maleghast10:06:28

@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...

maleghast10:06:55

...suffice it to say, I'd be interested in learning if you have some good results with it, as say an in-process cache... 😉

maleghast10:06:24

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...

alexlynham10:06:13

If I can't run it on my machine that's pretty much a dealbreaker imo

alexlynham10:06:20

(also, morning)

jonpither11:06:35

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.

alexlynham11:06:55

Interesting

alexlynham11:06:03

What size of data are we talking?

alexlynham11:06:30

Would it scale as an opdb for a webapp for example?

danm11:06:24

I can tell you that Kafka uses RocksDB, to go back to an earlier question ;)

danm11:06:09

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

mccraigmccraig11:06:16

it uses rocksdb by default for the stream-table-equivalence stuff doesn't it @carr0t ?

alexlynham11:06:55

Operational database

jonpither11:06:09

We use it for Web apps. If you've got large amounts of machine generated data then it might have trouble scaling.

alexlynham11:06:45

How difficult have you found it to develop against?

dominicm11:06:40

Really easy. You can load it inside your JVM as part of your system.

maleghast11:06:13

@dominicm - Is that RocksDB or Datomic..?

maleghast11:06:20

(I've lost the thread of the thread)

maleghast12:06:43

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...

maleghast12:06:58

I'll check back later - meeting now...

dominicm12:06:28

Yeah. That sounds like a good split to me.

guy13:06:07

So i was thinking about helping a friend learn Clojure. I was wondering what you folks thought the top 10 most important functions were?

rickmoynihan13:06:55

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.

alexlynham13:06:15

^ this guy knows what he’s on about

rickmoynihan13:06:32

lol thanks Alex

alexlynham13:06:45

no tbf you’ve trained, what now? 5-6 clojure devs? I’ve only successfully introduced one person (and weirdly they were a designer)

rickmoynihan13:06:16

probably a dozen - but it doesn’t mean I’m doing it right… lol

rickmoynihan13:06:39

the juxt folk will be orders of magnitude higher than me

guy13:06:45

👌 awesome

guy13:06:50

thanks for the tips!!

sundarj13:06:54

i'd put apply, first, rest, and seq on that list

👍 4
maleghast13:06:17

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...

alexlynham13:06:02

the only thing I’d add is you often need to shock people out of their ways a bit

alexlynham13:06:21

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

alexlynham13:06:04

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

alexlynham13:06:11

and that’s cool but that’s not what I was trying to do

sundarj13:06:57

people will take the path of least resistance if they can

rickmoynihan13:06:14

@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.

8
alexlynham13:06:42

also thinking in terms of map and reduce is pretty fundamental

alexlynham13:06:57

there’s a reason rich bangs on about reducers and transducers etc

💯 8
rickmoynihan13:06:49

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.

guy13:06:28

Thanks all!!

thomas13:06:08

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.

rickmoynihan13:06:14

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.

thomas13:06:05

and the data structures as well together with conj to show them what immutability means

rickmoynihan14:06:33

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.

3Jane14:06:29

personal preference, but I’d show -> and ->> - I know they’re sugar, but they significantly improve readability of code for me

16
💯 4
alexlynham14:06:02

this this this

alexlynham14:06:09

couldn’t agree more

danm14:06:52

Yes, thread macros made Clojure so much more readable to me

danm14:06:18

But we are straying into "Just show them everything!" territory

3Jane14:06:43

(and then, yes, basic data structure operations, map, reduce, first, rest, conj, get-in and such)

rickmoynihan14:06:50

Yeah… I’d introduce -> ->> only after sequences and FP, and after basic macros

3Jane14:06:19

see, I disagree since I think -> and ->> make it read more like imperative code, and thus make for an easier transition

3Jane14:06:53

(for anything beyond something like three-level nesting)

3Jane14:06:02

but as I said, personal preference 🙂

danm14:06:50

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

danm14:06:13

I don't think a 'basic macro' exists 😉

rickmoynihan14:06:33

Look at comment

rickmoynihan14:06:49

which is how I teach macros

rickmoynihan14:06:21

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

danm14:06:49

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

danm14:06:32

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

rickmoynihan14:06:42

> 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.

rickmoynihan14:06:44

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

danm14:06:13

Fair enough

simonkatz21:06:03

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

sundarj14:06:23

i think the order in which aphyr teaches it is pretty good https://aphyr.com/tags/Clojure-from-the-ground-up

guy14:06:54

thanks u folks too ❤️

yogidevbear14:06:57

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/

guy14:06:34

Alright got some good stuff 🙂

rickmoynihan14:06:56

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

👌 8
danm14:06:25

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 😉

👍 4
rickmoynihan14:06:53

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.

otfrom14:06:18

@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

otfrom14:06:40

I think learning how to use map and reduce introduces people to first, assoc, rest et al.

👍 12
manas_marthi14:06:42

what about specter based data transformation? Did anyone try showing that to newbies?

danm14:06:18

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

guy14:06:57

tbh i used to be in the same camp, but writing just seq is faster so now i dont care

guy14:06:27

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 begrudgingly

sundarj14:06:21

not 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

sundarj14:06:26

the only other requisite knowledge is that nil is falsey

rickmoynihan14:06:36

@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 🙂

danm14:06:38

I have yet to do any specter based transformation myself

maleghast14:06:41

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.

danm14:06:59

reduce-kv is also ❤️, as we're doing so much with maps

maleghast14:06:36

@carr0t - It's a doozy... @seancorfield opened mine eyes to it and I have to say I was greatly impressed by it.

otfrom14:06:15

@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.

rickmoynihan14:06:25

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.

rickmoynihan14:06:39

though I’d probably still teach fundamentals 🙂

manas_marthi14:06:51

agree. Teaching to Java programmers is different. Teaching programming using clojure is different.

danm14:06:14

Were any of those people, people who already did/knew FP? Or was Clojure basically "Intro to FP", even for the experienced coders?

manas_marthi14:06:23

But SICP does a great job at it.. I am learning-teaching to my colleagues

manas_marthi14:06:55

so my audience are java programmers. It makes easy job..Show how to do typical operations

manas_marthi14:06:59

that's all I am doing

rickmoynihan14:06:11

@carr0t probably 50/50 split between having some FP experience and no FP experience

rickmoynihan14:06:32

but java / non-FP programmers are still used to writing things like String s = dosomethingElse(doSomething("foo"))

otfrom14:06:30

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)

rickmoynihan14:06:04

just intended to show 1st order composition is not unfamiliar

danm14:06:33

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

danm14:06:27

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

rickmoynihan14:06:48

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?!? 🙂

manas_marthi14:06:19

I am working on creating screen casts of clojure. I started reading core.clj

manas_marthi14:06:28

the order of things in that looks good to me

manas_marthi14:06:31

I started with seq operations

manas_marthi14:06:10

I am planning to show specter based data transformations and regular reduce/reduce-kv operations..

manas_marthi14:06:48

For our internal teams I shared an internal ClojurePrimer git repo that I created from the lessons I learned on http://www.agilelearner.com

yogidevbear14:06:36

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

yogidevbear15:06:52

TBH, working through most of the official guides is probably a great starting point

Rachel Westmacott15:06:26

destructuring is awesome, but you can get a long way without it

Rachel Westmacott15:06:35

you rarely need it

mccraigmccraig15:06:56

you definitely need it if you are going to read my code!

😂 8
Rachel Westmacott15:06:16

oh mine too! I wouldn’t want to give it up.

Rachel Westmacott15:06:19

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?

3Jane16:06:55

you’d hate perl 😄

👍 4
practicalli-johnny23:07:32

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.

rickmoynihan15:06:24

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.

yogidevbear15:06:48

You deserve the thanks 🙂 After all, you were the author 👍