Good moaning https://i.pinimg.com/736x/42/c5/94/42c594705b5b803f4d223400e625f999.jpg
Morning
Good Morning!
morning
yarn isn't really needed now that npm has a native runner and lockfiles afaict
though maybe i'm missing a trick :)
When I did front end js agency work npm was a nightmare… But I’ve been out of that world for many years, and we’re currently using yarn in combination with shadow-cljs. However a colleague of mine who is in the know wrt js matters, by pure coincidence mentioned to me yesterday that npm was very deserving of its bad rep, but they eventually fixed the problems and is pretty good these days. Hence I think it’s one of those things where peoples perspective is coloured by when they last used it.
Question. Let say you receive a request that contains a code. That value is used to determine which code path to follow. Each code path could potentially invoke 1 of a number of possible calls, but only some are valid for a particular value. In Java, I would have an interface that has this set of possible methods, with the concrete implementations either providing the functionality, or returning an UnsupportedOperationException (or a null value) (keeping it simple, not taking about an abstract partial implementation). At runtime I would invoke the particular concrete implementation depending upon the value I receive, assured that as the interface is being implemented, the method must exist on the implemenation (the method may or may not return a result). In Clojure, would a multimethod suffice, or would I look to use Protocols (not something I've used before)
Looking to keep it simple to reason about and extensible.
Protocols are the closest to Java interfaces (and implementing classes) and they'll dispatch on the type of the first argument (the "object type" in Java).
Multimethods can dispatch on anything.
When you say "a request that contains a code", what exactly do you mean?
What is that code? Can it have multiple types, or just multiple values of the same type?
just a code, like "TISITA" which means something to us internally
So how would you have interface / implementation in Java based on that?
Just writing that 🙂
A moment
(I'm expecting a factory method or even a factory builder class thingy at this point 😐 )
Basically I have a set of customers which can grow. Each customer is allowed to perform a series of operations, let's say "eat", "sleep", "drink". However, not all customers need to "eat". But they may do in the future. So, I want to design something that says, if you are onboarding a new customer, they all have to adhere to "eat" "sleep" "drink", but maybe it might take some time for them to respond to the "eat" request, so just return nil for now. Therefore, as the request comes in (from the API) and I see, ah! this is Customer A, I still want to invoke "eat", but I don't really care if it returns something or nothing right now.
(think that "eat" is gaining access to their database to pull values out of their system - but takes them ages to do setup the right structure for me to interrogate their db)
So you either have to create a new "type" per customer or have some sort of double dispatch that works dynamically.
right right.
which makes more sense?
Creating a new "type" for every customer feels... awful... I mean, that's why I don't do C++/Java any more!
So I would probably lean toward something more pluggable, and have a hash map per customer with :eat
, :sleep
, :drink
keys and if they are implemented, the value would be a function (or a qualified symbol that resolved to a function) and if they are not implemented, the key could just be omitted.
it's pretty much as you say @rickmoynihan
it was bad, then they fixed it
(when-let [f (:foo customer)]
((requiring-resolve f) customer :or :whatever))
now it's good
right right. thinking...
The nice thing about a hash map with qualified function symbols is you can easily serialize that -- to a file or DB or over the wire or whatever.
never used requiring-resolve before...
a mment
door
It was new in 1.10
sorry dharrigan to be memeing around a serious conversation but i always think this when js comes up haha
btw, you're up late Sean
Yeah, rough day. We spent 3+ hours at the emergency vet with one of our cats tonight (and dropped $5,000 on it) so I'm trying to chill enough to go to bed. Already two beers in since I got home...
(This is a cat we spent $10,000 on four years ago for open chest surgery to remove a tumor -- we think maybe the tumor is back so we're not even sure we'll get him back from this latest vet visit)
oh dear
I hope it recovers well
is :foo
in this, my :eat
in my discourse?
Thanks, but we're not very hopeful. We were very lucky the tumor was operable before -- they happened to have access to a very special feline surgeon -- but the initial evaluation this time shows "very abnormal heart shape" and hyper-inflated lungs so... 😞
He's 15, nearly 16, so we don't want to put him through such invasive surgery again. He barely recovered last time.
(but once this second beer is gone, I'm off to bed... and it's nearly gone)
Yeah, or :sleep
or :drink
Or :implement-your-f'ing-database
🙂
neat
ah stand up
morning
(beer's empty, bedtime!)
thanks sean
I’m going to ponder on what you’ve said and maybe have more questions later 🙂
ttfn!
and you can get it to implement a protocol too
Morning. Sorry to hear about you feline friend Sean 😿
Playing around with requiring-resolve
. It seems another way of doing dynamic dispatch, akin to a multimethod
@dharrigan for what you describe I'd literally just do a multimethod
probably also a good place to use a variant
[:type/of/thing {:hash-map-representation-of-thing "will work i think"}]
arbitrarily extendable
and you can validate with a spec or schema that has an enum/set of the :type/of/things
that you allow
Yeah, @dharrigan personally I’d be careful with using requiring-resolve
after system instantiation. Loading namespaces and their dependencies can be side effecting, so it’s good to know when things are required.
Also might be worth mentioning you can use integrant to ensure each customer has the appropriate set of f
’s, you can then optionally use ig/load-namespaces
to essentially do the requiring resolve; but essentially move that call to instantiation time rather than having it be at runtime or on-demand.
ooh i hadn't thought of that
gpwm
integrant is pretty great at letting you configure a base config of wiring, and then having config per customer, all as edn.
?
I use juxt clip instead of integrant :)
but it would do the same thing
yeah it should support a similar setup
Looks like it also does the requiring-resolve
good point well made
I think this is what gets me about the js/node ecosystem: https://clojurians.slack.com/archives/C03RZGPG3/p1600274375276100 That's where my problems stem from. Lock files are great, but this problem can't be solved on stack overflow.
:woman-shrugging:
i very rarely have to interact with the community as a dev
the culture hasn't generally affected me other than the occasional big f-up that's obv affected all node projects, but no different to heartbleed or whatever it might be where i've had to patch servers
these things happen
and better node having that problem than e.g. the white supremacy problem in haskell
Look up the stuff around lambda conf, one of the main alt right 'thinkers' is/was big in haskell and we've had our fair share of edgy stuff from that quarter as event organisers. Like most things it's a few bad apples but does seem to be more common in haskell and scala. Although the uncle bob thing is bringing it home to roost in clj land now as well.
Thanks Alex. I was somewhat aware of Lambda conf issues and yeah I see issues relating to Bob Martin as well 😕
but i take yr point
I’ve not heard that about Haskell before. Could you share a source?
@alex.lynham oh yeah, it affects everyone in node. But node users seem to enjoy rewriting everything every few months to use the latest version of a library. Power to them, but it's not for me.
grr; there's been a Spitfire circling overhead with > Thankyou NHS painted onto its wings. People seem to be going into paroxysms of ecstacsy, But it doesn't seem to me like its doing much good for anybody
I mean the pilot is having fun, obviously
but that's it
Is it just that I've completed my transformation into a Miserable Old Git
We're very inclusive 🙂
the best thing about the Spitfire aeroplane is that it was given a cool name
well and was very agile for its time I suppose
it was, plus relatively cheap to build
a straw poll of my ex housemates (all doctors) suggests that they don't want thanks, they want people to vote out the tories and vote in a government that will fund the nhs
@alex.lynham Yeah, I felt I was one of the few people in the country who hated the clap for the NHS thing. Firstly the time genuinely didn’t suit as it was daughters bed time. However mainly I objected to the idea that NHS workers should be heroes. Not because they’re not deserving of the highest admiration; because they are, but because we shouldn’t expect and exert social pressure on them to risk their lives. It felt to me like the government encouraging the country to clap for them just enabled the government to not give them PPE, not give them pay rises, and generally treat them like dirt; but that’s ok because they’re heroes now!
I also know a few NHS workers who felt similarly; but the country clapping thing kinda silenced them on the issue.
Yeah what you say basically lines up with what my mates said. One was on an acute rotation where they were reusing PPE and he was very angry about it as you can imagine
Clapping doesn't solve chronic underfunding and government incompetence
@jiriknesl: That’s just because we’re a first world country. Most developed economies should expect to be in the top 10% globally. If you compare us to developed economies it’s more complicated, but we typically don’t do better than mediocre, and tend to be towards the bottom of the pile for most metrics.
makes sense
@dharrigan It's just a version of resolve
that will require
the ns of the name if it isn't already loaded. resolve
turns qualified symbols into actual Vars.