Fork me on GitHub
#clojure
<
2015-07-06
>
denik00:07:39

is there a way to observe subexpressions in a clojure fn ?

escherize01:07:07

what's a subexpression?

escherize01:07:39

like (repeat 2 a)?

(fn [a] (repeat 2 a) (str a))

denik01:07:34

yes and (str a) too

denik01:07:56

any forms nested within a toplevel form

escherize01:07:59

(str a) will be returned

escherize01:07:22

so sorry, but what did you mean by observe

denik01:07:43

look at the values generated during evaluation

escherize01:07:02

I do that in an ad-hoc way

denik01:07:08

like add-watch but for anonymous functions

denik01:07:33

well one can to (doto (fn [] abc) prn)

escherize01:07:38

(fn [crazy-map] (def *c crazy-map) "some computation")

denik01:07:57

that’s better

escherize01:07:19

then you can inspect *c like

(-> *c)
,
(-> *c keys)
,
(-> *c :this-key)

denik01:07:53

the problem I’d like to solve is that in order to unit test a subexp like that one needs to def it

denik01:07:10

I often find def’ing a simple function worsens readability

denik01:07:23

do I’d like to look into a bigger fn and unit test the subexpressions

escherize01:07:35

can i see an example

denik01:07:40

this would work best with an IDE that assigns some kind of anonymous identity to the subexps

denik01:07:50

