Clojurians
#clojure
<
2016-03-30
>

This page is not created by, affiliated with, or supported by Slack Technologies, Inc.

fasiha02:03:44

@josh.freckleton: I didn't use ring-transit for a very pedestrian reason: when I used it, it would try to parse some requests as transit as well, which was making compojure catch on fire, and I couldn't readily figure out how to make that middleware apply to some (not all) routes. I know, cargo-culting, but ring-middleware-format was smarter about only encoding the responses I wanted (inside a :body slot, per the gist), so I went with that…

josh.freckleton02:03:38

@fasiha: Thanks for the response. So, wouldn't compojure *not* apply ring-transit for things that don't signify they're content-type is transit? Would that not be your solution?

fasiha02:03:19

@josh.freckleton: you may very well be right—I see that the cljs client code does specify Accept: application/transit+json, */* in the request, and it's very possible I learned about that after I stopped using ring-transit and started using ring-middleware-format, and the former might have done the right thing if I'd had that request header.

zcaudate08:03:52

when would the :loops field get filled?

zcaudate08:03:18

i tried (analyse '(loop [] (recur)))

zcaudate08:03:52

but I didn’t see a :loops field on the results

bronsa08:03:02

@zcaudate: the annotate-loops pass is no longer run by default

bronsa08:03:46

@zcaudate: if you need :loops, you'll have to schedule #'clojure.tools.analyzer.passes.jvm.annotate-loops/annotate-loops along with the default passes

zcaudate08:03:46

@bronsa: I’m not sure of the purpose of the :loops tag. does the analyser predict how many times a loop might run?

bronsa08:03:14

@zcaudate: not how many, but which loops might cause an expression to recur. e.g. in (loop <a> [] (loop <b> [] (println "foo") (when some-cond (recur))) (when some-cond (recur))) (println "foo") might be re-evaluated because of loop <b> recurring or loop <a> recurring

zcaudate08:03:13

ah I see… so println will get a tag :loop [<loop-id>]

bronsa08:03:37

@zcaudate: if you don't understand the purpose of :loops chances are you don't need it :simple_smile: it's currently only used/needed by a complex analysis pass that deals with locals clearing

bronsa08:03:43

yes, exactly

zcaudate08:03:10

@bronsa: yeah… I’m designing a mini workflow language that uses a micro-set of clojure

zcaudate08:03:42

so I was looking at the output of the analyser to get some ideas :smiley:

zcaudate08:03:33

thanks for that! and yes… you’re right… I don’t need it… for now anyways

dm309:03:01

Is there a reason why (read-string "a/b/c") is OK, while (clojure.tools.reader/read-string "a/b/c") fails with Invalid token?

hiredman09:03:33

there is a ticket to fix read-string

dm309:03:07

so the correct behaviour is to fail?

dm309:03:31

thanks, seems like a breaking change :simple_smile:

hiredman09:03:51

the docs have precluded symbols like a/b/c for some time, and the behavior of how those unspecified symbols were read apparently changed at some point

zcaudate09:03:07

@hiredman: seriously. I’m really peeved about that because I’ve been using :a/b/c keywords for a while… even wrote a whole freaking library to deal with that http://docs.caudate.me/hara/hara-string.html#api---path

zcaudate09:03:40

and now they are taking it out

zcaudate09:03:42

i’m of the opinion that the ::foo/baz keywords should be taken out first

zcaudate09:03:09

user=> (require '[clojure.walk :as walk])
nil
user=> ::walk/hello
:clojure.walk/hello

zcaudate09:03:30

that causes way more problems

zcaudate09:03:43

especially with analysers

zcaudate09:03:19

@dm3 if there’s really a problem, you can patch it:

dm309:03:23

yeah, would have to patch cljs.tools.reader too unfortunately :confused:

dm309:03:32

think I'll just work around that

bronsa09:03:53

@zcaudate: ::foo/bar style keywords are in by design and not going anywhere, :foo/bar/baz have always been invalid by the spec and undefined behaviour

bronsa09:03:13

@dm3: is changing undefined behaviour a breaking change? :simple_smile:

dm309:03:50

breaking as in breaking people's code :simple_smile:

dm309:03:58

e.g. zcaudate

bronsa09:03:38

that code is already broken if it's using invalid clojure. It's just accidentaly working

dm309:03:42

I'm looking from a pragmatic perspective. Theoretically you're right :simple_smile:

dm309:03:08

and I'm not judging either

bronsa09:03:08

pragmatically, :foo/bar/baz is a bug waiting to happen. what does (namespace :foo/bar/baz) return?

dm309:03:38

whatever it returns currently?

dm309:03:03

I mean it's kind of defined by the implementation

sveri09:03:59

@dm3 @bronsa I wouldnt even agree that you are theoretically right. As soon as enough people adapted the broken code it falls under something like a common law that was accepted by both parties for a long enough time.

bronsa09:03:10

what about namespace on (keyword "foo/bar" "baz") and (keyword "foo" "bar/baz")

dm309:03:00

I agree that currently implemented semantics are messy

dm309:03:19

but my point was that it's still a breaking change

dm309:03:27

not that it's a "bad" change

dm309:03:34

that's a judgement

bronsa09:03:52

@sveri: I would agree with you, as long as the undefined behaviour we accept as defined doesn't cause impossible to fix semantics.

bronsa09:03:09

that's why for example, the patch that made symbols starting with numbers illegal was rolled back

bronsa09:03:11

it broke existing code, it didn't cause weird semantics so it was rolled back. not the case with :foo/bar/baz

bronsa09:03:43

@dm3: you could make the point that fixing any bug is a breaking change then -- people might be relying on that bug.

dm309:03:21

yep, I guess what matters is how obvious the incorrect behaviour is and how many people rely on it

bronsa09:03:32

if the doc explicitely says "you can use one / inside a symbol", then if you're using more than one you're writing invalid clojure and you should expect it to maybe break

dm309:03:18

I really haven't even thought about multiple slashes (nor noticed the docs) in a symbol in ~3 years of using Clojure

dm309:03:37

my initial thought (today) was that it was permitted

dm309:03:48

and the namespace would be the first segment before the first slash

bronsa09:03:19

well, that doesn't make much sense though. / in clojure means namespace separator. if I see FOO/BAR, no matter what FOO and BAR are, I know that FOO is the namespace, and BAR is the name. if you want to express paths with keywords as in @zcaudate's lib, you should use a different separator in your keywords that doesn't have a special meaning in clojure, like . (i.e. :foo/bar/baz -> :foo.bar.baz or :foo/bar.baz)

dm309:03:48

I do not want to argue semantics. Just sharing one point of view

bronsa09:03:59

and my point is that pragmatic point of views (especially when they go against the current doc) should only be considered if the semantics they imply are clear and unambiguous

sveri09:03:48

@bronsa: Nice explanation, thank you :simple_smile:

dm309:03:52

yep :simple_smile:

dm309:03:03

I agree to that, as you have to make decisions in the end

slotkenov12:03:47

I there a library to proxy a server request to another server?

slotkenov12:03:27

@nonrecursive: thanks, the streaming-proxy seems easy to set up!

dev-hartmann12:03:48

@nonrecursive: nice to see you around, just wanted to saythanks for clojure for the brave and true

zcaudate13:03:59

@bronsa: written form of communication has a way of making things more serious than they seem

zcaudate13:03:28

honestly… i knew it was coming since 1.6 when the edn reader started breaking my code

zcaudate13:03:08

it’s probably more my fault for not communicating this earlier but oh well.. we all have to roll with the times

bronsa13:03:55

@zcaudate: yeah no worries, I was just using your lib as an example since you brought that up

zcaudate13:03:27

having said that, you can imagine my disappointment because I had designed an entire query semantic based on the keyword :foo/bar/baz feature (now bug)

zcaudate13:03:53

you noticed I didn’t use (adi/select ds {:student/classes/teacher/name "Mr. Blair"}})

zcaudate13:03:07

in my docs because the tests started breaking

jstew13:03:22

@zcaudate: You put out so much quality stuff that I wonder if you ever sleep!

bronsa13:03:37

@zcaudate: luckly the fix should be easy :simple_smile: just replace / with .

zcaudate13:03:10

see the problem is… datomic has things like account.type/user

zcaudate13:03:34

and so I would have to do the cljs thing account.type$user

bronsa13:03:48

(that's some high quality documentation btw, good job)

zcaudate13:03:28

@bronsa: hahaha thanks… so maybe you can push the fix to 1.10

zcaudate13:03:46

that way I can get a few more months left

zcaudate13:03:49

like it’s not a big deal… but I thought that there is a parallel between the path structure of the / calls and the nesting of maps

zcaudate13:03:54

and so there is an equivalence to {:student {:classes {:teacher {:name '(?fulltext "Blair")}

zcaudate13:03:05

and {:student/classes/teacher/name "Mr. Blair”}

zcaudate13:03:19

which is prettier in my opinion

bronsa13:03:47

@zcaudate: sorry if that wasn't clear, but I don't actually have any control over when or what gets into clojure or not, I'm just a contributor :simple_smile: so there are chances that the clojure/core team will take a different decision and actually decline that ticket (I would be really disappointed if that was the case though!). If that will happenI will obviously make a change to tools.reader to allow them aswell,

zcaudate13:03:37

@bronsa: damn.

zcaudate13:03:07

well… maybe you can highlight this fact

zcaudate13:03:32

and also if the fix is made, a fix to (keyword “foo/bar/baz”) will also be needed

bronsa13:03:16

don't think that'll ever be done. validating inputs to keyword/`symbol` etc has been asked/discussed tons of times and repeatedly declined for performance reasons

zcaudate13:03:45

so that’s a matter of consistency.

bronsa13:03:52

(not that I agree with that decision, but it seems like Rich isn't going ot change his mind on that)

bronsa13:03:41

@zcaudate: there's a difference between what a symbol/keyword can be at runtime, and what a valid read-time symbol/keyword is

zcaudate13:03:51

and also, it means I can setup a reader macro #k foo/bar/baz and get the same effect

zcaudate13:03:20

like it’s stupidly ugly but i believe it will work

bronsa13:03:16

but the ambiguity of what to do with namespace and name still remains so dunno

bronsa13:03:54

@zcaudate: that wouldn't work either way, if http://dev.clojure.org/jira/browse/CLJ-1530 gets accepted neither :foo/bar/baz nor foo/bar/baz will be valid anymore

bronsa13:03:16

@zcaudate: btw I'd suggest you log your issues with that ticket in a comment there if you feel strongly against it

bronsa13:03:51

I suspect that the response will be "you should use a delimiter that doesn't have a special meaning in clojure", but I might be completely wrong (I find the core team doesn't agree with my opinions quite frequently :) ) especially if you point out that your library will break.

zcaudate13:03:42

@bronsa: thanks for the heads up. I’ll leave a comment and add a prayer for the bdfl

bronsa13:03:51

@zcaudate: thanks for that! I just edited your comment wrapping the discussion in a {quote} block for readability

zcaudate13:03:55

@bronsa: sweet :smiley: it looks much better

anmonteiro13:03:21

I'm curious whether people use #'private-fn in tests to test private functions

anmonteiro13:03:04

I feel like I shouldn't be doing it, but it's useful in some use cases

zcaudate14:03:40

@anmonteiro: all the time...

zcaudate14:03:02

the end justifies the means (in this case)

zcaudate14:03:01

another option is to put all the private functions in a sub namespace and make them public. The sub namespace is only used by the main namespace and so there is less noise and you can test easier too.

zcaudate14:03:02

@anmonteiro: but yeah… i don’t think what I do is standard practice so you may want a second opinion

anmonteiro14:03:49

:simple_smile:

bronsa16:03:03

@zcaudate: @anmonteiro the .impl namespace is also done by libraries like core.async so I'd say that's a good sign that it's good practice

timgluz16:03:24

Does anyone know how i could create a instance of userIndex by using Clojure interop

Collection<U> users = /// some collection

FastUserIndex<U> userIndex = new SimpleFastUserIndex<>() {
{
    users.forEach(u -> add(u));
}
}
here’s javadoc: http://ranksys.org/javadoc/es/uam/eps/ir/ranksys/fast/index/SimpleFastUserIndex.html

bronsa16:03:16

I'd do something like (reduce (fn [^FastUserIndex user-index user] (doto user-index (.add user))) (SimpleFastUserIndex.) users)

bronsa16:03:01

or (reduce #(doto ^FastUserIndex % (.add %2)) (SimpleFastUserIndex.) users) if that's too verbose

timgluz16:03:58

Yes, the constructor of SimpleFastUserIndex is a protected method - Java version works, but for clojure i get “No matching ctor"

bronsa16:03:20

you're out of luck then

timgluz16:03:38

that’s what i thought

timgluz16:03:52

thanks anyway

bronsa16:03:08

don't know off the top of my head if gen-class supports protected methods but I would not use it in this case even if it did

bronsa16:03:25

I do have a clojure fork implementing defclass and extend-class special forms and wrapping macros (more general than deftype and reify) that would work in this case -- but it's unlikely going to be accepted into core so I never bothered opening a ticket about that

richiardiandrea16:03:15

Hello everybody, we are planning to give a training in San Francisco area in the imminent future and would like to kind of survey the topic to be effective

richiardiandrea16:03:50

I don't know if this is the best place to ask actually, maybe there is a more suitable another channel

richiardiandrea16:03:21

ok I moved to #C0KQRPPBP

base69818:03:17

Anyone know how to execute batch with jdbc clojure?

base69819:03:44

Anyone know who maintains clojure jdbc?

hiredman19:03:15

base698: have you looked at the source, you can just grep for executeBatch and there are plenty of hits

base69819:03:49

it looks like it does it by default. I can't see the errors coming back and jdbc/insert! don't work right with PGSQL.

base69819:03:12

schema I'm using has Mixed case table names and it won't escape them

base69819:03:36

Filed that bug ^

hiredman20:03:06

by pgsql do you mean postgres?

base69820:03:50

Korma did it by default I believe

base69820:03:33

(j/execute! pg-db ["select 1 + ?" 3])

base69820:03:38

anyone know how to get that work?

hiredman20:03:16

I would add some more repro details to the issue

hiredman20:03:43

or double check that it is actually happening, since postgres pretty much doesn't care about case in table names

base69820:03:49

It definitely does case about case, if you do: select from SomeTable; It gets interpreted as select from sometable;

base69820:03:05

so if your table is actually SomeTable it fails

base69820:03:11

care about case%

base69820:03:46

create table "Foo" (bar text);

base69820:03:01

you have to create it with the quotes

base69820:03:48

# select * from Foo; ERROR: relation "foo" does not exist

base69820:03:32

@hiredman: ^

hiredman20:03:57

I saw, gross

base69820:03:10

and if you are wondering... yes it's awful to live with this schema :simple_smile:

hiredman20:03:54

have you tried using pre-quoted strings instead of keywords for table names?

hiredman20:03:05

"\"FooBar\""

base69820:03:06

no, but that's brilliant

base69820:03:44

yeah, that works

seancorfield20:03:58

java.jdbc supports :entities quoting-strategy as part of the API.

seancorfield20:03:15

That allows you to tell java.jdbc how to quote entities in SQL.

seancorfield20:03:42

For MySQL we use

:entities (jdbc/quoted \`)

seancorfield20:03:32

So then java.jdbc generates

select * from `foo
`

seancorfield20:03:10

For SQL Server, you can use

(quoted [\[ \]])
to generate [foo] in the SQL.

seancorfield20:03:58

(not just about case sensitivity — you need to quote entities if they would conflict with SQL reserved words too)

base69820:03:22

@seancorfield: Where do you put the :entities keyword?

base69820:03:50

Anyone have an example for execute-batch? The docs aren't doing it for me. I'm using insert! and that seems to be working great, except that the 300k insert statements take many minutes

hiredman21:03:15

base698: are you running the insert! once for each item?

base69821:03:22

Yeah, trying this now: (apply j/db-do-prepared pg-db

hiredman21:03:50

no, just apply insert!

base69821:03:19

is there an example somewhere?

base69821:03:01

that looks handy

base69821:03:41

cool, so my clojure code is about 10 times faster than the python code by doing that. Going to go demo it

base69821:03:47

:simple_smile: thanks for your help

base69821:03:56

jdbc is way better than korma

base69821:03:22

this thing did process in like 17 hours, it's down to like 2 minutes in clojure.

seancorfield21:03:28

@base698: did you figure out where to put :entities (quoted \")?

seancorfield21:03:47

(it just goes at the end of the argument list in the call)

base69821:03:25

I didn't I just quoted everything manually. Good to know

seancorfield21:03:15

Has examples of nearly everything — and it’s community-contributable!!

seancorfield21:03:41

Also on the DDL page it shows how to use :entities with create-table and drop-table

base69821:03:26

@seancorfield: Thanks! Did you used to host a clojure meetup in SF?

base69822:03:03

What's a good source project example for doc strings/documentation

hiredman23:03:25

docstrings are such a subjective thing, I really don't know, I think I tend to favor terseness because if I really want to know I read the source

hiredman23:03:42

there are a few different projects for generating html docs if that is more what you are looking for, I've used https://github.com/weavejester/codox and it seems nice

hiredman23:03:52

I think that is approaching 1:1 lines of docstrings to lines of code

zcaudate23:03:01

@base698: i really like honeysql

zcaudate23:03:41

it makes sql statements composable

hiredman23:03:59

the nice thing about honeysql, is it separates the dsl for generating and composing sql, from executing sql, so you can use honeysql to construct your sql queries, and then use java jdbc to run them

zcaudate23:03:31

and on the topic of documentation… I’ve been dogfooding this for a while now https://www.youtube.com/watch?v=3MIaucjfJcE

zcaudate23:03:33

lein hydrox import will pull in the docstrings. lein hydrox purge removes them

ghadi23:03:21

Amen @hiredman

base69823:03:40

So tesser was generated from codox?

hiredman23:03:01

uh, actually I haven't checked, but I am pretty sure it was, it looks exactly like codox

ghadi23:03:04

Not many libs exist that don't conflate query execution and query assembly

ghadi23:03:43

in any language

hiredman23:03:56

I used it on a few smaller personal projects

hiredman23:03:23

(codox, not tesser, unfortunately)

zcaudate23:03:12

@ghadi, @hiredman: yeah… i don’t know why people still work with strings

ghadi23:03:56

I'm gonna harp on this at Clojure/West a bit

ghadi23:03:21

Doing a talk on parsers, regexes are the same way - string "composition"

ghadi23:03:50

Datomic query got it sooo right

hiredman23:03:28

well, there is always going to be some kind of lag between when feature X is added to your favorite database and when you will be able to use it from some library

zcaudate23:03:34

@ghadi: won’t be able to make it but I’ll look forward to the vids

zcaudate23:03:04

pegs have always been a mystery to me

ghadi23:03:22

How so? Genuinely curious

zcaudate23:03:07

There are alot of strategies out there and there is so much to learn just to understand how to parse text

zcaudate23:03:37

I was always looking for a one page summary =0

ghadi23:03:39

Strategies being implementation strategy?

ghadi23:03:05

Yeah -- that's the library writer's problem, not the user ;)

ghadi23:03:46

Execution semantics are really nice - it matches in one way or not at all, no ambiguous parses

zcaudate23:03:01

well… when we use something without understanding it… there is an element of magic about it

ghadi23:03:12

I find that .... wait for it ... "simple"

ghadi23:03:38

I hope I can demystify it!

zcaudate23:03:09

like I was trying to explain the immutable datastructure the other day… “it looks like a vector… but it’s actually a tree"

ghadi23:03:19

On the other hand millions of people use regexes without knowing how they work

zcaudate23:03:50

no, so it’s always best to hear it from the people who know

zcaudate23:03:14

because then they can talk about alternatives

zcaudate23:03:52

and by exposing the underlying data, it gives a clue as to how something is implemented

zcaudate23:03:06

and the thought processes behind the design

zcaudate23:03:43

@base698: the reason why I chose to write my own documentation tooling instead of using codox is because I wanted to write prose and to be able to configure it the way I want it to look: http://docs.caudate.me/adi and http://docs.caudate.me/hara are completely generated…

zcaudate23:03:36

there are certain directives that take a namespace and expose it’s docstrings. i.e: http://docs.caudate.me/hara/hara-string.html#api---case is generated from only one line: https://github.com/zcaudate/hara/blob/master/test/documentation/hara_string.clj#L26