Fork me on GitHub
#clojure
<
2017-01-30
>
ag02:01:12

stupid question (quick search did’t get me anything) how to I access to all function arguments from within the function? Basically looking for an equivalent of arguments object in javascript

eslachance02:01:38

It's like doing argument destructuring in ES6, basically

joshjones02:01:14

@ag -- the vars are bound and without macros, you can't really do that. however, this may give you some direction: http://stackoverflow.com/questions/18797856/get-clojure-argument-list

eslachance03:01:04

Also there are no stupid questions ¯\(ツ)

eslachance03:01:29

I have a question though. Functionally the following are the same, afaict, to get a value within a multi-level hashmap. Is either better, either idiomatically, functionally or performance-wise?

(-> msg :author :username)
(get-in msg [:author :username])

Alex Miller (Clojure team)03:01:34

idiomatically, no. both are common.

Alex Miller (Clojure team)03:01:03

functionally, I’d say basically no

tolitius03:01:25

(-> msg :author :username)
should be faster though

tolitius03:01:38

if that is important of course

tolitius03:01:43

boot.user=> (def m {:a {:b 34 :c {:d 42}}})
#'boot.user/m
boot.user=> (time (dotimes [_ 10000000] (-> m :a :c :d)))
"Elapsed time: 300.658938 msecs"
nil
boot.user=> (time (dotimes [_ 10000000] (get-in m [:a :c :d])))
"Elapsed time: 632.927241 msecs"
nil

Alex Miller (Clojure team)03:01:22

I think there are two reasons for that - get-in reduces over the keys, invoking get on each key where as -> is compiled (via macroexpansion) into the direct series of lookups (:username (:author msg))

eslachance03:01:09

Thank you both for the thorough answer!

eslachance03:01:20

I shall be using -> from now on ^_^

tolitius03:01:07

@eslachance I think they both have a place 🙂

tolitius03:01:18

i.e. -> is a macro so it does not compose

Alex Miller (Clojure team)03:01:23

and the second reason is that the -> will use (:author msg) vs (get msg :author) which is ever so slightly faster

Alex Miller (Clojure team)03:01:41

agreed - get-in is great when you have some code that creates the lookup vector

eslachance03:01:01

Ah yes, doing it programmatically would need the vector

eslachance03:01:05

That's a good point

ag03:01:10

have do I get names of symbols (not values) that passed into function?

ag03:01:00

e.g. this (def foo “foo-val”) (name (quote foo)) works, right?

ag03:01:22

but this (map (fn [e] (name (quote e))) [foo bar]) wouldn’t

ag03:01:40

I guess I need to use some quoting trick

joshjones04:01:55

@ag you need a macro for this. when you call (my-func foo), foo is evaluated before being given to the function. the answer here should show you how to do it, in case you want to go this route. http://stackoverflow.com/questions/41482431/return-concatenated-params-in-clojure/41490018#41490018

sveri08:01:09

@beppu awesome, I was looking at the generated API: http://clj-time.github.io/clj-time/doc/index.html and it does not have that method. Its a bit of a pity. Anyway, thats what I need, thanks

karol.adamiec11:01:24

how can i remove all keys from a nested map? i.e. i want to strip away all keys == :db/id. I was thinking about postwalk, but have problem with coming up with how to tell it to remove the keys...

artur11:01:02

keys with values or just strip away the keys?

bronsa11:01:28

user=> (def x {:foo 1 :bar 2 :baz {:foo 1 :bar {:foo 2}}})
#'user/x
user=> (w/postwalk (fn [x] (if (:foo x) (dissoc x :foo) x))  x)
{:bar 2, :baz {:bar {}}}

pgmcgee12:01:52

i’m not sure i understand this:

pgmcgee12:01:03

`user=> (= (concat "Abc: " nil) "Abc: ") false`

pgmcgee12:01:20

how do i get that value to be true?

moxaj12:01:42

@pgmcgee concat returns a sequence, while "Abc: " is a string

moxaj12:01:32

either do (seq "Abc: ") or (apply str (concat "Abc: " nil))

pgmcgee12:01:56

oh, derp derp, it looks like i can also use (str “Abc:” nil) in this case

pgmcgee12:01:00

thanks so much!

mindenaaron13:01:01

@moxaj Thank you very much!! parrot

pesterhazy14:01:53

Watching @plexus's latest episode on defrecords (https://lambdaisland.com/episodes/defrecord_defprotocol), it struck me that I've seen reader literals for defrecords used only rarely - in fact I forgot about their existence.

