Fork me on GitHub
#clojure
<
2017-03-09
>
wei00:03:40

is there core a function for this? (some #(if (pred %) %) coll) basically some but returns the element instead of the predicate result

jr00:03:49

(first (filter pred coll)) ?

wei01:03:08

true, that works. thought there might be a single core function but it’s easy enough to write a helper

josh.freckleton01:03:22

i have some data with a compound key, eg a 2-tuple (:a, :b), and I need to be able to search it for a list of all matches on the first part of the key I can brute force this, eg a normal map with a normal vector as the key, and then search over the whole map. But is there a more efficient way? Or a way to make multiple indexes?

josh.freckleton02:03:14

I'm contemplating juxt for that... or index...

joshjones02:03:15

@josh.freckleton is the existing data used extensively in your system in other places? is the data changed often, or is it mostly being read? and, if the data is a regular clojure map already, is it being stored as an atom, or?

josh.freckleton02:03:16

it's used through a limited boundary, I have cusomt getters/setters it's mostly being read yes, an atom

joshjones02:03:38

two similar approaches would be: 1) have a 'proxy' data structure that is of the form {:a {:b 1 :c 2} :x {:y 42}} for your data {[:a :b] 1 [:a :c] 2 [:x :y] 42}, and then have simple but custom functions that assoc/dissoc/get/update/etc, so that you would do (assoc-compound m [:a :b] 1) and then (get-compound m [:a :b]), but which behind the scenes uses the other structure. This would only be feasible if the use and access of your data were limited to a relatively contained portion of your code. 2) maintain your regular map with the actual compound key, but use the indirection map as above as a separate entity. If your regular map were an atom, it would be easy to add a watch to it, and the watch function would silently update the indirection map automatically when the main data changed. Then, when you wanted to search, search the indirection map.

josh.freckleton02:03:25

