Fork me on GitHub
#beginners
<
2020-03-16
>
soxley02:03:49

@seancorfield looks like that worked. Thanks! I didn't think I would have to import the nested class specifically.

Tuomas12:03:09

Hi, I’m new to Clojure and confused about:

(let [[[x]] [[:x]]] x)
; vs
(first (first [[:x]]))
; in a datomic cloud ion
I have a fulcro + pathom + datomic cloud backend. I have read the documentation on all but probably should revisit certain parts? I got errors for: class java.lang.UnsupportedOperationException: nth not supported on this type: HashSet in a resolver ["^ ","~:enemies","~:com.wsscode.pathom.core/reader-error","~:com.wsscode.pathom.core/errors",["~#cmap",[["^0"],"class java.lang.UnsupportedOperationException: nth not supported on this type: HashSet"]]] and the resolver:
(pc/defresolver enemies-resolver [{:keys [db]} input]
  {::pc/output [{:enemies [:list/id]}]}
  (let [[[list-id]] (d/q '[:find ?list-id
                           :in $ ?list-label
                           :where
                           [?list :list/label ?list-label]
                           [?list :list/id ?list-id]] db "Enemies")]
    {:enemies {:list/id list-id}}))
I figured it was because of the let form although I tested it should work
(d/q '[:find ?list-id
         :in $ ?list-label
         :where
         [?list :list/label ?list-label]
         [?list :list/id ?list-id]] db "Enemies")
=> [[:enemies]]
(let [[[list-id]] [[:enemies]]]
  list-id)
=> :enemies
I was wondering what d/q was returning after deploying to ions (everything worked fine when served locally through http-kit) so I modified the resolver and redeployed
(pc/defresolver enemies-resolver [{:keys [db]} input]
  {::pc/output [{:enemies [:list/id]}]}
  (let [res (d/q '[:find ?list-id
                   :in $ ?list-label
                   :where
                   [?list :list/label ?list-label]
                   [?list :list/id ?list-id]] db "Enemies")]
    (cast/alert {:msg "EnemiesResolver" :ex res})
    (cast/alert {:msg "EnemiesResolver" :ex (first res)})
    (cast/alert {:msg "EnemiesResolver" :ex (first (first res))})
    {:enemies {:list/id (first (first res))}}))
but it actually returned what I expected in the first place and started working
{
    "Msg": "EnemiesResolver",
    "Ex": "[[:enemies]]",
    "Type": "Alert",
    "Tid": 66,
    "Timestamp": 1584357837592
}
{
    "Msg": "EnemiesResolver",
    "Ex": [
        "Enemies"
    ],
    "Type": "Alert",
    "Tid": 66,
    "Timestamp": 1584357837592
}
{
    "Msg": "EnemiesResolver",
    "Ex": "Enemies",
    "Type": "Alert",
    "Tid": 66,
    "Timestamp": 1584357837592
}

Tuomas12:03:03

TL;DR Why does this not work

(pc/defresolver friends-resolver [{:keys [db]} input]
  {::pc/output [{:friends [:list/id]}]}
  (let [[[list-id]] (d/q '[:find ?list-id
                           :in $ ?list-label
                           :where
                           [?list :list/label ?list-label]
                           [?list :list/id ?list-id]] db "Friends")]
    {:friends {:list/id list-id}}))
And this does
(pc/defresolver friends-resolver [{:keys [db]} input]
  {::pc/output [{:friends [:list/id]}]}
  (let [res (d/q '[:find ?list-id
                           :in $ ?list-label
                           :where
                           [?list :list/label ?list-label]
                           [?list :list/id ?list-id]] db "Friends")]
    {:friends {:list/id (first (first res))}}))

jumpnbrownweasel12:03:14

I think it's because in the first case you're using vector destructuring ( [[list-id] ) on a map (return from d/q )

jumpnbrownweasel12:03:24

When you have a map on the right side, you have to use map destructuring on the left side. https://clojure.org/reference/special_forms#_map_binding_destructuring

jumpnbrownweasel12:03:32

You can't use destructuring to get the first k/v pair from a map.

jumpnbrownweasel13:03:08

One reason is probably that maps (by default) are unordered, so the first k/v pair is arbitrary.

jumpnbrownweasel13:03:38

In the second code (that you said works) you're using first to get the first k/v pair. That method (along with next and rest) are used for traversing through all the k/v pairs of a map. Vector destructuring uses nth rather than first to get a specific entry by index, and nthis not allowed on maps.

Tuomas13:03:17

Thank you! I did some further testing in the REPL. It seems to me like datomic.client.api/q sometimes returns a vector and sometimes a map

(def conn (d/connect (get-client) {:db-name database-name}))
=> #'app.database/conn
(def db (d/db conn))
=> #'app.database/db
(d/q '[:find ?list-id
         :in $ ?list-label
         :where
         [?list :list/label ?list-label]
         [?list :list/id ?list-id]] db "Enemies")
=> [[:enemies]]
(let [[[list-id]] (d/q '[:find ?list-id
                       :in $ ?list-label
                       :where
                       [?list :list/label ?list-label]
                       [?list :list/id ?list-id]] db "Enemies")]
    list-id)
=> :enemies

pithyless13:03:51

