Fork me on GitHub
#clojure
<
2015-11-04
>
Tim00:11:38

where can I get the source of let* rather than let?

Tim01:11:14

(defmacro let
  "binding => binding-form init-expr
  Evaluates the exprs in a lexical context in which the symbols in
  the binding-forms are bound to their respective init-exprs or parts
  therein."
  {:added "1.0", :special-form true, :forms '[(let [bindings*] exprs*)]}
  [bindings & body]
  (assert-args
     (vector? bindings) "a vector for its binding"
     (even? (count bindings)) "an even number of forms in binding vector")
  `(let* ~(destructure bindings) ~@body))

Tim01:11:16

it has this

Tim01:11:25

but I can't find the let* implementation

taylor.sando01:11:52

They initially define let, and let* here: https://github.com/clojure/clojure/blob/clojure-1.7.0/src/clj/clojure/core.clj#L32-L35 -- I think there's a lot of bootstrapping of code between that definition and the next. It seems to build a list with let*, though I'm not sure where let* is interpreted.

taylor.sando01:11:07

Then you're basically in java code though

jackmaz01:11:19

question: This may have already been answered, but is this the preferred comms over freenode/IRC?

jackmaz01:11:04

not that it matters; i'm on both, but just wondering

Tim01:11:17

anyone know why I would be getting a null pointer exception here?

(defmacro my-let [a b & body]
  (list 'let ['res b]
              (list 'println "just checking" 'res)
              body))

(my-let [foo 2] 'bribe (println "in second body"))

taylor.sando02:11:03

This is what it's expanding to: (let [res (quote bribe)] (println "just checking" res) ((println "After")))

jackmaz02:11:42

@taylor.sando: look at your macro-expansion

jackmaz02:11:07

the (println "After") is in function position in another list

jackmaz02:11:13

that's where the null pointer is coming from

jackmaz02:11:20

also, i'm not terribly sure what you're trying to accomplish here

taylor.sando02:11:54

Well the & body gets packaged as a list of arguments, so the println gets packaged inside that list. You would have to eval it. Usually you'd use syntax quote for defining macros. You could do this:

jackmaz02:11:44

so your problem comes from the & body

taylor.sando02:11:09

Actually my thing would ignore the println

jackmaz02:11:16

b/c that's in a list, you have to splice that in

jackmaz02:11:15

(defmacro my-let [a b & body] #_=> (apply list 'let ['res b] #_=> (list 'println "just checking" 'res) #_=> body))

jackmaz02:11:26

use "apply" in there, and that should give you what you want

jackmaz02:11:50

you'll have other problems (with the macro in general), but it will get rid of the null pointer

jackmaz02:11:17

the NPE comes from trying to evaluate the result of (println "after"), which will be nil, since println always returns nil

jackmaz02:11:20

if that makes sense

taylor.sando02:11:56

Sure, (println "whatever") returns nil, and (nil) is a null pointer exception

Tim02:11:03

oh I see

nimblerabit02:11:50

As a learning exercise, I took a homework project I had to do in Java and re-did it in Clojure. The clojure version ended up running over 50x slower than the Java one, and I'm having trouble figuring out what I've done wrong. I'd appreciate it if anyone was willing to take a look at the code to help me understand what I need to do differently: https://gist.github.com/anonymous/703ffb1fe824bed2cb2e#file-star-distance-clj

nimblerabit02:11:04

I'm sure there's all kinds of sloppy code in there as I'm still really new, but mostly I'm curious what I need to be focusing on to improve the performance.

nimblerabit02:11:41

There's kind of a lot of extraneous lines, but basically all of the work is being done in the (compute-distance) function, which is called over 10 million times (this is an n^2 algorithm). I'm not sure if the issue is how I'm doing the computations there, or if it's more about the scaffolding around that.

roberto03:11:53

you are finding the nearest star for each star?

roberto03:11:45

It is hard to know without some profiling information.

nimblerabit03:11:02

I'm not very experienced at profiling

roberto03:11:08

One of the things I would try is to memoize is to memoize these https://gist.github.com/anonymous/703ffb1fe824bed2cb2e#file-star-distance-clj-L48

roberto03:11:37

it could help, or maybe not, hard to tell.

nimblerabit03:11:22

http://i.imgur.com/17xQoa9.png here's what I got out when I tried to profile the program

nimblerabit03:11:31

ooh memoizing is an interesting idea I hadn't thought of

nimblerabit03:11:37

I'll give it a shot and see how it goes, thanks!

roberto03:11:34

(let [ax->bx  (- (:x a) (:x b))
         ay->by (- (:y a) (:y b))
        az->bz (- (:z a) (:z b))]
   (math/sqrt (+ (memoize math/expt ax->bz 2) (memoize math/expt ay->by 2) (memoize math/expt az->bz 2)))

roberto03:11:39

something like that

roberto03:11:09

and to squeeze out some more speed you could probably also try memoizing the sqrt function.

ghadi03:11:02

rather than using clojure.math.numeric-tower, use (Math/sqrt)

ghadi03:11:17

nimblerabit ^

roberto03:11:54

Also, you can improve the algo. You are calculating the distance between star a and star b 2x.

roberto03:11:01

If a is the nearest star to b, then b is also the nearest star to a, right?

roberto03:11:27

Or maybe not

roberto03:11:42

Yeah, I just realized how wrong I am

roberto03:11:44

But you can still save extra computation by only calculating distances b/w same stars only once

ghadi03:11:58

ignoring that, it's still calculating the distances twice, is it not?

nimblerabit03:11:21

Yeah you're right

nimblerabit03:11:36

also wow, the Math/sqrt is way faster

ghadi04:11:22

same with the other math call

nimblerabit04:11:37

yeah I just switched it to Math/pow

nimblerabit04:11:38

@roberto fyi memoization seems to actually slow things down, I don't think there's enough overlap in the problems

nimblerabit04:11:35

on the other hand using the java Math functions speeds things up quite a bit, that made a large difference

nimblerabit04:11:57

so apparently I shouldn't be averse to using Java functions...for some reason I had a desire to stay within Clojure

ghadi04:11:18

"Clojure is not an island"

nimblerabit04:11:34

so I changed to using the Math/ functions, and I switched all the maps to records, and the total running time is half as long now

nimblerabit04:11:48

that's much more in line with what I was expecting, thanks for the help guys

audaxion05:11:29

anyone know anything about compojure-api?

mikera05:11:29

@nimblerabit might be worth trying core.matrix with vectorz-clj. There are some highly optimised vector maths operations there

audaxion06:11:14

do you know if there’s a way to change the routes for compojure api based on the APP_CONTEXT env variable? seems like they compile in, but i have to deploy into a context other than root for prod and it’s just the swagger-ui pieces that are busted i can hit the api via curl at the app_context just fine but swagger-ui is so handy

juhoteperi06:11:11

@audaxion: Compojure-api automatically supports setting swagger-ui base-path from servlet context, if that is not enough you sould be able to set it manually: (swagger-docs "/api-docs" {:basePath "..."})

audaxion06:11:54

i can try that

audaxion06:11:10

the problem is i have to serve it behind nginx in a non-root context

audaxion06:11:23

so servlet-context doesn’t get set

audaxion07:11:41

@juhoteperi: got it working, thanks!

nowprovision07:11:28

you can build a handler without defroute (apply compojure/routes [list-of-routes])

maxp11:11:27

is it possible to stop "leiningen repl" create directory "dev-resources"?

triss12:11:40

ok guys... what's the simplest way of getting all files with a particular extension from a folder?

triss12:11:58

should I be filtering my file-seq with a reg exp?

triss12:11:06

oh just found javas .endsWith... that'll do I guess

itrillian12:11:05

@triss: I had to do this in a project and ended up taking over the file-seq code but adding a FilenameFilter to it

triss12:11:17

itrillian: ah thanks man. might come in handy next time I have a lot of files to sort through

jstew12:11:29

@triss: There is also this is you're doing a lot of things with filesystems. I like it a lot: https://github.com/Raynes/fs

triss13:11:25

ah great thanks jstew . looks very handy

dominicm17:11:17

I'm working with multimethods, and I'm a little concerned about how I should order something in this system.

dominicm17:11:32

Multimethods seem to depend on global state to a degree.

dominicm17:11:38

I'm using honeysql, and I'm adding a postgres function to it (`ilike`) But I'm not sure how to organize my code for including this extension of the multimethod. Anybody got any advice?

dominicm17:11:00

Or even documentation which describes what I'm speaking of? I'm hoping there may be a few pointers there.

thheller17:11:05

@dominicm: short answer would be that each namespace that expects a given multimethod to be there should require it

thheller17:11:38

just like normal code

dominicm18:11:38

@thheller: Yeah. It's just.. weird to me, because you're requiring something from the bedroom, so you can go in the bathroom. If you get my point?

thheller18:11:44

well .. if you have a "system" namespace that loads everything you can do it there too

dominicm18:11:02

@thheller: I am considering that, as I am using component.

thheller18:11:02

but that doesn't work so well with a REPL

thheller18:11:24

since your namespace using ilike now has a hidden dependency on the system ns

thheller18:11:43

so if you want it clean and simple require it in the namespace that actually uses it

thheller18:11:22

might feel weird in the beginning but that goes away

dominicm18:11:43

Yeah, that's what arises 😛. Glad to know there's not something obvious I'm missing to resolve it. Thanks @thheller

thheller18:11:07

if you are using component it is save to do wherever you set up the db component

thheller18:11:17

since it is save to assume you are going to use the component

dominicm18:11:28

It's safe, but somewhat complicating, as you said. As there's a silent dependency. Which hopefully will never change, but it's code, and it will. It's inevitable.

thheller18:11:55

exactly, which is why I prefer the verbose way simple_smile

dominicm18:11:57

Me too. The code is now committed to the repo! There's no going back.

pjagielski18:11:05

hi, is there any short way to convert nested map like {:a {:b "1"}} to xml in form <a><b>1</b></a>? I have only elements, no attributes, cdata, etc.

pjagielski18:11:19

should I walk the whole structure to convert it it data.xml/element ?

pjagielski18:11:53

should help, thanks!

sandbags18:11:51

I’m struggling to google an answer for this but, using leiningen, how can i control which source folders are included? I may be going about this the wrong way but my tests are getting run when I am running my app in development and, hence, polluting the database.

sandbags18:11:11

i’m wondering if maybe i have something else wrong … i don’t have a lot of time for dev at the moment so keep having to relearn what’s going on

mahinshaw18:11:50

@sandbags: You should be able to use :source-paths ["src" ..]

bostonaholic18:11:48

it has all of the options for a project.clj file

sandbags18:11:08

okay thanks guys, i will look into those

ghadi18:11:32

dominicm: I believe donaldball is familiar with extending HoneySQL

donaldball19:11:26

In my systems where I participate in honeysql’s multimethods, I have a project.honeysql ns that I require in my project.system ns, which is in turn required by anything that does anything with the db

seancorfield19:11:27

@yogthos: We’re using Selmer really heavily at work and one of the things we find we need fairly often is a way to look up filter arguments in the context-map, so foo|my-filter:kw means something like this (my-filter (:foo context-map) (kw context-map)) rather than (my-filter (:foo context-map) kw)

yogthos19:11:09

@seancorfield: do you have a change in mind, it sounds like something that could be added fairly easily

seancorfield19:11:10

It would be great if there was some syntax for "special" arguments that indicated "look this up in the context-map" instead of just being a literal value. Not sure what that syntax should be tho’?

yogthos19:11:17

I’m definitely open to ideas on this one simple_smile

seancorfield19:11:00

Can’t use : since that’s the separator. Not sure what would be safe to use that wouldn’t break existing Selmer code…

seancorfield19:11:52

foo|my-filter:@kw perhaps? (still risks breaking existing code I guess)

yogthos19:11:18

right now the separator parsing is pretty straight forward, I think it’s just a regex

yogthos19:11:49

so it shouldn’t break anything off top of my head, @ seems like a reasonable character to use there

meikemertsch19:11:52

Is it possible using get, always looking it up and if it's not found returning the literal as default?

seancorfield19:11:16

@meikemertsch: I suspect that would break a lot of existing code?

yogthos19:11:23

yeah I think changing the existing semantics would affect the current users, and it would be a subtle change so tricky to test

yogthos19:11:12

might also have performance implications, so I’m leaning towards explicit

yogthos19:11:31

probably the easiest would be to take the parsed out filters and check for any that start with @ for example

seancorfield19:11:06

Yeah, it would need to pass context-map into a some of the called functions so filter args could be looked up — since @foo.bar would need to be supported so they’d have to be split-filter-vald too

yogthos19:11:36

are you up for doing a pr for it? simple_smile

seancorfield19:11:57

I’m happy to have a go at it (since I have a use case for it right now) although part of me wants full recursive evaluation since my main use case right now is actually @(locale|language), i.e., the ability to filters to the argument values as well simple_smile

yogthos19:11:53

I’m open to whatever makes the use case work best barring regressions in current behavior simple_smile

yogthos19:11:04

using the parens would make sense to group them, just have to get more clever with the parsing that way

seancorfield19:11:39

I’m looking at the parsing now…

yogthos19:11:34

great, and glad to hear you’re getting good mileage out of selmer simple_smile

seancorfield19:11:44

Our business team love that they can write HTML email templates as i18n content stored in the DB and don’t have to ask DEV to write code simple_smile

yogthos19:11:55

I imagine that’s a fairly common scenario

seancorfield19:11:21

Hmm, making the parser fully recursive would touch a lot of parts :( read-tag-info would need to become fully recursive and a lot of code would get touched supporting that. I guess I’ll be a bit less ambitious simple_smile

yogthos19:11:08

if you did go with that approach it would probably make sense to have a separate namespace that handles these types of filters

yogthos19:11:35

as long as they can be encapsulated in a way that’s easy to parse out on the initial parse it wouldn’t be too bad

sandbags21:11:32

I’m missing something. my reading of the docs suggest that {:profiles {:dev {:test-paths ^:replace []}}} should override the default value (as shown using lein pprint) but doesn’t seem to. Anyone see where I have come unglued?

sandbags21:11:20

assuming the default profile if nothing else is specified is dev, i’m pretty sure it is but maybe i goofed there

sandbags21:11:00

i wish lein pprint actually was pretty

bostonaholic21:11:45

@sandbags: lein test uses the test profile

sandbags21:11:19

@bostonaholic: my problem is the code on the test-paths being evaluated in the dev profile

bostonaholic21:11:21

I don't know why, but I recall (maybe) needing to use it as {:profiles {:dev {:test-paths ^:replace [""]}}}`

sandbags21:11:45

ah, will give that a try thanks

sandbags21:11:55

hrnn… didn’t seem to work

bostonaholic21:11:58

are your sources and tests in a "non-standard" path structure?

sandbags21:11:46

i don’t think so: ${PRJ_HOME}/src & ${PRJ_HOME}/test

xeqi22:11:46

@sandbags: do you mean to use :source-paths instead of :test-paths?

sandbags22:11:37

xeqi: the test source folder isn’t in the :source-paths variable so I don’t think so...

xeqi22:11:59

ah, right, sorry been awhile since I've looked at that part of lein

xeqi22:11:19

@sandbags: adding :profiles {:dev {:test-paths ^:replace []} causes lein pprint to show me an empty :test-paths on lein 2.5.3

sandbags22:11:46

@xeqi: useful to know thx, maybe i am doing something rong

cfleming22:11:13

When trying to use the jsr166y jar with Clojure to support JDK6, I’m getting an "Unsupported major.minor version 51.0"

sandbags22:11:13

tried it again, c&p’ing your syntax and no dice, 2.5.3 here also

cfleming22:11:34

javap agrees, the class is JDK7 only.

sandbags22:11:58

ah, there are two test-paths keys in the output

stopa22:11:42

hey @all, I'm having a weird bug using prismatic/schema 0.4.0, and clojure 1.8.0 if I re-eval the file that has all of my schemas, functions that use those schemas don't see to update to the new value. If I re-eval the functions that use those schemas, then it works

sandbags22:11:55

the empty one is in the {:profiles} but the top-level one is not empty

stopa22:11:10

(oh shit, I hope all does not call everyone in the group...did that out of habit)

sandbags22:11:53

maybe i have misunderstood something about how the :profiles are applied

sandbags22:11:42

oh well, i guess i will carry on tilting at this particular windmill tomorrow

sandbags22:11:03

thanks for your help @bostonaholic and @xeqi

cfleming22:11:22

I’m also having a problem where I can’t compile my Clojure code under JDK6, I get the “Can’t connect to window server” error.

cfleming22:11:38

Setting java.awt.headless=true doesn’t help.

cfleming22:11:36

Does anyone know where I can get a jsr166y jar that works under JDK6?

cfleming22:11:02

@xeqi: Yeah, it says it works under JDK6 but it lies

xeqi22:11:19

@stopachka: are you using protocols as part of your schema?

cfleming22:11:33

java.lang.UnsupportedClassVersionError: jsr166y/ForkJoinPool : Unsupported major.minor version 51.0, compiling:(clojure/core/reducers.clj:56:21)

stopa22:11:10

@xeqi -- we don't use defprotocol, but I do see a defrecord

cfleming22:11:41

@xeqi: I was going to build from source, but the build process is... interesting.

xeqi22:11:14

@cfleming: just pulled it down and yeah, 1.7 blah

alex.nixon22:11:02

why does Clojure forbid you from creating an unbuffered channel with a transducer?

xeqi22:11:33

@cfleming: http://repo1.maven.org/maven2/org/codehaus/jsr166-mirror/jsr166y/1.7.0/ has a 1.6 ForkJoinPool.class if you want to trust random jars from the internet

alex.nixon22:11:40

(and by forbid I mean "silently ignore your transducer leaving you with a subtle bug")

cfleming22:11:08

@xeqi: I trust a random internet jar more than one I’ve built myself with this ant file.

alex.nixon22:11:24

I notice this was raised in Jira but I disagree with the resolution - am interested in hearing others' thoughts. http://dev.clojure.org/jira/browse/ASYNC-140

seancorfield23:11:06

@yogthos: PR submitted to support @foo.bar in filter arguments.

yogthos23:11:27

nice! I'll take a look in a moment

seancorfield23:11:18

LMK if anything needs changing. I’d like to be able to start relying on this new functionality at work simple_smile

yogthos23:11:15

@seancorfield: it looks good to me, the only question is if the syntax would need to be changed if you decide to add the recursive case

yogthos23:11:30

so I could pull it in as is and push it out, but then if the logic needs to be more sophisticated later on there would be an api change potentially