(-> {:p {:first “george”
               :last “smith”)}
     :p
      (update #(str/join “ “ ((juxt :first :last) %)))) ;; want to test update fn

escherize01:07:49

Hm, I would either defn that update function, maybe let it take :first :last depending on if it's ever used again? or test here at the top level

escherize01:07:20

is there a reason to not test @ the top level?

denik01:07:20

I understand that. The point is it’s just one line and I actually find it more readable to just look over the code

denik01:07:46

yes, of course, both top level and every function inside

denik01:07:35

I could use tools.analyzer correct?

denik01:07:45

optimally I would like to select a subexp within the IDE and write a unit test for it right there

escherize01:07:08

you or an ide could use tools.analyzer to do that. once you refactor the function you would have to re-calculate the path to the subexpression you want to test, even if the subexpression itself was unchanged

escherize01:07:30

for me, if I need to test something I would defn it.

canweriotnow03:07:31

Wondering if anyone has a strong preference for a SQL DSL used alongside prismatic/schema? I was a Korma fan, but HoneySQL looks pretty… sweet (groan).

canweriotnow03:07:11

@gtrak you can’t use prismatic/schema w/ plumbing to build types and protocols to do what you need to do?

canweriotnow03:07:11

Or do deftypes and defrecords have too much clj-ness to fulfill your pojo goals?

escherize04:07:22

for static queries, I prefer jdbc (and am interested in yesql). The rationale against dsls is that you don't have to learn sql + _____. For creating dynamic queries, I can see the value in honey sql.

niwinz05:07:44

@canweriotnow: do you know about suricatta?

denik14:07:43

thanks @escherize ! Same here just thinking about edgecases

pesterhazy15:07:47

Does anyone have this problem? When I run nightcode on Linux, all I get is a black window. (oracle or openjdk, xmoand as window manager)

mccraigmccraig15:07:39

@canweriotnow: i've had a generally good experience with honeysql for composing query fragments... it still has some wrinkles (e.g. "insert into foo (a,b,c) select..." isn't (or wasn't) directly supported

socksy15:07:20

anyone know what happens if JDBC throws an exception when trying to connect to the database for an insert? the JDBC wrapper puts the connection in a with-open, which worries me https://github.com/clojure/java.jdbc/blob/ffea0332a87ec4100d459ec9533e9619d46fb2c8/src/main/clojure/clojure/java/jdbc.clj#L1002

socksy15:07:29

not sure I’m reading the code right though

canweriotnow15:07:22

@niwinz I hadn’t, but I will certainly play with that, it looks very cool.

pesterhazy15:07:43

@socksy: only if the connection wasn't already open!

alejandro15:07:50

@socksy: the exception will still get thrown

socksy15:07:18

so if it weren’t open, then I wouldn’t get an exception?

alejandro15:07:44

in both cases you could get an exception

alejandro15:07:53

but if the connection is already open, it won’t with-open it

alejandro15:07:14

with-open won’t suppress exceptions though

pesterhazy15:07:49

you should probably open the connection explicitly in non-exploratory code anyway

pesterhazy15:07:12

the with-open is just a convenience to be able to play with queries easily in the repl, I think

alejandro15:07:55

@pesterhazy: why do you prefer opening the connection explicitly? not disagreeing, just didn’t know about the benefits of doing so

pesterhazy15:07:40

@alejandro: no real benefits except that usually you'll be executing more than one query anyway

pesterhazy15:07:55

and it would be bad to re-open the connection for each query

pesterhazy15:07:23

plus more often than not a db pool is the best choice

alejandro15:07:45

makes sense. thanks

ghadi16:07:39

@pesterhazy: @alejandro @socksy I have a different approach to jdbc that I've been working on https://github.com/ghadishayban/squee Major contrast to clojure.java.jdbc is not to look for a connection or open transaction in every single API function, instead favoring being explicit

ghadi16:07:33

I'll cut a release this week. Currently adding "readers" to the SQL ResultSet interface so that you can choose your own ways of materializing datatypes (a la clojure.edn or transit). It's nice to not have to change java.sql.Timestamp -> whatever.

ghadi16:07:56

And instead read the timestamps as Joda time, or java.time

pesterhazy16:07:05

I agree that clojure.jdbc has a whiff of magic, which is bad

ghadi16:07:31

The internal implementation is showing its age

pesterhazy16:07:45

I've also been bitten by the java.util.Date / clj-time problem

ghadi16:07:53

My pet peeve is the argument syntax in java.jdbc

ghadi16:07:58

It's almost a DSL

pesterhazy16:07:12

yes, I need to look it up each time

pesterhazy16:07:35

@ghadi, I love that you include insert-sql.

pesterhazy16:07:48

Everybody must a written a version of this at some point.

roberto16:07:02

squee looks pretty sweet

roberto16:07:20

no, thank YOU

ghadi16:07:11

Considering last week's release of 1.7 with transducers, I'd like to encourage everyone to start experimenting more with reducible collections, rather than lazy-seqs

ghadi16:07:37

There are some substantial speed wins to be had, but it may merit looking at things in a different way. Like being more eager over lazy

roberto16:07:58

I don’t grokk transducers yet. Still experimenting & learning clojure (and common lisp)

roberto16:07:17

trying to immerse myself in the general philosophies first

niwinz16:07:24

it has very similar goals that squee

niwinz16:07:11

I personally don't like the clojure.java.jdbc api and its implementation so, I'm currently maintaining clojure.jdbc and suricatta (at funcool organization)

niwinz16:07:37

that offers a little bit fresh and cleaner api for access to sql databases.

pesterhazy16:07:20

Clojure.jdbc vs clojure.java.jdbc is seriously confusing

niwinz16:07:01

is not confusing, the real name of clojure.java.jdbc is java.jdbc, and java.jdbc and clojure.jdbc

niwinz16:07:08

is a clearly different name

pesterhazy16:07:33

Well similarly for clojure.data.xml vs clojure.xml

pesterhazy16:07:13

I was surprised that there is a difference in each case

pesterhazy16:07:09

Even though the names are different, they both read as "clojure's standard xml/jdbc library"

seancorfield17:07:53

clojure.java.jdbc is likely to get reducible result sets "soon" so that it will play nice with transducers etc, but I’ve been resisting breaking too much backward compatibility — with is why contrib libraries in general move more slowly than some community libraries.

mahinshaw17:07:34

I am playing with transducers, and I want to compose some transducers conditionally. Something like (comp (when pred xform) (when pred xform2) ...). Is this something that should happen in a macro, or is there a way to do this with functions?

ghadi17:07:11

mahinshaw: build up your transducers in a let binding, then (apply comp) on them

mahinshaw18:07:40

@ghadi: Thanks, I'll give that a whirl

mahinshaw18:07:40

@ghadi: When I do (apply comp (map inc) (filter odd?)), I get an error saying "Dont know how to create ISeq from: clojure.core$fulter$fn__4576".

ghadi18:07:36

apply takes a collection at the end: (apply comp [(map inc) ... your other transducers])

mahinshaw18:07:04

@ghadi: right, thanks!

bmay20:07:38

what are S-expressions? can't wrap my head around the concept

arrdem20:07:22

What's unclear to you?

arrdem20:07:17

Traditionally the name is short for "symbolic expressions" and just refers to symbols and lists in parenthetical notation.

bmay20:07:03

i was reading how lisps are unique in that their source code is also written in sexprs?

arrdem20:07:14

Okay so the "big idea" here is that a program is really a bunch of expressions and evaluation rules. In a traditional interpreted Lisp dialect, these expressions are written as lists, read in as lists and processed as lists. This means you can write programs that write programs because the program itself is "just data" at the end of the day.

arrdem20:07:29

Does that make more sense?

bmay20:07:04

kind of. is this big idea related to language grammars or compilers?

teslanick20:07:39

If you're familiar with AST transformers, Lisps are written in their own AST (if that makes sense).

arrdem20:07:17

It's only to do with language grammar in that the only representation for a program is the same representation for general purpose data.

arrdem20:07:57

Macros are one example of this... consider the -> threading macro. It's a function from one list to another list, where the input list is in some DSL and the output list is a (presumably valid) Clojure program.

arrdem20:07:23

If programs weren't encoded as datastructures you couldn't express transforms like that.

meow20:07:19

@bmay: in a language that used infix notation like 2 + 3 the source code might get turned into an internal representation like (+ 2 3) whereas in Clojure and other Lisp languages the source code is itself already represented as such an expression.

meow20:07:16

For example, Python serializes (pickles) object representations in the form of s-expressions.

bmay20:07:46

@meow: so most programming languages use s-expressions under the hood?

meow20:07:29

most have some kind of abstract syntax tree (AST)

meow20:07:54

not sure that they are all s-expressions - not my area of expertise

gtrak20:07:16

ruby uses sexps under the hood

teslanick20:07:13

Javascript has a couple different ASTs depending on the parser implementer; one parses into s-expressions, but others parse into JS object literals.

bmay20:07:51

hmm maybe it's not clicking because i don't know what the "alternative" would be

gtrak20:07:41

the distinction is that you're literally writing the AST manually, and building up a compiler in some sense as you write your program.

arrdem20:07:06

The big idea is just that your programs in a Lisp are datastructures you can manipulate thus making it possible to extend the language with user land compilers like core.async which you can't reasonably do in other PLs where the program isn't visible as a datastructure.

gtrak20:07:07

if you had to call object constructors to do so, it would be too difficult, the literals are what make it powerful.

gtrak20:07:18

and macros...

arrdem20:07:29

mainly macros (which are userland compiler hooks)

arrdem20:07:08

You could imagine programs which use eval to generate code on the fly and do crazy stuff but this turns out to be really hard to do.

gtrak20:07:25

when ASTs are too far from the written source, it gets harder to manipulate both.

arrdem20:07:09

When your AST is written as its own string print representation it's dead easy.

gtrak20:07:14

comparatively, C macros are much more dangerous and less useful because they work on strings and can't have a notion of context

gtrak20:07:48

you could, possibly, write a C macro preprocessor in terms of the C AST

bmay20:07:56

yeah, i ran into this question while researching C macros

gtrak20:07:31

you'd have to learn a whole new set of abstractions to use such a preprocessor.

gtrak20:07:50

and i imagine it'd be tedious at best

mahinshaw20:07:06

You are probably just overthinking the subject. Take a look at SICP, mainly the first chapter (https://mitpress.mit.edu/sicp/full-text/book/book-Z-H-10.html#%_sec_1.1.1). It talks about expressions and the way they are evaluated.

bmay20:07:43

yeah, i was wondering if something like this was mentioned in SICP

gtrak20:07:27

they don't talk about macros there i thought? but the tradeoffs are similar for eval+apply.

mahinshaw21:07:22

no, not macros, but I think the s-expression idea is at the heart of heart question. And understanding evaluation helps.

bmay21:07:30

i might take a look at CS61A to go along with SICP. anyone watch those lectures?

bmay21:07:00

CS61A is a berkeley course

meow22:07:02

Another way to look at it is to turn it around: what would your code look like if every bit of it had to be written in terms of data structures? All of it, without exception.

meow22:07:44

You get a very uniform set of expressions with lots of parens.

meow22:07:16

simple, clean, elegant

meow22:07:24

once it becomes familiar

meow22:07:34

I'm still getting there

danielcompton23:07:24

I’m wanting to put Maven repository username and password in my ~/.m2/settings.xml, but I’m not sure how to reference it from my project.clj correctly

danielcompton23:07:35

Here’s the relevant parts of my project.clj and settings.xml https://gist.github.com/danielcompton/bd8a5d6219cd80e01bd9