Fork me on GitHub
#beginners
<
2018-02-24
>
Will01:02:56

I’m calling a query like this

(let [card-account (j/query t-con [queries/get-card-account-by-card-account-user-id (:entityId receipt)] {:result-set-fn first})]
and the object looks like this
card account  {:account #object[org.postgresql.util.PGobject 0x7618a385 ("2015-12-14 08:04:22-07","2019-12-14 08:04:22-07",854.06,854.06,0.00,0.00,29,0,30,0,220)]}
How do I make it come back as a clojure map?

Will01:02:30

Nvm I figured it out, my query looks like this

"SELECT account FROM card_account as account, card_account_user as causer
      WHERE account.card_account_id = causer.card_account_id AND causer.card_account_user_id = ?"
Any reason why all the fields from account aren’t in the map?

noisesmith02:02:00

what kind of data type is account?

seancorfield04:02:20

@josmith2016 Try changing your query to SELECT account.* FROM card_acount as account... -- I think Postgres is "helpfully" trying to return the whole row as an object because that's what you asked for.

Appo06:02:07

hi I have a question concerning the threading macro, is this the idiomatic way to handle switching argument positions?

Appo06:02:10

(def some-string "this is a string")
(defn foo []
  (-> some-string
      (str/split #" ")
      ((fn [x] (map count x))))

Appo06:02:07

or is it preferable to just use another ->> instead of the anonymous function?

dpsutton07:02:21

(defn foo [some-string]
  (as-> some-string <>
      (str/split <> #" ")
      (map count <>))

dpsutton07:02:44

although if its not heavily nested as here maybe just compose the forms yoursef?

dpsutton07:02:45

(defn foo [some-string] (map count (str/split some-string #" ")))

Aron10:02:47

if I have two sets that I know that are disjoint, how can i use the data as a single set? so i don't have to union or map over a list of sets every time

Reuben Steenekamp11:02:50

With clojurescript macros, which you write in clojure, how do you handle clojurescript dependencies. Say, for example, that my macro uses clojurescript libraries. How do I ensure that the libraries are included wherever the macro is referred?

mfikes14:02:07

One answer for @ashnur is in #clojurescript

mfikes14:02:58

@reuben.steenekamp For your macro to use a ClojureScript library, it would have to expand to code that uses that library. One solution is to simply additionally require that library wherever the macro is referred so that the expanded code works properly. Another (perhaps easier to consume) solution could be to introduce a ClojureScript namespace to accompany the macro's namespace, and have the macro expand to calls to that ClojureScript namespace (which can then delegate to the ClojureScript library). In this secenario, if the macro namespace and accompanying ClojureScript namespace have the same name, then you benefit from implicit macro loading and simpler macro inference. This ends up allowing consuming code to simply require the ClojureScript namespace while simply referring the macro (in other words, a single require/refer instead of a require-macros along with a require of the ClojureScript library namepsace). A lot of this is covered in http://blog.fikesfarm.com/posts/2016-03-01-clojurescript-macro-sugar.html but let me know if you could use an example illustrating how this works.

mfikes14:02:17

In concrete terms, if your macro wants to call into some.library, you can introduce a my.foo split across foo.clj which has the macro, and foo.cljs which has a :require-macros for my.foo, and a :require for some.library, and ClojureScript functions that call into some.library which the macro in foo.clj expands to call.

mfikes14:02:41

A macro in foo.clj might look like (defmacro abc [x] (my.foo/bar ~x)) with my.foo/bar being a ClojureScript function that calls some function in some.library. It is important that in foo.cljs you (:require-macros my.foo).

mfikes14:02:18

The benefit of all of this is that some other ClojureScript namespace can simply (:require my.foo :refer [abc]) and then just use the abc macro.

mfikes15:02:34

@reuben.steenekamp Thinking more on this, a concrete example is probably better than the verbiage above. Here is a gist showing a macro that uses a ClojureScript library (`clojure.zip`) https://gist.github.com/mfikes/d296af1c7621d69c5b1db9323763a6ca

mfikes15:02:23

@reuben.steenekamp No problem. I updated that gist (with an abc2 macro) to show how your macro can actually expand to code that directly calls into the ClojureScript library, if you don't want to call a delegating ClojureScript function. Either way works.

justinlee15:02:25

how does all this work in a self hosted scenario then?

mfikes15:02:11

@justinlee It just does 🙂

mfikes15:02:41

But you asked, "how?". My response is that there is nothing that prevents it. Is that a sufficient answer?

justinlee15:02:45

my real question is to try to get some understanding of what requires this funky macro system for cljs in the first place. the existence of self-hosted systems sort of suggests that it isn’t really needed. macros are data-to-data transformations so it has always seemed weird that that’s the one thing that doesn’t work in straight cljs

justinlee15:02:12

i’ve tried to read some blogs on it but i’ve never gotten it

mfikes15:02:12

Ahh, OK. I'd say that macros are "separate" in ClojureScript because ClojureScript wants to optimize by producing artifacts that are small and only contain runtime stuff. (No compiler, essentially.)

mfikes15:02:27

But, in self-hosted ClojureScript there is no technical reason for this constraint.

mfikes15:02:41

The reason macros are separate in self-hosted ClojureScript is for compatibility. There was a desire to not have self-hosted ClojureScript be a completely separate fork that ends up working with code that can't be used with JVM ClojureScript.

justinlee15:02:21

that all makes sense at a high level, but still two things nag at me (1) separate is distinct from choosing clojure instead of clojurescript. why not separate clojurescript macros? (2) don’t macros do their thing, expand the code, and then the compiler comes through and compiles it all to js?

mfikes15:02:49

Yeah, it is interesting to imagine macros that call ClojureScript functions during expansion, and if the entire compiler were self-hosted, whether you could produce artifacts that are small.

justinlee15:02:29

why would the choice of language increase code size if the macroexpansion produces the same result?

noisesmith16:02:04

@lee.justin.m because right now cljs compiles without running any cljs and doesn't rely on a js runtime - so the naiive way to move macro-expansion to cljs would be to put it in the emitted code and make it happen in the target vm

noisesmith16:02:08

just a guess

noisesmith16:02:42

that and the annoyance of making a quirk-compatible macroexpander I bet?

justinlee16:02:35

oh! that makes total sense to me. now i get what the compile size comments are about.

mfikes16:02:35

If you allow macros to call ClojureScript functions, then in theory the code the macro produces can vary at runtime, and thus you would need the compiler at runtime, which I think implies large artifacts. If the ClojureScript functions called at expansion time were pure or completely independent of runtime state, maybe it could be pulled off. Hrm.

noisesmith16:02:41

cljs already has quirkier differences from clj in other places, so you might be able to enforce that 😄

mfikes16:02:51

Yeah, with a completely self-hosted compiler you could allow mixed macros and functions, so long as the macros were "well behaved" and abided by a constraint that they only use "compile-time state."

justinlee16:02:21

how does it work in clojure? can you go make a network call to a server in the middle of macroexpansion?

mfikes16:02:17

Yes. One common idiom is to have a macro expand based on some content in a file.

noisesmith16:02:11

compiling clojure, should this runtime be able to launch missiles? [Y/n] - macro by user input

mfikes16:02:19

Perhaps if you AoT, you force all of the side effects to occur at compile time? Hrm.

justinlee16:02:24

i’d never considered that. super interesting. let’s inject a subtle bug into the code if the weather is nice and it’s a saturday and we are in a production environment

justinlee16:02:07

i always thought macros were purely applicative functions

justinlee16:02:19

hence my confusion, but of course there’s no reason why that would be true

noisesmith16:02:30

IMHO in good well written code they are 😄

justinlee17:02:44

In clojurescript, I have a bunch of networks calls that have to be made in sequence. I have the common pattern of, “do call, if error print message and bail, if okay, go to the next step”. In js, I usually deal with this kind of code by throwing an exception and dealing with it all in a catch block. Is this the suggested way of dealing with this in cljs? If I don’t do it this way, I get indentation problems as each step is in yet another else clause.

noisesmith18:02:33

each of these is in a nested callback right?

justinlee18:02:44

I’m using go blocks right now, but I’m not wedded to it.

(defn complex-remote
  []
  (go (let [response (<! (rpc ...))]
        (if error-condition
          (print "error")
          (let [response (<! (rpc ...))]
            (if error-condition
              (print "error")
              ... and so on))))))

justinlee18:02:00

in javascript, those prints would be throws and then i’d do the print in the catch block

noisesmith18:02:11

then the problem is nested lets, right?

noisesmith18:02:41

you never need nested let

noisesmith18:02:50

or - well sometimes it might be nice, but its not needed

justinlee18:02:09

I should say, I need the response in both the then and the else

noisesmith18:02:15

(let [x (f) _ (println "x is" x) y (g x) ...] ...)

justinlee18:02:18

I didn’t show that in my example

justinlee18:02:45

but i need to bail if there’s an error condition

justinlee18:02:51

i don’t want to keep going

noisesmith18:02:58

let allows referring to previous bindings, and you can use _ for side effecting bindings (it's idiomatic)

noisesmith18:02:11

so you can throw at any step you like, and put all the bindings in one let block

noisesmith18:02:00

since throwing doesn't return, you don't need it to be in an if/else, it can be in a when, and the else is just the next binding

justinlee18:02:43

okay so throwing is the right move in clojure too. when i read books/blogs it always seems like the section on exception handling is, “oh yea you can do this too”

noisesmith18:02:07

@lee.justin.m you can, and in this case it's the simplest option IMHO

noisesmith18:02:38

just make sure your try/catch does the right thing round it - you can use ex-info to construct a throwable with context data so your catch can do whatever you need

justinlee18:02:56

so something like this

(defn complex-remote
  []
  (go 
   (try (let [response (<! (rpc ...))
              _ (when error (throw (js/Error ..)))
              response (<! (rpc ..))
              _ (when error (throw (js/Error ..)))
              ...])
     (catch js/Error e
      (print ...) ...))))

justinlee18:02:14

possibly with ex-info

noisesmith18:02:21

you need _ on the left hand of each when

noisesmith18:02:31

but yes, that's exactly it

justinlee18:02:40

cool that’s nice and readable

noisesmith18:02:33

not only is ex-info more powerful (it lets you accompany it with arbitrary data), (ex-info "foo happened" {:x x}) looks nicer than (js/Error. "foo happened") in code IMHO

orestis19:02:37

@lee.justin.m @noisesmith Just be careful when throwing inside a go block — I can’t find it now but I vaguely remember might be some kind of weird behaviour?

noisesmith19:02:27

@orestis yes I should have mentioned that explicitly, but was reassured to see this was inside an explicit try/catch which does work

justinlee19:02:43

Yea I read about the issue of throwing across the go boundary. But thanks because that’s a big gotcha

petr.mensik20:02:25

Hello guys, I've got a problem with Integrant running my web application. The thing is that I can sometimes run it successfully via REPL (meaning that all components are correctly initialized and application is then running). But it cannot be run with lein run or from built uberjar (and sometimes even not from REPL) with error in the paste. I put the configuration into the pastebin link, for better clarity (it's only 90 lines long including error) https://pastebin.com/AQE9pmVp

petr.mensik20:02:40

I tried to Google it and read upon the topic however I am struggling with this with couple of hours and couldn't solve this problem 😕 I would appreciate any Integrant tips as well, I am not sure if I am using it correctly

Steve Upstill20:02:50

I'm dealing with a philosophical problem/brain shift in approaching Clojure and functional programming. I'm starting out in Clojure by writing a Sudoku solver, where the basic idea is to distribute constraints from individual cells, to their rows, columns and "slabs" (3x3 subgrids), and back to other cells. So each cell is a member of three other collections, and when a cell gets renewed, all three need to know about it.

Steve Upstill20:02:03

This seems contrary to the principle of immutability. I'm sure i can find workarounds, but I'm trying to learn "the Clojure way" or "the functional way" to achieve this effect, and I could use some wisdom here. Anyone care to set me straight? That would be really helpful, and appreciated, so thanks.

noisesmith20:02:07

@steve171 the simplest transformation is often to take a function which mutates an item in a collection and make it a function that takes a state of a collection, and returns a new one. Instead of neighbors "knowing about" a change, data is just data, it doesn't do anything - but your algorithm might cue up a series of changes for the neighbors based on a change

noisesmith20:02:06

and that cue of changes, instead of being a loop that modifies each neighbor, is a list of cells to adjust, which the algorithm is walking through and updating

Steve Upstill20:02:29

@noisesmith Thanks for the suggestion. i'm going to have to think about that, but it's an interesting track to pursue. It seems to imply that each row, column and slab are independent; in particular, there are three representations of each cell, independently in each parent. That means that the updating procedure would have to be atomic across all three representations, yes?

gonewest81820:02:05

…or there’s one representation of the board (a 9x9 grid or maybe a list of 81 cells, each holding a set of constraints)

gonewest81820:02:47

and the update says: I just put a 3 in the center square, so add the constraint “cannot be a 3” to the remaining cells in that column, in that row, and in that slab.

gonewest81820:02:36

various ways to “walk” the current board and produce a new one, depending how you chose to represent it. map probably.

Steve Upstill01:02:55

Neil, I've come down to the problem of "functionally" updating the board, i.e., applying a constraint to some cell and returning a revised board. My procedural brain is rebelling at the idea of copying the entire board except for one cell (especially if it's immutable once defined, so I have to special-case the copy of the cell being changed before it gets redefined). This feels like me not getting something, but it's hard to see what. When you suggest using map, do you mean, say, iterating over all the columns on a board using a function which iterates over all cells in a column, and simply returns all cells which are not the one being modified? Is this the "functional way"?

gonewest81803:02:04

Well, suppose you’re representing the board as a vector of vectors, a 9x9 “array”.

gonewest81803:02:41

foo.core> (def b (vec (repeat 9 (vec (repeat 9 [])))))
#'foo.core/b
foo.core> b
[[[] [] [] [] [] [] [] [] []]
 [[] [] [] [] [] [] [] [] []]
 [[] [] [] [] [] [] [] [] []]
 [[] [] [] [] [] [] [] [] []]
 [[] [] [] [] [] [] [] [] []]
 [[] [] [] [] [] [] [] [] []]
 [[] [] [] [] [] [] [] [] []]
 [[] [] [] [] [] [] [] [] []]
 [[] [] [] [] [] [] [] [] []]]

gonewest81803:02:29

Ok, well actually, that’s a 3 dimensional array where the third dimension are the empty vectors at every cell location.

gonewest81803:02:42

Suppose I decide to represent the “constraints” at a cell as keywords, :1, :2, :3, etc.

gonewest81803:02:38

Therefore each of those empty vectors will accumulate up to 8 constraints, at which point the value of the cell is fully determined.

gonewest81803:02:14

To update the constraint at a given cell you use update-in

gonewest81803:02:19

foo.core> (update-in b [0 0] conj :3)
[[[:3] [] [] [] [] [] [] [] []]
 [[] [] [] [] [] [] [] [] []]
 [[] [] [] [] [] [] [] [] []]
 [[] [] [] [] [] [] [] [] []]
 [[] [] [] [] [] [] [] [] []]
 [[] [] [] [] [] [] [] [] []]
 [[] [] [] [] [] [] [] [] []]
 [[] [] [] [] [] [] [] [] []]
 [[] [] [] [] [] [] [] [] []]]

gonewest81803:02:56

Which returns a new board with the constraint added.

gonewest81803:02:28

Update an entire row

foo.core> (reduce #(update-in %1 [0 %2] conj :3) b (range 9))
[[[:3] [:3] [:3] [:3] [:3] [:3] [:3] [:3] [:3]]
 [[] [] [] [] [] [] [] [] []]
 [[] [] [] [] [] [] [] [] []]
 [[] [] [] [] [] [] [] [] []]
 [[] [] [] [] [] [] [] [] []]
 [[] [] [] [] [] [] [] [] []]
 [[] [] [] [] [] [] [] [] []]
 [[] [] [] [] [] [] [] [] []]
 [[] [] [] [] [] [] [] [] []]]
where the #(update-in …) is syntactic sugar for an anonymous function taking two arguments, the first one is the board b, and the other one is the y coordinate to be updated.

gonewest81803:02:16

or similarly can update a column

foo.core> (reduce #(update-in %1 [%2 0] conj :3) b (range 9))
[[[:3] [] [] [] [] [] [] [] []]
 [[:3] [] [] [] [] [] [] [] []]
 [[:3] [] [] [] [] [] [] [] []]
 [[:3] [] [] [] [] [] [] [] []]
 [[:3] [] [] [] [] [] [] [] []]
 [[:3] [] [] [] [] [] [] [] []]
 [[:3] [] [] [] [] [] [] [] []]
 [[:3] [] [] [] [] [] [] [] []]
 [[:3] [] [] [] [] [] [] [] []]]

gonewest81803:02:12

not suggesting you literally use a nested vector, but just to illustrate the idea. constraints are updated by generating the list of locations to be modified, and iterating over those (with reduce in my example) to produce a new board state.

Steve Upstill00:03:39

A nested vector is pretty much what I'm after, so thanks for that. What I hadn't gotten to is update_in, and the fact that it returns a copy of the collection. That's a key pointer (so to speak) for me. Thanks Neil!

Steve Upstill20:02:40

@gonewest818 Yeah, that makes sense. I think you'd still need a queuing mechanism because new constraints will accumulate faster than you apply them...

gonewest81821:02:31

yes, I believe that’s what noisesmith was getting at.

gonewest81821:02:15

but… the “queuing mechanism” might not be much more than a plain old list that you map over. At some level this solver is going to have a loop where it is choosing what’s the next number to place. Placing a number ripples a bunch of constraints (the queue). The resulting board state is used to choose the next number to place, which generates a new queue of changes, etc.

noisesmith21:02:48

right, I was speaking of a queue of changes functionally not implementation wise - and yes a list would work perfectly for that

noisesmith21:02:28

@steve171 also consider that somer operations are much easier to do with the pure functional version - for example you could create a lazy sequence of every possible placment of a number on the board, and use filter to remove the placements that break some constraint

sundarj21:02:26

@steve171 doesn't really help you in writing a functional version, but you might find this logic programming version interesting 🙂 https://gist.github.com/swannodette/3217582

Steve Upstill21:02:28

@noisesmith I think that's an interesting alternative strategy, i.e., what do you do when there are no more numbers to place and the queue runs out?

Steve Upstill21:02:08

@sundarj Thanks for that. I'll check it out. (I must be learning something; my brain hurts!)

sundarj21:02:53

looks like it was inspired by http://norvig.com/sudoku.html

Steve Upstill21:02:30

Oh that's funny. I've followed along with Peter's Scrabble machine, but I didn't know he'd presented a Sudoku solver.

sundarj21:02:54

oh! nice 🙂