pesterhazy14:01:24

I mean something like this (from the transcript)

#ep24defrecord.core.Book{:title "Iain M. Banks"
                           :author "Consider Phlebas"
                           :year 1987}

pesterhazy14:01:10

What are those reader literals useful for?

bronsa14:01:49

serializing/deserializing record instances

pesterhazy14:01:26

ah because the records are automatically printed as literals

pesterhazy14:01:51

so basically you can easily serialize those literals to EDN or transit?

pesterhazy14:01:03

as a side node this works in a Clojure repl but not in lumo

(do (defrecord Foo [name age]) (cljs.reader/read-string (pr-str (->Foo "Joe" 92))))
Error: Could not find tag parser for cljs.user.Foo in ("inst" "uuid" "queue" "js")

bronsa14:01:47

no idea what lumo is

pesterhazy14:01:33

@anmonteiro's self-hosted clojurescript repl

bronsa14:01:45

but I don't think cljs.reader implements type reader literals

pesterhazy14:01:25

so "type read literal" is the concept I was missing

pesterhazy14:01:10

>>> Calls to Java class, deftype, and defrecord constructors can be called using their fully qualified class name preceded by # and followed by a vector

pesterhazy14:01:36

so this sounds as if this would work with regular Java classes too

pesterhazy14:01:52

#java.util.Date[0]
#inst "1970-01-01T00:00:00.000-00:00"

theblackbox14:01:14

hmm... not seen the lambda island before.... is it worth it?

bronsa14:01:44

@pesterhazy it does, it's just that record use that as their default printer while other instances use #<Klass instance@hash>

pesterhazy14:01:13

@bronsa,

#java.util.Random[]
#object[java.util.Random 0x73600add "java.util.Random@73600add"]

bronsa14:01:50

ah yeah, that's the new readable printer

pesterhazy14:01:51

so it's `#object[Klass hash "Klass@hash"] ?

bronsa14:01:06

since 1.7 IIRC

bronsa14:01:28

I forgot about it because I monkey patched it to work as before in my local repls

bronsa14:01:37

too noisy :)

pesterhazy14:01:39

#object can't be read though (No reader function for tag object)

bronsa14:01:46

it's readable

pesterhazy14:01:08

what's readable as opposed to "can be read"?

bronsa14:01:08

if you define a tagged reader for object then supposedly you can make something useful out of it

bronsa14:01:15

it can't be read by default

bronsa14:01:22

but it's just a tagged reader away

pesterhazy14:01:25

ah I get the distinction

bronsa14:01:31

which is unreadable

pesterhazy14:01:36

it's readable in the sense of potentiality, not an actuality

pesterhazy14:01:11

it's kinda cool what you can uncover

bronsa14:01:26

btw the last item I think is just the toString representation of that instance

bronsa14:01:34

[class, hash, tostring]

pesterhazy14:01:09

@theblackbox to your question, I can wholeheartedly recommend lambda island, I've been a subscriber from the beginning

pesterhazy14:01:24

I've subscribed since the beginning and it's some of the best information you can find, for beginners to intermediates (with some advanced stuff sprinkled in). Disclaimer: I'm a friend so potentially biased

theblackbox14:01:53

cool, good to know... I'll have a look see

pesterhazy15:01:48

Speaking of which, can anyone recommend a great book on Java?

tbaldridge15:01:27

Java is a pretty big topic, what are you looking into

pesterhazy15:01:29

I'd love to learn about advanced topics

pesterhazy15:01:36

intermediate to advanced I guess

pesterhazy15:01:04

memory model, concurrency, performance, GC

tbaldridge15:01:22

This is pretty much the final word on concurrency (and memory to some extent): https://www.amazon.com/Java-Concurrency-Practice-Brian-Goetz/dp/0321349601

mrchance15:01:38

> Original Cotton Rope Hammock with Stand 😂

pesterhazy15:01:17

"The Java™ Virtual Machine Specification" ... not sure if I'm prepared to go there yet...

schmee15:01:08

pesterhazy I found this book extremely helpful in my early days of programming: https://www.amazon.com/Effective-Java-2nd-Joshua-Bloch/dp/0321356683/

pesterhazy15:01:53

got all of the above. Used books are so affordable 🙂

theblackbox16:01:11

hello guys, I'm struggling to pick my way through the various concurrency methods in an attempt to debug my code. I believe I'm in a race condition whereby a process is kicking off before a doseq has finished initialising various stuff and things so I would like to block until I know initialisation is complete. Where should I be looking? Futures look most likely?