@UH9091BLY you can use [:find [?list-id ...]] to return a collection, or if there will only ever be one list-id in this query, you can use [:find ?list-id .] to return the scalar directly (without needing to use destructuring). By default [:find ?list-id] returns a set-of-tuples

eagon17:03:03

For cloud I thought only find rels were allowed? Not sure if I could get the single return or collection return notation working

eagon17:03:47

Also @UH9091BLY I ran into this problem before on cloud, the reason is that while locally during dev your return is a vector of vectors, like @U05476190 says inside the actual transactor/query group it's a hash-set of vectors, which doesn't support nth or destructuring

pithyless18:03:45

I didn’t realize the cloud (or is it a difference in the peer vs client api?) query works different than on-prem in this situation. YMMV :)

eagon18:03:03

Yeah I got tripped up on the same thing, wonder why there's a difference

Endre Bakken Stovner14:03:08

I want to create a DAG (https://github.com/stuartsierra/dependency), but the examples for how to create one only work when the values to insert are hard-coded.

(def g1 (-> (dep/graph)
            (dep/depend :b :a)   ; "B depends on A"
            (dep/depend :c :b)   ; "C depends on B"
            (dep/depend :c :a)   ; "C depends on A"
            (dep/depend :d :c))) ; "D depends on C"
If the values to insert come from a list of tuples, this does not work. What is the idiomatic way to update the created graph object with arbitrary tuples from a vector?
(for [[in out] to-insert]
   (dep/depend g in out))
obviously does not work since dep/depend does returns a new graph.

jumpnbrownweasel14:03:55

I haven't used that library, but I suggest trying a reduce of your list of tuples, where the reducing function calls (dep/depend acc x y), where accis a (dep/graph) and x and y are the values in each tuple.

Endre Bakken Stovner14:03:46

Yes, of course 🙂

Endre Bakken Stovner14:03:22

One way would be to create an atom with a graph and update it in the loop, but this cannot be the best way...

Lukas20:03:46

Hi all, can anybody help me with connecting to a socket repl in emacs? I have cider installed and inf-clojure but both don't really work out of the box for me (I know I probably do something wrong 🙈) Cider -> connect to a clojure repl doesn't seem to work and with inf-clojure i have no idea how to connect to the repl (babashka)

borkdude20:03:13

@lukas.block What works for me:

$ bb --socket-repl 1666
M-x inf-clojure-connect <ret> localhost <ret> 1666 <ret>
This will open a socket REPL buffer. Then in your script file:
M-x inf-clojure-minor-mode
And then you can eval forms from your buffer.

Lukas20:03:25

❤️ thank you, and thanks for creating babashka 🤗

borkdude20:03:03

I'll try and document this at the bb repo.

borkdude20:03:11

np, enjoy 😉

borkdude20:03:38

Maybe @bozhidar could also take a look at the above if what I've been describing is correct from the pov of inf-clojure

bozhidar08:03:21

You’re totally right. 🙂 Might be a good idea to add something about bb in the inf-clojure README.

borkdude08:03:09

Chlorine and vim-iced also have autocompletions for bb socket REPL btw :-)

andy.fingerhut20:03:29

I have used inf-clojure for months now to connect to a socket REPL, to Clojure/JVM processes started with the clj and clojure commands provided as the Clojure CLI tools.

andy.fingerhut20:03:03

Sean Corfield's sample deps.edn file has a :socket alias defined in it here https://github.com/seancorfield/dot-clojure/blob/master/deps.edn#L66-L67 that can be invoked from the command line by typing clj -A:socket for example.

mrchrisadams20:03:20

hey folks. is light table supported any more?

andy.fingerhut20:03:14

Last I heard, no one is continuing to enhance it. I do not know how useful it is in its current state.

borkdude20:03:05

Last time I heard about it was when someone asked why clj-kondo (on the JVM) didn't work for him in LT. Apparently it's stuck on Clojure 1.8 for some reason.

andy.fingerhut20:03:14

It sounds like if it already does what you want it to do, then go for it, but do not expect someone else to enhance/fix things if it does not work how you wish.

andy.fingerhut20:03:11

Other editors with add-on support for Clojure like Atom + Chlorine, VScode + Calva, Emacs + CIDER or inf-clojure, vim with one or two add-ons whose names I do not recall because I haven't used them, are all under more active development.

mrchrisadams20:03:44

ah… thanks folks. I was looking for the simplest way for someone to start, in a fairly lightweight editor

mrchrisadams20:03:31

what’s the closest thing to light table these days, that doesn’t require folks to know about versions of jdk?

andy.fingerhut20:03:54

If they are willing to install AdoptOpenJDK 8 or 11 based on your recommendation, and not otherwise worry about its version, those are two very good choices that are unlikely to cause you to worry much about them for a while.

andy.fingerhut21:03:41

I do not know which environments exist that do not require first installing a JDK. If they do, it is because they include the installation of some JDK inside of them.

eagon07:03:45

@U06DGRFRB Nightcode works really well for something simple to start, has all dependencies baked into a jar, and good enough editor features like parinfer https://sekao.net/nightcode/

mrchrisadams08:03:03

Thanks folks. Light table was erroring when starting because I think I had open JDK9 installed, and I wasn't ready to take the plunge with Emacs yet. Nightcode seems ideal, and worked first time with a web project. Danke!