Fork me on GitHub
#clojure
<
2017-07-03
>
hackeryarn01:07:14

I am trying to test a java.sql.SQLException handler which unwraps the exceptions like below. However I'm not sure how I would throw this exception in a test.

(-> e
           (.getNextException)
           (.getMessage)
           (.startsWith "ERROR: duplicate key value"))
current mock (`.getNextException` returns nil on this):
(throw (SQLException. "ERROR: duplicate key value"))

armed05:07:45

Hey, clojurians. I’m using yesql in my project to query postgres database. Some tables has boolean columns ending with question mark. How to properly use queries like this with yesql:

select name, email from user_accounts where "activated?" = true;
Seems yesql thinks that question mark is param placeholder and fires error.

tatut07:07:31

armed: you may be interested in my fork https://github.com/tatut/jeesql

armed07:07:14

@U11SJ6Q0K wow, thanks. I’ll definitely look at your lib.

tatut08:07:29

If you are feeling particularly adventurous, you can try https://github.com/tatut/specql

seancorfield06:07:36

@armed Could you try that same query directly with java.jdbc just to eliminate whether the problem is yesql or something else?

seancorfield06:07:02

I've never seen a database with ? in column names... I didn't even think it was legal.

armed06:07:39

Me neither, but have to use it 🙂 Tried JDBC - works fine.

armed06:07:36

In postgres it is not legal, but can be escaped with column name with quotes

seancorfield06:07:36

OK, well, that confirms a bug in yesql so you should create a GitHub issue.

armed06:07:53

Seems that yesql is not actively maintained. Started evaluating hugsql instead.

armed06:07:58

Thanks anyway

seancorfield06:07:24

Ah, right, I heard that folks are switching to HugSQL. BTW, there's a #sql channel that's probably best for Qs like this.

seancorfield06:07:15

We use HoneySQL for complex queries and raw java.jdbc for most stuff.

melindazheng07:07:56

Singapore Clojure Meetup tomorrow night, welcome to join. https://www.meetup.com/Singapore-Clojure-Meetup/events/240601551/

pesterhazy08:07:36

