This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
- # aleph (5)
- # announcements (18)
- # babashka (3)
- # babashka-sci-dev (56)
- # beginners (56)
- # biff (5)
- # calva (27)
- # cider (20)
- # clj-commons (2)
- # clj-kondo (17)
- # cljsrn (18)
- # clojure (41)
- # clojure-europe (24)
- # clojure-nl (1)
- # clojure-serbia (1)
- # clojure-uk (15)
- # clojured (1)
- # clojurescript (40)
- # cursive (39)
- # datahike (2)
- # datalevin (4)
- # datascript (5)
- # emacs (23)
- # events (2)
- # figwheel-main (3)
- # inf-clojure (1)
- # instaparse (23)
- # introduce-yourself (3)
- # jobs (3)
- # jobs-discuss (13)
- # joyride (1)
- # juxt (10)
- # malli (21)
- # nbb (29)
- # off-topic (18)
- # pathom (29)
- # polylith (11)
- # project-updates (1)
- # proletarian (1)
- # rdf (2)
- # re-frame (4)
- # reitit (2)
- # releases (2)
- # remote-jobs (1)
- # shadow-cljs (52)
- # tools-deps (57)
- # xtdb (32)
I've read some people describe using Pathom as a tool for generic function composition. Are there any articles that elaborate on this way of thinking with some examples?
I've been thinking of writing an article on this. I think of Pathom as automatic function composition.
I did this a few days ago. Not an article, but related. https://github.com/souenzzo/sciphi
@U2845S9KL It may have been something you mentioned that got me thinking about it. I've been trying to find more places to use Pathom in my code, but I feel like I'm not really getting the full potential. I don't have a clear picture in my head about how it should work when, as you described, you have several resolvers that get attempted until one returns something other than nil. I mean, I can describe it, but I don't see how I'd re-implement my existing code that way to get value out of it. As for the concept of going up one level of abstraction and returning things like object expressions rather than the objects -- that's hard to wrap my head around at all. And further, I find myself shying away from using Pathom where a regular function would be "good enough" because I'm worried about adding unnecessary complexity or potential latency, but I think this sort of thinking is what's holding me back from understanding "Pathom as automatic function composition". I recently read Out of the Tarpit and thought the parts about artificial execution order requirements creating unnecessary complexity were relevant to Pathom's value statement about "abstracting the function call chain"... so here I am trying to make more sense of how to leverage it. Hopefully that gives you some more ideas for that article 🙂
In my current project, I have structured the entire backend data model around Pathom not just the client facing API
There are definitely tradeoffs. On the positive side, it forces me to be more thoughtful about the data model and that has lead to better structure.
But the downside is that data model is harder to navigate because my tooling doesn't understand it like it understands function calls
Some of th navigation problem is ameliorated by Pathom Viz but that tool isn't quite where it needs to be (yet)
You have definitely given me more reason to flesh out my thinking in an article. Now I just need to find the time 😃
> But the downside is that data model is harder to navigate because my tooling doesn't understand it like it understands function calls Ah, yes, I don't know how many times I've thought "it would sure be nice if the code lens could give me reference counts on these attributes".
Overall, I'm happy with the decision. In fact, I'm thinking of writing a macro that blurs the line between a resolver and regular function even more.
There are some cases where my application needs parameters that are computed by a client facing resolver AND would benefit by pulling additional information out of the Pathom environment
I'd like to invoke that code as a regular function (out of convenience) by passing in both the environment and a list of parameters rather than bind it all up in an entity map.
I just looked at the link @U2J4FRT2T posted . That might be what I'm talking about
The current sciphi impl only resolve keys in function calls. Today I think that it could do something directly on maps. I will try to do it
hello @UPWHQK562, about the mental model, there a few things that I like to keep in mind that help me, and may help you too: 1. everything is a graph: the first big mental thing here is to imagine that all your data is a single graph, where nodes may contain data and/or links to other nodes (entities), in abstract that's possible any data because we deal and think with data that has those relations/connections 2. generic entities: this is the idea where every node in this graph is generic (in contrast with a GraphQL graph for instance, where the nodes must have specific types), and what the node is/can do depends on the data available at it, that when combined with resolvers will define the reach of that node (both in terms of the data on itself, and the relationships of it) them its about defining these atributes and mapping them 🙂
I find souenze idea a very interesting experiment, in practical terms I wouldn't go that further to make everything on Pathom, mainly for 2 reasons: 1. Pathom is not performatic enough to replace standard call stacks, if you need real speed, better to compute "out of the graph" and just put it back under a name. 2. not everything needs a name, Pathom is more on the controller side, but depending on the complexity of the process, its easier/better/faster to dont have the names for every intermediate step, the names that make sense are the ones you plan to use somehow, and the good thing is that you can always add names in the middle if you need later without affecting the users, this frees you to decide later what intermediate steps you want to name
Thanks for the input everyone. I think I'll continue trying to use Pathom in more places, but will look out for the performance hiccups. I'm still not totally clear on how it works as automatic functional composition, but hopefully I'll build up that intuition with more experience:crossed_fingers:
I'd love to hear what you discover on your journey (yeah, I know I need to write up my thoughts as well 🙂 ).
In response to @U066U8JQJ’s comment, "not everything needs a name" - This is true but I find that Pathom doesn't help or hinder in this regard. Without Pathom, I have to name the function. It's true that Pathom makes me come up with a few different names (attribute names and the resolver name), this isn't a big deal. In fact, the structure that that Pathom enforces helps me regularize names so that names can better serve their purpose: helping me keep the application straight in my head.
This isn't to say that I think resolvers should be used everywhere that functions are used. I definitely do not. I haven't figured out where that boundary is yet, though.
Some days ago I drew an activity diagram and told a colleague that I would love to have some visual programming tool, that could translate something like this into code, parallelized it, if possible… Pathom does effectively that…
In my case, my functions are either throwing if something goes wrong or returning a vector which gets merged with other vectors into a datahike transaction..
@U4VT24ZM3 that's the pattern you use throughout your https://github.com/hhucn/decide3/blob/7c048b0411285282d56a127cd1ec10362d024947/src/main/decide/models/argumentation/api.clj#L68= project? That looks like a nice set of examples for this topic.
@U4VT24ZM3 Yes, I was just looking at your code to see if I could find some concrete examples. Think I need to take a deeper look to understand it better, but some of the resolvers there look like what you were describing. Am I mistaken here?
I don‘t use resolver for this right now. The resolvers are purely for the Fulcro frontend. (Be careful with the code. Some parts are quite old and hastily cobbled together for an experiment. The software is used for my research.) Functions which produce vectors for transaction are prefixed with ->
This doesn't exist in the public domain yet, but a project I'm working on uses pathom as the extension interface. i.e. plugins can install their own compute-able subgraphs to the main app. While large scale plugins haven't been made (yet), I'm quite happy with the composition it gives me in the small scale.
fwiw, we have something similar. We use a combination of
when clauses to support something like multimethods in Pathom. I think the approach is more powerful than multimethods since we don't have to decide on a dispatching function up front. The only thing that we need to be concerned about is the order in which resolvers fire which is very easy to reason about (now that resolvers are executed strictly using priority).