hm, I liked your first idea, but then swap!ing into it takes ~30s, (it's a big map)...

joshjones02:03:50

approx how many values in the map total?

joshjones03:03:57

30 seconds to swap?

josh.freckleton03:03:59

yep, i'll copy the code over, it looks like upgrading to sorted-map has slowed things down a bit

joshjones03:03:52

i've sorted maps before, but they were very small and it was only for "display" purposes -- i'm curious why you need to sort such a large map?

josh.freckleton03:03:25

it doesn't take much longer to load the map, and I (naively?) assumed that a sorted map would read quicker

josh.freckleton03:03:50

ah wait, it's fine

josh.freckleton03:03:59

cider was trying to print the whole map after swaping

josh.freckleton03:03:19

i forced the fn that swaps to return nil

josh.freckleton03:03:12

@joshjones thanks for your help, this is running perfectly now!

josh.freckleton03:03:30

oh, and for the record, does sorted-map not run faster?

josh.freckleton03:03:10

i imagined it was a clojure way of saying things were indexed, but now that I think of it, map is a hashmap already, right?

joshjones03:03:55

your map is already a hash map, yes -- if it's a sorted map, changes should take longer, since it has to sort on those changes

joshjones03:03:52

if i were doing this, i'd at least explore adding a watch to the data atom, and you can then run clojure.data/diff on the old and new values, and update your indirection map based on what was added, removed, and changed. it may prove too slow to diff such a large map, but i'd benchmark it and see if the performance penalty is high. It would be a great way to make things transparent

joshjones03:03:47

(add-watch data :unused
           (fn [_ _ prev curr]
             (let [[removed added _] (clojure.data/diff prev curr)]
               (println "removed: " removed
                        "\nadded: " added))))

josh.freckleton03:03:38

interesting, i'll need to check out watches since I haven't used em yet. My perf seems ok right now though...

josh.freckleton03:03:56

I may be able to get by with just this, but i'll definitely keep watches in my back pocket

joshjones03:03:01

this will update the indirection map seamlessly, but of course a performance review on diffing large data is warranted

joshjones03:03:04

(add-watch data :unused
           (fn [_ _ prev curr]
             (let [[removed added _] (d/diff prev curr)]
               (run! (fn [[[a b] _]]
                       (swap! data' #(update-in % [a] dissoc b))) removed)
               (run! (fn [[path v]]
                       (swap! data' assoc-in path v)) added)
               (println "removed: " removed
                        "\nadded: " added))))

joshjones03:03:17

where data' is your indirection map and d/diff is clojure.data/diff

joshjones03:03:47

yeah, it seems to work fine, as long as of course you are using [a b] format for your keys -- anyway, have fun with it!

joshjones03:03:25

clojure rocks

rcolyer03:03:42

I wonder if a book that explains Rich's philosophy and data-oriented programming is needed. Or at least a series of medium articles

josh.freckleton04:03:04

@joshjones thanks for the guidance! clojure does indeed rock 🙂

emboss04:03:26

Hello everyone, Clojure beginner here... I have a hugsql question but since nobody is online there right now, may I ask it here, too?

seancorfield04:03:58

(not sure whether you mean no one is in #beginners or in #hugsql -- I suspect the latter... and I admit I didn't even know there was such a channel! -- and there's also a #sql channel for general SQL-related questions)

bcbradley04:03:04

is it possible to generate a typhint in clojure programmatically?

bcbradley04:03:59

like if i had [Ljava.lang.String; and I wanted to make a type hint out of it

bcbradley04:03:03

what i want to do is generate the type hint metadata from a string

bcbradley04:03:11

or keyword or symbol

emboss04:03:00

@seancorfield Somebody has found me in #hugsql, but thanks for your help 🙂

tbaldridge05:03:35

@bcbradley IIRC you just want ^objects since a string array really isn't a thing on the JGM

bcbradley05:03:21

main(java.lang.String[] args)

bcbradley05:03:03

i'm writing a tool to convert that library into a clojure library

bcbradley05:03:49

i got [Ljava.lang.String; through java reflection via interop in clojure

bcbradley05:03:48

i'd like to automagically have type hints in the library i'm generating, but i need a way to programatically generate type hints

bcbradley05:03:30

if i can't do that, my tool has to change; it would have to output a bunch of files that happen to be clojure code, rather than clojure forms

tbaldridge05:03:43

That really is the better option, imo

bcbradley05:03:47

in other words, i have to go up a level and deal with "strings" as code

tbaldridge05:03:59

outputting .clj files is easier to debug, for what it's worth

bcbradley05:03:18

alright was just wondering if anyone has done something like this before, doesn't hurt to ask 🙂

tbaldridge05:03:21

you get real line numbers in errors

tbaldridge05:03:50

there is a way to do it, but I forget the incantation

bcbradley05:03:05

oooh i think i found what i was looking for https://clojure.org/reference/metadata

pesterhazy15:03:01

When people say EDN is a subset of Clojure, what do they mean? I.e. what Clojure syntax does not conform with EDN?

qqq15:03:25

does (fn [x] (+ x 1)) parse as edn?

pesterhazy15:03:28

ah but #(+ % 1) doesn't

pesterhazy15:03:31

so that's one example

qqq15:03:18

btw, were you the one looking for a decent apple-like keyboard sometime back? if so, what did you get?

qqq15:03:55

the only thing I know about edn is that "read clj data" <-- can be dangerous due to things evaled at read time, and edn resolves that issue

qqq15:03:04

not sure about limitations of edn beyond that

pesterhazy15:03:35

so not the newest incarnation, which is more expensive

pesterhazy15:03:45

happy with the choice

pesterhazy15:03:23

so I think the difference between .clj and .edn is only that dispatch macros like #() (what else?) are not supported by .edn

pesterhazy15:03:13

also regex: #"asdf"

wamaral15:03:43

what about ~@ ?

pesterhazy15:03:52

and #' though #_ and #{} work

pesterhazy15:03:14

so basically you could write all clojure in EDN syntax, but you'd lose some convenient shortcuts like @ for deref or macro characters

bronsa15:03:16

the lack of reader support for regexes means you can't write all clojure in EDN

bronsa15:03:54

(defmacro x [y] (if (instance? java.util.regex.Pattern y) .. ..))

bronsa15:03:14

(x #"..") vs (x (Pattern. "..")) would behave differently

pesterhazy15:03:30

hah you're right

pesterhazy15:03:45

I'm guessing a regex literal is also compiled only once

pesterhazy15:03:36

but it's pretty close

pesterhazy15:03:09

philosophically it's mildly disappointing that reader literals don't all just desugar to forms

pesterhazy15:03:27

@bronsa, are regex literals the only exception?

bronsa15:03:38

between EDN and clj? that i can think of, yes

keymone15:03:11

hi, i’m getting an error that <! is outside of go block for this code: (go (do-something (repeatedly #(<! channel))))

keymone15:03:32

i don’t understand how is that not valid code, can somebody help?

quartz15:03:28

You’re not technically calling <! inside the go block as it is wrapped in an anonymous function

quartz15:03:37

maybe putting the go inside the anonymous function?

keymone15:03:45

oh.. this is not how i understood go block scoping

quartz15:03:21

since you’re using <! inside an anomymous function, nothing guarantees you that that function will be called inside a go block, it might well be not 😛

bronsa15:03:18

go blocks don't cross function boundaries

bronsa15:03:24

it's a lexical transformation

keymone15:03:50

this explains a lot actually

quartz15:03:56

You could just write a manual loop instead of using repeatedly

keymone15:03:29

i’ll do that

bronsa15:03:33

which is also why macros like for don't work inside go blocks, as they wrap the body in a fn

quartz15:03:55

(go-loop [v (<! channel)] (do-something v) (recur (<! channel))

quartz15:03:58

something like that perhaps?

quartz15:03:34

or maybe even write a variant for repeatedly that takes a channel instead of a function 🙂

josh_tackett17:03:14

silly question but having trouble using the clj-fuzzy lib [12:03] Could not locate clj_fuzzy/metrics__init.class or clj_fuzzy/metrics.clj on classpath [12:03] I added to project file and namespace [12:03] project file: ;; Fuzzy String Matching [clj-fuzzy "0.3.3" :exclusions [org.clojure/clojure]] [12:04] namespace [clj-fuzzy.metrics :as fuzzy]

josh_tackett17:03:58

using this lib ^^^

rauh17:03:23

Did you restart the repl?

rauh17:03:22

@josh_tackett Is it in (System/getProperty "java.class.path")?

josh_tackett17:03:49

nah its not in the path @rauh

josh_tackett17:03:53

it shouldn’t need to be

josh_tackett17:03:02

I did what I typically do for all other deps

seancorfield17:03:55

@josh_tackett Posting the exact same question here, just one minute after posting it in #beginners is a bit impatient...

nicoschneider17:03:27

Hello everyone, I’m trying to list markdown files in a directory, under resources/blog, just a flat list of .md files. When developing, I have it working using something similar to (-> “blog” io/resource io/file .list). Unfortunately when I package using lein uberjar and try to run it, I get an java.lang.IllegalArgumentException saying Not a file: jar:file:[…].jar!/blog. I inspected the compiled .jar file, and it contains the blog directory. Any ideas?

hiredman17:03:44

you can't do that

nicoschneider17:03:30

So I have to keep them outside the jar?

nicoschneider17:03:46

(or keep track of them somewhere else)

hiredman17:03:57

the fact that it sort of works sometimes is unfortunate, but turning a resource (arbitrary bytes loaded rom a classloader) in to a file is not something you can generally do

hiredman17:03:09

you also cannot list resources

hiredman17:03:26

it's like a limited key value store

hiredman17:03:51

yeah, so if you want to treat them like files, you'll need to keep them on the filesystem, if you want to treat them like resources you'll need to some up with some kind of registry or something to enumerate them

nicoschneider17:03:24

I’ll just keep them outside, should work better anyway, at least for a blog ^^

rauh17:03:17

@josh_tackett Post your full project.clj

plins18:03:33

hi everyone, I'm trying to wrap my head around clojure.test, but im quite confused. is there a way to run a fixture (to insert and delete stuff inside a database) on ONE SINGLE test (declared with deftest) instead of all tests in the namespace?

tanzoniteblack18:03:21

@plins if you only want it on a single test (or a few random ones, but not all), then call the functions you want directly from the test definition. Fixtures are a helper for when you want to save some extra code by not having to write the same function calls in every test.

plins18:03:32

hmm I see, thks! I'm used to the whole setup teardown stuff 🙂

josh_tackett18:03:03

@rauh :dependencies [[org.clojure/clojure "1.6.0"] [clj-stacktrace "0.2.8"] [clj-time "0.11.0"] ;; JSON [cheshire "5.6.3"] ;; SQL [org.clojure/java.jdbc "0.6.1"] [org.postgresql/postgresql "9.4.1209"] ;; HTTP [clj-http "1.1.2"] ;; Encoding [base64-clj "0.1.1"] ;; Redis [com.taoensso/carmine "2.15.1"] ;; Fuzzy String Matching [clj-fuzzy "0.3.3" :exclusions [org.clojure/clojure]] [environ "1.0.1"] [dire "0.5.3"] [manifold "0.1.0"] [overtone/at-at "1.2.0"]]

hiredman18:03:03

@plins test-vars (called at the repl takes a collection of vars) will run the required fixtures

hiredman18:03:54

lein also can run a single test doing something like lein test your.test.namespace/test-name

sebastjan.pereyro19:03:41

is there are any significant time difference when running clojure and pure java app?

hiredman19:03:00

what do you mean by time difference? performance?

sebastjan.pereyro19:03:25

i'm planning to make live wallpapper for android

sebastjan.pereyro19:03:31

will clojure be slower than java?

hiredman19:03:46

it is super hard to answer that

hiredman19:03:03

if all your app does is call out to other libraries, they are going to be the same. you can write clojure code in such a away as to generate pretty much the same bytecode as javac would, so performance will be the same, and modern jits are very good. But idiomatic clojure is likely to be slower, allocate more than the idiomatic java will. But java isn't automatically fast either, so I dunno

netsu20:03:48

Hi there! Could you suggest me, please, how to split regex into multiple line, something like that:

(def uri-regex
  "RFC URI regex "
  #"^(([^:/?#]+):)?"           ; scheme method
  #"(//(?<host>[^/?#]*))?"     ; authority host domain
  #"(?<path>[^?#]*)"           ; path location
  #"(\?(?<queryparam>[^#]*))?" ; query
  #"(#(.*))?")                 ; resource fragment

netsu20:03:16

But here Too many arguments.

jr20:03:49

re-pattern can take a string and convert to regexp

netsu20:03:40

#"" sytax preferable for me (because of regexp syntax highlighting).

netsu20:03:34

Can it be done by combining #"" parts?

tanzoniteblack20:03:41

@netsu

(re-pattern (str #"(https?)://" #"(.*)")) ;; ==> #"(https?)://(.*)"

netsu20:03:02

nice, thank you again, @tanzoniteblack !

Alex Miller (Clojure team)20:03:03

there’s a clojure lib that does something like this I think

netsu20:03:24

looks nice, thanks. But I made it even simpler:

(def uri-regex
  "RFC URI regex "
  #"^(([^:/?#]+):)?           # scheme method
    (//(?<host>[^/?#]*))?     # authority host domain
    (?<path>[^?#]*)           # path location
    (\?(?<queryparam>[^#]*))? # query
    (#(.*))?                  # resource fragment
   ")

ccann21:03:56

anyone know how to execute a prepared statement (created via jdbc) with korma?

hiredman21:03:28

I don't follow

hiredman21:03:48

PreparedStatement (the jdbc class) has a couple of different execute methods

hiredman21:03:03

you mean execute it and have a bunch of post processing done?

ccann21:03:15

so actually I have a prepared statement and I want to execute it on the same connection as the one created by korma with defdb

ccann21:03:17

I have an UPDATE I need to run that uses .setBinaryStream so I followed the first example here: https://www.postgresql.org/docs/7.3/static/jdbc-binary-data.html

hiredman21:03:52

as far as I know, a preparedstatement can only be executed on the connection that created it

hiredman21:03:14

so if you created a preparedstatement, the only way to execute it is with the connection you created it from

ccann21:03:31

okay, right, then I need to find the reference to the connection that Korma creates

ccann21:03:40

and use it to create the prepared statement

ccann21:03:45

I can’t seem to find the actual java.sql.Connection instance

schmee22:03:40

ccann you might want to try Honeysql + JDBC instead of Korma

schmee22:03:53

it avoids the exact problems you mentioned

schmee22:03:59

by being more explicit

ccann22:03:34

@schmee glad to hear it — I’m actually hoping to move to yesql. Meaning no offense to Korma, of course, it just doesn’t suit our needs

tbaldridge22:03:32

It doesn't suit anyone's needs

tbaldridge22:03:19

It's a library that takes a fairly popular approach from other languages, writing a DSL around data, but that approach doesn't really work well in any language

tbaldridge22:03:48

Even back when I used to do C# we ended up going a route closer to yesql, DSL sql wrappers just don't work.

fellshard22:03:15

The end conclusion is usually that SQL itself is the DSL.

fellshard22:03:55

And attempting to recreate its structure in your language of choice generally doesn't give you benefits compared to crafting queries by hand.

fellshard23:03:19

What I usually see changing are the structures around SQL - parameterizing queries, extracting results, etc. Because JDBC sucks to use. 😐

chillenious23:03:21

I’ve used jOOQ (in Java) for the last couple of years, and that works great for the most part. It’s great to be able to compose your query if you need it. Though I also built a yesql-like tool to deal with the times that the queries got too unwieldy, and in Clojure, yesql definitively seems the way to go.

schmee23:03:59

how do you compose queries in Yesql?

shaun-mahood23:03:29

Don't forget about hugsql - I've not used it much but it's pretty similar to yesql as far as the general approach and is the library that Luminus uses now.

chillenious23:03:45

I’m guessing you don’t compose queries in Yesql, just use variants?

chillenious23:03:15

any pros/ cons when it comes to hugsql vs yesql @shaun-mahood ?

shaun-mahood23:03:38

@chillenious: Good article at https://yogthos.net/posts/2016-02-22-LuminusEmbracingHugSQL.html - about a year old - I haven't used either substantially though, I mainly use JDBC with occasional honeysql