Fork me on GitHub
#beginners
<
2019-08-01
>
dwalmeida04:08:38

i'm a bit confused with walkable and pathom...what's the difference between these two libraries and where do they fit in the overall web app scene ?

jaihindhreddy05:08:24

EQL is a declarative data-oriented query language to query graphs of data inspired by Datomic Pull. pathom is a library that can be used to parse EQL, and connect various data sources to satisfy the queries. pathom has an abstraction called resolver (akin to graphql resolvers) which are used to tell pathom how to query for stuff. walkable is a library that makes plugging SQL-based sources into pathom easily. You can think of walkable as pathom-sql. Watch this to understand more about pathom: https://www.youtube.com/watch?v=r3zywlNflJI And this talk has more demos and how pathom is used in combination with fulcro, a UI library to build "full stack" applications: https://www.youtube.com/watch?v=yyVKf2U8YVg

4
Ahmed Hassan05:08:10

Pathom is heavily used in Fulcro apps, but can be used generically for parsing EQL or mapping data sources.

βž• 4
dwalmeida21:08:41

@U883WCP5Z Thank you. Will go through the links you posted.

dwalmeida21:08:12

@UCMNZLJ93 yes ..that's why I am interested as I'm going through fulcro docs to understand how to do full stack using fulcro

dwalmeida21:08:30

Since walkable is only for queries ..how do you propagate mutations back as sql updates/inserts ?

Ahmed Hassan02:08:01

@ULL659VU6 walkable don't support update/insert.

Ahmed Hassan02:08:20

I think you'll have to use Pathom mutations for it.

dwalmeida03:08:56

@UCMNZLJ93 yeah.. that's the feeling i got skimming through the docs

Ahmed Hassan05:08:56

Pathom is library used for EQL parsing.

βœ”οΈ 4
Ahmed Hassan05:08:31

Walkable is built on the top of Pathom for querying and fetching SQL databases.

dehli13:08:16

Hello, has anyone run into

Error building classpath. connector is not available:  
com.jcraft.jsch.agentproxy.AgentProxyException: connector is not available:  
I'm getting it on my CI when I try to clone a private git repo using SSH (https://github.com/dehli/docker-clojure/blob/master/Dockerfile ). My guess is that there's a a dependency I'm not installing because I don't get that error on my personal linux box.

alexmiller13:08:05

are you running ssh-agent?

dehli13:08:51

Ahhh, I didn't start that. Let me do that in my script. Thanks!

πŸš€ 4
dehli13:08:50

Hmmm, so I ran ssh-agent in my CI script and it seems to have successfully run however I'm still getting that same error. I'll try to come up with a minimal reproducible example.

alexmiller13:08:24

do you have an identity registered in the agent?

alexmiller13:08:25

if not, you need to add your key to the agent with ssh-add

dehli13:08:12

I added the ssh files manually but that could be the step I'm missing. Thanks for the help again!

alexmiller13:08:55

ssh-add tells your agent about your identity (the ssh key files)

alexmiller13:08:18

and clj is using jsch to talk to the agent (not to look at your files)

πŸ‘ 4
doesntmeananything15:08:51

does anyone know of a good tutorial for both server and client auth setup with clojure/clojurescript? so far I've only found back-end stuff, but not sure how to proceed on the client

jumar15:08:03

If you are talking about form based authentication that's pretty simple - just add an html form and submit it to the login route + handle potential auth errors

doesntmeananything15:08:15

yeah, I'm building a fairly simple SPA but want to implement all the fundamental stuff, like being able to log in. I'm super new to clojure so I'm not even sure how to approach what you suggest. Would appreciate if you could point me towards some centralised source of info on how to do it with clojure and in some idiomatic fashion

jumar15:08:33

On mobile so don't have access to any links right now. But if you're able to implement any other UI component then login form should be pretty easy. For server side we use friend library - that's IMHO easier to use than buddy.

doesntmeananything15:08:25

cool, thanks for the tips

