morning
moinmoin
moarnin
hi guys, when is the next meetup?
bahulneel: schedule is here: http://www.londonclojurians.org/
Thx, I looked at that but couldn't then find the corresponding event on skills matter for tomorrow, so was unsure.
bahulneel: I've deleted that event. We didn't really get things together in time (life intervened for a number of the organisers incl me)
i'm looking to replace pallet as my infrastructure automation tool... any recommendations anyone ? i need to manager clusters of cloud servers with various roles and services, and i much prefer git-based config to a config server
mccraigmccraig: wow, if even you are leaving pallet...
mccraigmccraig: not sure what you think of the thing that elise_huard and thattommyhall are working on here: https://github.com/MastodonC/terraboot
@otfrom: final-straw - pallet is way behind on the AWS client libs https://github.com/pallet/awaze
how have you found terraform @otfrom ?
elise_huard and thattommyhall love it
it is a pity they didn't go w/amazonica then https://github.com/mcohen01/amazonica
oh, they did, but they forked it, and the fork is some way behind and there were sufficient AWS api changes that it's not an easy upgrade
π
so, a pity they didn't stay with amazonica
hmm - if i like terraform, terraboot looks like something i could use/fork @otfrom - afaics it's setting up a mesos cluster, which is most of what i want... starting from scratch might even encourage me to move my c* onto mesos at last
Hey @mccraigmccraig, terraform is good but I found it lacks abstraction. Adding a DSL to generate their JSON format has worked well for me in Ruby and now here in Clj too
I didnt realise the project was public already, will probs share the more reusable stuff somewhere else
by "lacks abstraction" dyu mean stuff like the ability to define concepts like groups and roles for resources and associated behaviours @thattommyhall ?
want to do the same thing in N regions/AZs, do some conditional logic
cool - DSL sounds like a good approach too - if the underlying behaviours are simple, then you get to introspect why your cluster is messed up from the generated JSON :simple_smile:
thattommyhall: I think the repo started off as public. I do realise it is too early for other people than us to even think about using it yet though
so, caveat forker mccraigmccraig π
https://www.terraform.io/docs/configuration/syntax.html is where it mentions the JSON format
thattommyhall: mccraigmccraig is also using c*, kafka, mesos, es, spark, hadoop et al
and he has a better beard than I do
π
π»
https://www.terraform.io/docs/configuration/interpolation.html is were they list a few built-in functions etc (but no way to define your own afaikt)
and the index stuff is just annoying
@otfrom: semper caveat forker
I hope they resist nonsense like http://docs.ansible.com/ansible/playbooks_loops.html
thattommyhall: I was wondering when you were going to post that. π
do you have a yasnippet or macro for that set up? π
haha
mean time before slagging off Ansible
argh... it's the old programming in XML zombie arising again
thats why I like the 'feed it JSON' approach
mccraigmccraig: but xml is just lisp with angled brackets. You should love it. π
any declaritive thing either has an escape hatch like JSON in terraform or becomes like Ansible and tries to turn a serialisation format into a proglang
yep, i'm convinced by that argument. i'll take a good look at terraform
mccraigmccraig: always happy to have more community around an approach.
@otfrom: not sure that follows - i don't love common-lisp or elisp
i'm picky about my lisps
mccraigmccraig: what do you look for in a lisp?
clojure (and clojure derived) are my faves atm as I really like the seq abstraction
@otfrom: basically this forward a few years - https://github.com/LuxLang/lux
i'm happy in clojure atm, but i keep hankering after some static-type goodness
I'm mostly interested in good (haskell or similar) levels of static typing to see what I'm missing. Anything less that haskell seems to be not worth the effort (C++ or Java types)
agree
i'm currently liking the monad stuff and working with them in clojure is not as straightforward as in a lang with a decent static-type system, though still very useful
mccraigmccraig: so I have to admit, that I think I only kind of sort of understand the State monad (which I think earlier versions of pallet used). What applications are you using monads for and how does having static typing make those things easier?
@otfrom: i make everything async and sensible with monads :simple_smile:
i recently switched the UI of my app from being based around core.async for api calls to promesa - thanks to everything using the generic monadic apis it took only a couple of hours...
and now i've got the awesomeness of alet
aka applicative-do too - http://funcool.github.io/cats/latest/#alet
the difficulty is non-obvious (at first) exceptions if you return the wrong type from your monadic functions... something that will never happen with static validation
as an example, here's a function which does a c* upsert with the async api... every step is actually an async call with a callback-function, and there is composable short-circuit-error behaviour, but it reads like straightforward synchronous code https://github.com/employeerepublic/er-cassandra/blob/master/src/er_cassandra/model/upsert.clj#L150
other libs implement such behaviours for themselves - https://github.com/ztellman/manifold/blob/master/docs/deferred.md#composing-with-deferreds - but there's an advantage to having a standardized interface
mccraigmccraig: have you seen muse? https://github.com/kachayev/muse
@otfrom: or urania - https://github.com/funcool/urania :simple_smile:
mccraigmccraig: ah, yes: http://funcool.github.io/urania/latest/#acknowledgements
i'm not yet, but i think i will soon be using urania - it should make a bunch of stuff simpler in my app
could you get over some of those problems (or at least the weirdness) with :pre checks in some of the functions that expect monads?
(I'm still trying to wrap my head around which bit of these things are the monads, as it looks like it is just passing around useful data structures and not throwing exceptions or returning nils)
and I do realise I'm a numpty
my most common error is this - https://www.refheap.com/01d65cbc88c78c1ea7658819c
which won't be caught by :pre
checks unless they were in the bind
impl itself (which is not unreasonable thinking about it...)
is a bit confused by (return ...)
@otfrom: the monad is the type and its associated bind
/ return
operations... return would be better called wrap
or something
https://github.com/funcool/cats/blob/master/src/cats/core.cljc#L75 <- this?
the way i found to think about it is that every step in an mlet
(aka do
in haskell land) is supplied naked values, and returns a value with the type of the monad
ok, I think I'm starting to get there
yep, that's the one - it wraps a naked value in the monad... e.g. if you are composing manifold Deferreds, it just returns a resolved Deferred with the value in - https://github.com/funcool/cats/blob/master/src/cats/labs/manifold.clj#L80
well, it is a data-structure - plus some bind
and return
ops
:simple_smile:
lol
wondering if an intervention was required
every small explanation of monads tends to drift into full tutorial-land
itβs inescapable
mccraigmccraig: ok, I think I understand a bit of what return is doing, so I just need to understand what bind is doing
minimal: yeah, guilty of asking too many questions again
donβt be guilty, itβs just inevitable hehe
you are probably right... i only intended to give some examples of how they can be useful,and then fell down the rabbit-hole
there's an event-horizon
mccraigmccraig: examples of how/where they are useful (what problem they are solving in a particular instance and how) is usually what I don't get from the monad tutorials I've read
I would say itβs hard to think about as a thing unless you are actually using them
and it is hard to know where to use them without a good example
@otfrom: bind
is taking a wrapped value, unwrapping it and feeding the naked value to a function, which returns another wrapped value
mccraigmccraig: thx
so, using the Deferred example again, bind
takes a Deferred, gets at it's resolved value (by registering a callback in this case), and passes it to a function which is expected to return another Deferred - i.e. does a step in an asynchronous computation without you needing to wire up callbacks yourself - https://github.com/funcool/cats/blob/master/src/cats/labs/manifold.clj#L80
i'll stop now @minimal π
lol
ok, that's useful. I get the idea of using monads as a way of handling the failures of remote systems. Does that particular type of monad have a name? (Like State or IO or Fred?)
minimal: I'm a bad influence
hehe
I did warn you
but knowing that you just described monad transformers will help me when I come across someone else talking about them, so thank you
there are things like Maybe and Either for signalling things not working out as expected
@otfrom: the either or exception monad can be combined with other monads for that sort of behaviour... e.g. you could combine a core.async promise-chan monad with an either monad
if your type already has error-handling built in (like promises or manifold Deferreds) then you won't need to do that, and the basic monad implementation for the type will probably come with error-handling behaviour
as in "either you get the result or you get an error data structure"
zakly
OK, I think I've got you there
and if using a type system you have to check
the monad-transformer allows you to take two monadic structures, say promise-chan
and either
and create a new monadic structure like promise-chan<either>
i.e. a promise-chan
containing an either
minimal: b/c the expected return type is different from the error type which is why you wrap it in an either type that can handle that for you?
yeah, by saying that the type is and either then the type system will make sure you handle both cases. In a dynamic language not so much so itβs less useful
...
and I'd probably solve that problem in core.async using something like http://clojure.github.io/core.async/#clojure.core.async/split
say if I was processing msgs coming in and I was trying to coerce them using plumatic schema and then I'd either get back the type I expected as a return or and error and then I could use a predicate in split to get a chan of the good ones and a chan of the bad ones to pass to a transducer
Yeah iβve done things that group by true/false after a channel
I think that is the type of tying into the kind of work I normally do that I've been missing around monads tbh
minimal and mccraigmccraig thx for talking me through that. I feel I've made a little break through. I think most of my problem has been around the terms used to describe it more than anything.
yw @otfrom
and this also means that an earlier conversation I was having with Rich Hickey around monads and stats calcs makes more sense too
Thx @mccraigmccraig @minimal - useful convo to listen in on.
Me too. So engrossed I missed my bus stop
malcolmsparks: lol
@otfrom: u invented the socratic monad tutorial !
yeah, but Socrates usually knew the answer he was after. I was just a numpty trying to understand a small part of monads. π
@otfrom: looks quite nice actually - http://www.foodnetwork.com/recipes/hemlock-cocktails.html
@mccraigmccraig @minimal reading the Wadler paper now π
@otfrom cool, I was going to suggest that. At leat a bit of it if you can stomach/ignore the maths notation
Also the terminology is slightly different for some of the function names