@melindazheng event invitations are always appreciated. But it would probably be better to limit them to one channel (#events seens best)

grav11:07:02

Anyone dabbled with Java 1.8's Nashorn (js runtime)? I’m a bit puzzled as to how it evaluates JS object literals:

(-> (javax.script.ScriptEngineManager.)
    (.getEngineByName "nashorn")
    (.eval "new Object({foo: 42})"))
=> {"foo" 42}
versus
(-> (javax.script.ScriptEngineManager.)
    (.getEngineByName "nashorn")
    (.eval "{foo: 42}"))
=> 42

grav11:07:04

Oh, this works (wrapping the exp with parens):

(-> (javax.script.ScriptEngineManager.)
    (.getEngineByName "nashorn")
    (.eval "({foo: 42})"))
=> {"foo" 42}

mdallastella12:07:58

Hello everyone, is there any book/online resource about functional architectural patterns? Something like Patterns of Enterprise Application Architecture by Martin Fowler but from a functional point of view...

yury.solovyov13:07:09

Rich Hickey's Talks can be considered as source of some patterns I think

matan13:07:47

any spectacular clojure alternative to https://github.com/Raynes/conch?

matan13:07:41

clojure's built-in sh is limited (no support for processing stdout/stderr as streams)

vandr0iy15:07:13

Hi clojurians! I'm trying to pattern-match a hashmap, but this is what I get:

(m/match [{:arst false}]
  [{:qwfp #"stuff.*"}] 1
  [{:arst false}] 2)
ClassCastException clojure.lang.Keyword cannot be cast to java.lang.CharSequence  clojure.core/re-matcher (core.clj:4775)
What's going on here?

potetm15:07:49

@vandr0iy I pasted exactly what you have into the repl and got 2.

baritonehands15:07:12

@vandr0iy Looks like that error message indicates a problem with the regex

potetm15:07:18

Just to double check, what version of core.match are you using?

vandr0iy15:07:29

@potetm [org.clojure/core.match "0.3.0-alpha4"], with (:require [clojure.core.match :as m][clojure.core.match.regex]) in my ns

vandr0iy15:07:26

@baritonehands (re-matches #"stuff.*" "stuff123") works, so no regex issues as well

vandr0iy15:07:24

clojure version: org.clojure/clojure "1.9.0-alpha15

potetm15:07:29

I'm not sure what the design of this is, but it looks like it might be a boog.

potetm15:07:44

macroexpanding the above yields:

(try
 (clojure.core/cond
  (clojure.core/instance? clojure.lang.ILookup x)
  (try
   (clojure.core/let
    [x_qwfp__6982
     (if
      (clojure.core/instance? clojure.lang.ILookup x)
      (clojure.core/get x :qwfp :clojure.core.match/not-found)
      (clojure.core.match/val-at* x :qwfp :clojure.core.match/not-found))]
    (clojure.core/cond
     (clojure.core/re-matches #"stuff.*" x_qwfp__6982)
     1
     :else
     (throw clojure.core.match/backtrack)))
   (catch
    Exception
    e__6002__auto__
    (if
     (clojure.core/identical? e__6002__auto__ clojure.core.match/backtrack)
     (do
      (try
       (clojure.core/let
        [x_arst__6983
         (if
          (clojure.core/instance? clojure.lang.ILookup x)
          (clojure.core/get x :arst :clojure.core.match/not-found)
          (clojure.core.match/val-at* x :arst :clojure.core.match/not-found))]
        (clojure.core/cond
         (clojure.core/= x_arst__6983 false)
         2
         :else
         (throw clojure.core.match/backtrack)))
       (catch
        Exception
        e__6002__auto__
        (if
         (clojure.core/identical? e__6002__auto__ clojure.core.match/backtrack)
         (do (throw clojure.core.match/backtrack))
         (throw e__6002__auto__)))))
     (throw e__6002__auto__))))
  :else
  (throw clojure.core.match/backtrack))
 (catch
  Exception
  e__6002__auto__
  (if
   (clojure.core/identical? e__6002__auto__ clojure.core.match/backtrack)
   (do
    (throw
     (java.lang.IllegalArgumentException.
      (clojure.core/str "No matching clause: " x))))
   (throw e__6002__auto__))))

potetm15:07:57

woof that was a lot, sorry ya'll

potetm15:07:56

Anyways it looks like it's probably calling re-matches with :clojure.core.match/not-found.

potetm15:07:28

There should probably be a guard there in to-source ::m/regex.

vandr0iy15:07:10

@potetm thank you, following the report...

potetm15:07:49

@vandr0iy Be sure to upvote it if you want attention paid.

yury.solovyov16:07:33

is there a formatter for clojure code that I can adapt progressively without converting the whole codebase at one? I tried parinfer for Atom, but it is too intrusive for me

noisesmith16:07:55

cljfmt is a good plugin and unlike editor based options every collaborator can easily have the same rules

mbertheau17:07:08

Is there an obvious way to write the following without repeating x? (if (some-pred? x) y x) Meaning if x is ok, just use it, otherwise use the alternative y

a1317:07:45

it could be written like

(or (somefn x) y)
, but inside somefn there definitely would be repetitions of x or % argument

eriktjacobsen17:07:03

you have three values you care about, x, y, and (some-pred? x), so you will need those three elements. if x is truthy, you could write the pred to return x or false and use (or (some-pred? x) y), though that means custom predicates.

eriktjacobsen17:07:41

Doesn't work if you need pred to succeed on x being false / nil though

a1317:07:59

complement

tatut17:07:13

I think (if (foo? x) y x) is readable and repeating one name, once as a parameter to the predicate, isn’t bad

jeff.terrell17:07:43

@mbertheau You can do that with a macro if you so desire. Something like this:

(defmacro pass-or-alternative [pred-expr value-expr alternative-expr]
  `(let [value# ~value-expr]
     (if (~pred-expr value#)
       value#
       ~alternative-expr)))

eriktjacobsen17:07:33

you don't need a macro, just (fn [pred x y] (if (pred x) x y), then you'd just use it like (my-fn pred x y)

moxaj17:07:11

you do need a macro, you don't always want to evaluate y

noisesmith17:07:12

if y has side effects the macro version is better

sashton17:07:19

although the original question did not mention any lazy evaluation requirements

noisesmith17:07:19

it wanted a replacement for if

sashton18:07:35

i read it more as “how can I avoid re-typing ‘x’” rather than “how can I replace a call to ‘if’ while keeping the characteristics of ‘if’”

mbertheau18:07:03

Thanks for your suggestions!

arohner18:07:31

is there a way to macroexpand a private macro?

arohner18:07:45

(macroexpand (private-macro foo))

arohner18:07:14

trying that gives “var #‘private-macro is not public”

jeff.terrell19:07:30

I think you need to quote the to-be-expanded form.

jeff.terrell19:07:40

(macroexpand '(private-macro foo))

arohner19:07:37

that was slack formatting fail on my part

arohner19:07:55

I know the standard way to use macroexpand, but it fails w/ private macros

jeff.terrell19:07:46

Interesting. :thinking_face:

jeff.terrell19:07:28

Have you tried ns-resolveing the private macro? Not sure whether that would work, but maybe.

arohner19:07:42

ah, looks like tools.analyzer will do it

arohner19:07:56

but AFAICT, it’s not possible in the built-in implementation

jeff.terrell19:07:37

Wasn't aware of that limitation. Interesting.

noisesmith19:07:47

@jeff.terrell the problem with resolve or ns-resolve is that the clojure compiler uses metadata on vars to decide if something is a macro, so using the var means it gets treated as a function - but! the fascinating thing is that this is a valid way to expand a macro, as long as you provide placeholders for &form and &env (nil here because I’m lazy and it doesn’t change the output)

=> ((resolve 'when) nil nil true :OK)
(if true (do :OK))

noisesmith19:07:00

@arohner so yeah, see above, just give workable &env and &form, and call the var instead of macroexpand the macro call and it works

arohner19:07:45

interesting

noisesmith19:07:21

of course with macros that don’t access &env or &form (which is most…) two nils suffice

jeff.terrell20:07:38

Very cool! Thanks for the info @noisesmith. simple_smile