Chase16:08:25

just had a kind of "ah ha!" moment when I saw someone use (repeatedly 5 #(rand-nth [:x :y :z])). Seeing no % in an anon function made me double take. I hadn't thought to make an anonymous function out of an expression that takes no other arguments to use as the function parameter of something creating lazy seqs and such. I don't really have a question I guess, but what do you think of this approach? Any pitfalls I should know? I kind of want to start throwing # in front of stuff now and see what design patterns that leads me through if that makes sense. Still looking for a deeper understanding of concepts like laziness and composing functions.

andy.fingerhut16:08:13

There are not a lot of functions that don't have a parameter like that, but there is nothing wrong with the expression you show. I wouldn't recommend just randomly throwing # in front of other expressions, unless it is in very isolated experiments at the REPL, when you are curious what will happen. Most expressions that do something useful would likely be changed into a non-working expression by such a change.

xi16:08:09

You can make a binary etc with #(print %1 %2). It's just shorthand for fn. Sometimes partial is easier.

alexmiller18:08:33

if you see # without a %, you're basically looking at a thunk that can delay calculation. Clojure also provides delay which is a bit more elaborate. https://en.wikipedia.org/wiki/Thunk

πŸ‘ 4
alexmiller18:08:40

namely, delays cache their result (include exceptions thrown)

Ahmed Hassan18:08:37

What are good resources for finite state machines in Clojure?

hiredman18:08:42

finite state machines are an extremely broad topic and there are many applications and many different approaches

πŸ‘ 4
hiredman18:08:29

https://github.com/ztellman/automat is the only library I know of that deals in sort of classical fsm's from automata theory, but even there its approach isn't universal (I like fsm's a lot and try to use them everywhere, but have never ended up using automata)

πŸ‘ 8
hiredman18:08:34

outside of automata theory when programmers talk about finite state machines they often mean a loop around a switch statement, or something vaguely actor like, which core.async can fit in well with

πŸ‘ 4
hiredman18:08:38

and core.async's go transformation can be seen as turning clojure code in to a fsm

Ahmed Hassan19:08:15

Can you elaborate that?

hiredman20:08:00

core.async's go macro rewrite's clojure code to make it possible to suspend and resume execution of the code at various points(for channel operations), this rewrite is often described as turning turning the code in to a state machine, and has the effect of turing the code in to a loop and a case (switch)

hiredman18:08:12

coming from the programming view of fsm's as loops around switch statements erlang has its own notions of finite state machines built on actors (gen_fsm, which I don't know a lot about) so there are a few different erlang inspired clojure libraries that deal in that sort of thing

πŸ‘ 4
hiredman18:08:22

my favorite fsm reference (not really clojure specific) is the wikipedia page, which talks about classical finite state machines as relations on sets, which is super useful for modeling fsm as data you can inspect and do neat things with, which you cannot do with the loop around a switch

πŸ‘ 4
SgtZdog19:08:52

Is there a tidier way of including values into your strings like python's f'This is a string with a {my_named_value} in it.'?

noisesmith19:08:39

there's str, format, and clojure.pprint/cl-format

SgtZdog19:08:46

Or do I have to do (str "This is a string with a " mynamedvalue " in it?")

noisesmith19:08:48

no syntax for it though, those are all functions

noisesmith19:08:23

there are also templating libs (usually used for html or sql) which accept a similar substitution syntax, but take the substitutions as a hash map, not named locals

SgtZdog19:08:31

Yeah, the (str) function is what I want here, I just really liked python's f-strings for their tidiness and easy reading.

byrongibby20:08:05

Can anyone please tell me how I can shade dependencies when building an uberjar with lein?

byrongibby20:08:38

Thanks, I will see if this works for me. Much appreciated.

byrongibby20:08:06