7h3kk1d16:01:13

Futures do allow you to block if that’s what you’re asking

joshjones16:01:15

what “process is kicking off” are you referring to?

theblackbox16:01:10

so I'm using Clojure to implement Kafka Streams using interOp =/

theblackbox16:01:12

I have my "topology" built by one process and my thinking is that the error I am currently getting means that I am calling "start()" before the topology has been initialised

joshjones16:01:58

this process that builds your topology — you are calling it how?

theblackbox16:01:00

using "thread first"

theblackbox16:01:23

sorry this is literally my first week with Clojure so I may not be using any of the words correctly 😉

masonc16:01:42

@theblackbox Is it possible to post the relevant code portion?

theblackbox16:01:45

so I'm trying to break out the "process" method so that I can throw as many predicates at it as I need and it should implement a stream for each

theblackbox16:01:01

then it should start but I just get the error: "Exception in thread "StreamThread-1" java.lang.IllegalStateException: Consumer is not subscribed to any topics or assigned any partitions"

theblackbox16:01:04

which is exactly what the process method should be doing

masonc16:01:24

Got it. Admittedly, I'm not well versed in Kafka. But I'll take a look and see if anything is glaringly off.

joshjones16:01:43

from what i can tell, (doseq [predicate model/all] process) .. is not doing what you think it should be doing.

theblackbox16:01:53

more than likely

theblackbox16:01:13

as in when I use a single predicate - it works

joshjones16:01:25

you want:

(doseq [pred model/all]
  (process pred))
… i think

joshjones16:01:11

assuming model/all is a vector of predicates

theblackbox16:01:13

so yeah, if it is implemented like that using the single predicate, it works as anticipated

joshjones16:01:36

(doseq [predicate model/all] process) … evaluates to nothing useful. you’re not calling process like you seem to want to do. try the above.

theblackbox16:01:50

@joshjones that seems to get me further, cheers

ghadi17:01:10

@theblackbox might want to use the .. macro instead of ->

ghadi17:01:44

(.. builder (stream input-topic) (map kvmapper) etc)

theblackbox17:01:29

sorry what's the advantage there? or is it rtfm?

masonc17:01:41

I think it's a readability thing.

theblackbox17:01:55

cool, I'll look into it

masonc17:01:16

From the doc: (.. System (getProperties) (get "os.name")) expands to: (. (. System (getProperties)) (get "os.name")) but is easier to write, read, and understand.

masonc17:01:59

It may get a bit awkward with the length of your chain though.

nwalkr17:01:09

hello guys. can someone enlighten me how to implement pretty standard pattern “worker pool with bounded task queue” in clojure? i’ve already got ztellman/manifold in my project and it will be pretty cool if it will fit.

tbaldridge17:01:59

that's pretty much exactly what core.async was designed to do

nwalkr17:01:27

ok, i’ll take a look

nwalkr17:01:56

@tolitius i’ll try it too. it seems to better fit my case out-of-box.

danburton18:01:46

Does lein test run tests in parallel by default?

danburton18:01:04

But regular un-pluginned lein doesn't, right?

danburton18:01:31

Trying to figure out why a test is failing, looks like things are running in parallel when we don't want them to.

pesterhazy18:01:01

try adding println at the beginning and end of tests to see if your hypothesis is right 🙂

tanzoniteblack18:01:03

lein test doesn't run in parallel by default

pesterhazy18:01:12

I also suspect it's not lein test

tanzoniteblack18:01:29

but that doesn't mean that your code's not running in the background because one of your tests kicked off some background process by accident

tanzoniteblack18:01:27

which is really easy to do if the code your testing has a lot of future or core.async code in it

dmillett19:01:11

If anyone is interested, I am trying initialize an open source project that facilitates building campaigns for public office in a transparent and less costly manner. There are more details in the #political-canvas channel

csm20:01:04

howdy, I’m trying to get single-writer, multi-reader broadcast working in core.async; I tried using mult and tap, but that seems to turn the write side into a dropping buffer

tbaldridge20:01:53

don't think so, but the mult does't remember past values, so it's best to setup your taps/mult and then start putting in values

tbaldridge20:01:10

if you post some code, we can probably give you better advice

csm21:01:16

My writer code is almost literally (alt! [[ch value]] :sent (timeout to) :timeout), and right now the read side is (alt! ch ([v] v) (timeout to) :timeout)

csm21:01:48

what I was after is having multiple readers receive a value when sent, and to have the writer time out if no-one is reading