@alexmiller I am reading through mrandersons README and I can't quite make out whether it can solve my problem, which I would describe as being equivalent to https://leiningen.librelist.narkive.com/FWrX3HoV/using-the-maven-shade-plugin-from-lein-to-rename-dependencies-or-equivalent-functionality , would you mind taking a quick look at the post and giving a yes/no response as to whether I should pursue mranderson as the solution to this problem. If you don't have the time it's no worry. πŸ™‚

alexmiller20:08:03

I’ve never used it but people use it for the same purpose as maven shade

byrongibby20:08:23

Cool, I will do some further research tomorrow.

argo22:08:16

Hi total noob here. I'm wondering how to do branching on a map expression. To explain what I mean: I'm working on the rna-transcription exercise on http://exercism.io (sry, I don't know how to get a public link to the exercise). Part of the requirements is to throw an assertion error on invalid input. This works:

(ns rna-transcription
  (:require
   [clojure.string :as s]))

(def dna-to-rna-map {\G \C \C \G \T \A \A \U})

(defn- dna-to-rna-char
  [c]
  (or (dna-to-rna-map c) (assert false)))

(defn to-rna
  [dna]
  (s/join (map dna-to-rna-char dna)))
(to-rna "AGX")
;; => throws
I'd prefer to do throw on the outmost fn, in this case to-rna. But I can't just (s/join (or (map dna-to-rna-char dna) (assert false))) there. My guess is map in this case returns the entire seq at once, so the or is always true. And I don't want to iterate over the seq more than once, just to check if it contains any nil value. I hacked together a solution with a custom transducer just for throwing, but I'm sure there is a better way. So, is there a good way to do side effects or branching in a chain of reducers or a in a transducer? Sorry if I don't make sense, happy to explain ...

Crispin03:08:01

What about not throwing, and just returning a nil?

Crispin03:08:45

I like to keep exceptions for exceptional circumstances. Having an X in a fasta file is pretty common, isn't it?

noisesmith22:08:24

@argo when map finds an invalid codon, that means one element in its list is nil

noisesmith22:08:05

clojure considers a list with a nil in it to be "truthy", so the assertion can't fire

noisesmith22:08:26

the right place for the assertion is the position you have - the place where the input is found invalid

noisesmith22:08:48

assertions and exception throwing are not functional or value oriented, there's no need to pretend they are functional

argo22:08:37

@noisesmith Yes,that's what I thought, thank you. It was part of the exercise to throw, I would prefer not to in my own code. But is there a way to do branching in a transducer? It would be nice if I could process the elements of a seq one after the other and, dependig on the value of the element, choose different paths how to go on.

noisesmith22:08:54

what I mean is it doesn't matter where in the stack you throw

noisesmith22:08:05

nothing above it catches, so the throw happens as needed

noisesmith22:08:28

also what transducer are you talking about?

argo22:08:20

Yes, it's just an example from the exercise. About the transducer: There is no transducer in the code, I'm just wondering how to do branching in a transducer. But never mind, thank you for the info πŸ™‚

noisesmith22:08:28

we use if or cond or case for branching, but I am not sure what kind of branching you are talking about, why you are looking to a transducer so it's hard to answer

argo22:08:47

Another solution to the task I came up with is this:

(ns rna-transcription)

(defn- throw-on-nil [xf]
  (fn
    ([] (xf))
    ([result] (xf result))
    ([result input]
     (cond
       (nil? input) (assert false)
       :else (xf result input)))))

(defn to-rna [dna]
  (let [s (transduce (comp
                      (map #(get (hash-map \G \C \C \G \T \A \A \U) %))
                      throw-on-nil)
                     conj
                     dna)]
    (clojure.string/join s)))
In this case, I just want to stop processing the elements of the seq as soon as I get a nil and, because of the requirements, throw. Another possibility would be to stop processing and just return nil. But as I'm just starting with clojure, I guess I might better stay with the fundamentals

alexmiller23:08:48

If you’re throwing, that will stop the reduce. But if you want to just end and throw later you can use reduced to signal early termination

argo23:08:06

Ah okay, I'll have a look at reduced. Thank you.