csm21:01:59

are pub and sub the things to use instead? I was going to study them next

tbaldridge21:01:03

@csm pub/sub is basically mult/tap but with topics. So you can dispatch to only certain channels based on the "topic" of each message

nwjsmith21:01:09

Where would be a good place to ask a question about clojure.java.jdbc?

nwjsmith21:01:04

Awesome. So here’s a problem I’m having. Running this:

(jdbc/query db [”SELECT my_table.* FROM my_table WHERE my_table.id = ?” id])
Results in:
[{:id “someid”}]

nwjsmith21:01:31

What I would like is for it to return:

[{”my_table.id” “someid”}]

nwjsmith21:01:51

By default clojure.java.jdbc will “uniquefy” column names by appending “_N” to it, but I need to be able to prepend the table name to the column name

7h3kk1d21:01:57

You may need to do that in sql.

7h3kk1d21:01:08

not sure though.

pesterhazy21:01:21

usually best not use * at all

pesterhazy21:01:51

can't you use my_table.id AS my_table.id ?

nwjsmith21:01:14

Nah, that’s not valid SQL (the alias can’t have a period in it)

pesterhazy21:01:33

then use another character and replace? 🙂

pesterhazy21:01:53

it's hard to advise without knowing the use case

pesterhazy21:01:27

this may be to do with the JDBC driver as well, not clojure.java.jdbc per se

leov21:01:54

hihi. is it ok if I use one folder for cljc, clj and cljs?

pesterhazy21:01:56

@leov, yeah I don't see why not

dpsutton21:01:58

i think you can give the jdbc stuff a function to run on your keys afterwards

dpsutton22:01:11

Usage: (query db sql-params)
       (query db sql-params opts)
Given a database connection and a vector containing SQL and optional parameters,
perform a simple database query. The options specify how to construct the result
set (and are also passed to prepare-statement as needed):
  :as-arrays? - return the results as a set of arrays, default false.
  :identifiers - applied to each column name in the result set, default lower-case
  :qualifier - optionally provides the namespace qualifier for identifiers
  :result-set-fn - applied to the entire result set, default doall / vec
      if :as-arrays? true, :result-set-fn will default to vec
      if :as-arrays? false, :result-set-fn will default to doall
  :row-fn - applied to each row as the result set is constructed, default identity
The second argument is a vector containing a SQL string or PreparedStatement, followed
by any parameters it needs.
See also prepare-statement for additional options.

dpsutton22:01:17

specifically, the :identifiers

dpsutton22:01:38

you can transform your column names however you like

7h3kk1d22:01:56

You still wouldn’t know the table names though right?

dpsutton22:01:43

his query has the table name in it

dpsutton22:01:47

so presumably he knows it

7h3kk1d22:01:12

if that’s the case can’t he just wrap the returned value?

dpsutton22:01:30

(jdbc/query db ["SELECT my_table.* FROM my_table WHERE my_table.id = ?" id]) is his example, so prepend the known table name?

dpsutton22:01:50

@nwjsmith did you see that documentation above?

nwjsmith22:01:43

I do, but I don’t think that will quite do it

nwjsmith22:01:32

I’m trying to write a function that takes any result set and transforms it into a normalized map structure in memory

nwjsmith22:01:51

It won’t have knowledge of the query, but it could have knowledge of the schema

nwjsmith22:01:51

I’m just surprised you can’t hook into the mapping of ResultSet -> seq of maps translation the way I want to

nwjsmith22:01:03

I essentially need to replace clojure.java.jdbc/result-set-seq with my own function

7h3kk1d22:01:52

Does the java ResultSet return the table names?

ghadi22:01:05

you can hook into this with some of the lower level things in java.jdbc

ghadi22:01:34

clojure.java.jdbc/db-query-with-resultset

ghadi22:01:19

keep in mind transformed columns could possibly not have a table name

ghadi22:01:59

but like @dpsutton said -- you already know the table name a priori so you might as well use it

7h3kk1d22:01:02

You can probabluy use the metadata-result stuff?

nwjsmith22:01:41

So I think that clojure.java.jdbc/db-query-with-resultset

nwjsmith22:01:45

will do what I need

7h3kk1d22:01:23

lol, I tried.

thomas.williams23:01:28

Hey all, so I have an array of objects, and they are a subset of the overall data, so I want to assign them their proper ids (shift by some offset). So, I assume the best way is to convert it into a map right? If so, I cannot seem to figure out how to convert an object from an array to a map.