Fork me on GitHub
#clojure
<
2016-09-15
>
lvh02:09:14

Hey; is there a :keys destructuring syntax that lets me destructure a bunch of keys with a shared namespace, even if that thing isn’t really a namespace? (I have a bunch of stuff in datascript, a la :widget/color)

lvh02:09:17

I have a lot of :widget/$PROPERTY keys I’m trying to access with as little typing as possible 🙂

Alex Miller (Clojure team)02:09:13

(let [{:widget/keys [color foo bar baz]} …] … )

Alex Miller (Clojure team)02:09:26

assuming you are using 1.9.0-alpha8+

lvh02:09:36

ah; I was playing with that and somehow did ::widget/keys

lvh02:09:43

that makes sense

Alex Miller (Clojure team)02:09:05

::widget/keys will also work, presuming you have a widget alias referring to something

viesti07:09:00

Humdee, having problems with byte-streams library (https://github.com/ztellman/byte-streams) when using chunk-size larger than 1MB

viesti07:09:32

bytes.core=> (count (take 10 (bs/convert (bs/to-input-stream (repeat "hello")) (bs/seq-of java.io.InputStream) {:chunk-size (* 1024)})))
10
bytes.core=> (count (take 10 (bs/convert (bs/to-input-stream (repeat "hello")) (bs/seq-of java.io.InputStream) {:chunk-size (* 1024 1024)})))
2

viesti07:09:15

wonder why in the last case I don’t get 10 items, but only two 😕

sveri07:09:17

@seancorfield Thank you very much for the detailed explanation. All you said sounds good, also that these essential functions are part of .jdbc now makes me kind of happy. I will try to use .jdbc directly now. In the end, maps and seqs are all we need.

hiredman07:09:44

@viesti: here it doesn't just return 2, it returns a different number every time it is run

hiredman07:09:01

which is, I think, worse

viesti07:09:05

Now that I realise that @ztellman is here, would you have a clue on why the above behavior (large chunk-size gives less items even when an infinite stream is passed to convert)? 🙂

viesti07:09:38

when reading from a 600MB file instead of a lazy stream, using 5MB chunk-size, I cannot get to end of the file before getting AsynchronousCloseException

hans07:09:46

@viesti you need to make sure that you're not returning the lazy sequence out of the scope of your enclosing with-open form (if that is what you use)

viesti07:09:54

used doseq on the result

viesti07:09:54

something like (with-open [in...] (doseq [x (bs/convert.... in] ... ))

hans07:09:24

maybe something in the return value of bs/convert is lazy?

viesti08:09:51

hmm, might be

viesti08:09:19

(with-open [in (io/input-stream "/tmp/bigfile.json")] (doseq [x (bs/convert in (bs/seq-of java.nio.ByteBuffer) {:chunk-size (* 5 1024 1024)})] (println x) (swap! sum inc))) results into AsynchronousCloseException before completing

viesti08:09:38

sum is (def sum (atom 0))

viesti08:09:00

bs/vector-of seems work better, hmm

viesti09:09:07

odd that including byte-streams 0.2.2 in one project, I cannot seem to find bs/vector-of, and on a clean 1.8.0 project, this funtion is available 😕

viesti09:09:38

might be related that there is vector-of in clojure.core

miikka12:09:13

@viesti Are you sure that some other package is not depending on older version of byte-streams and that's what you get? If you run lein deps :tree, you should get a list of conflicts.

borkdude12:09:09

does compojure-api offer anything for error handling, like liberator?

ikitommi12:09:25

@borkdude: what kind of error handling? Exception handling is described here: https://github.com/metosin/compojure-api/wiki/Exception-handling

borkdude12:09:10

@ikitommi thanks, I’ll have a look

abdullahibra13:09:55

is there away to set http-agent before slurp call of url ?

abdullahibra13:09:07

(System/setProperty "http.agent" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.94 Safari/537.36")

abdullahibra13:09:43

(slurp "http://www.demilked.com/magazine/wp-content/uploads/2015/11/new-hybrid-animals-photoshop-37.jpg") CompilerException java.io.IOException: Server returned HTTP response code: 403 for URL: http://www.demilked.com/magazine/wp-content/uploads/2015/11/new-hybrid-animals-photoshop-37.jpg, compiling:(form-init2601230912767068017.clj:1:10)

abdullahibra13:09:17

but it's working in browser, i know the problem in setting agent, some servers accept specific agents

abdullahibra13:09:36

is there away to fix it?

katox13:09:09

@ikitommi hi, is there a way how to get api_key directly into swagger using compojure-ui? There used to be a text field on top the swagger js page which is now gone.

juhoteperi13:09:41

@katox New Swagger UI has a button which opens a dialog with text field to set the api key

ikitommi13:09:13

@katox @juhoteperi does the new ui require the api_key property to be set for the spec? There is an example of that somewhere...

jstew13:09:18

abdullahibra: If you're doing anything more than the simplest of I recommend using clj-http or another http client library. I'm not sure how to do that with slurp, but it's easy with clj-http.

idiomancy13:09:03

alright, so im struggling with macros again (read the chapter in brave clojure). Just for my own education, i want to write functions, not macros, that manipulate and return code directly. for instance:

(defmacro macropass [macro-function & code]
  (apply macro-function code))

(defn infix [first second third]
  '(second first third))

(macropass infix 1 + 1)

idiomancy13:09:34

if i do that though, it doesnt work, because

macro-function
is just a symbol

idiomancy13:09:11

how do i make it resolve that symbol within the macro?

idiomancy13:09:44

^whoops, edited to fix name refactor error 😛

katox13:09:55

@juhoteperi what should I add to spec to the button to appear?

juhoteperi13:09:01

@katox :securityDefinitions {:api_key {:type "apiKey", :name "x-apikey", :in "header"}}

juhoteperi13:09:15

at :swagger :data

katox13:09:15

@juhoteperi I put it as a sibling to :info under path [:swagger :data] but the index.html is still the same, there is an empty auth_container div. No button anywhere. What should I check?

idiomancy13:09:30

Anybody have any experience writing macros that might be able to lend a hand?

ikitommi13:09:18

@katox dont’ put it under :info.

katox13:09:12

@ikitommi it's only under ':data', it is sibling of ':info'

ikitommi13:09:33

@katox that example sniplet seems to do the trick. btw, let’s move this to #ring-swagger?

katox13:09:26

@ikitommi I'll try it and move there, thanks

idiomancy14:09:51

I just want to throw out my request for help again, in case anyone new is around

idiomancy14:09:59

is what im trying to do not possible?

idiomancy14:09:05

I suppose it probably isnt.

idiomancy14:09:21

thats probably why the concept of a "macro" exists.

sveri14:09:15

@idiomancy A lot of people here are willing to lend a hand, but, what we need is some more information about your problem that you are experiencing and some code, if possible.

idiomancy14:09:53

@sveri haha, yeah, I had posted that above. I didnt want to be obnoxious and post the same thing again until I got a sign of a pulse

idiomancy14:09:19

reposting: alright, so im struggling with macros again (read the chapter in brave clojure). Just for my own education, i want to write functions, not macros, that manipulate and return code directly. for instance:

(defmacro macropass [macro-function & code]
  (apply macro-function code))

(defn infix [first second third]
  (list second first third))

(macropass infix 1 + 1)
if i do that though, it doesnt work, because
macro-function
is just a symbol how do i make it resolve that symbol within the macro?

sveri14:09:52

@idiomancy ah, sorry, I only saw this message: "Anybody have any experience writing macros that might be able to lend a hand?". Otherwise you have to wait I guess.

idiomancy14:09:26

right, Yeah, I figured I was going to come off as an arse either way.

sveri14:09:49

I usually ask in the clojure forums after a day of no answer here

idiomancy14:09:09

clojure forums? I've seen the reddit sub

idiomancy14:09:18

is there a different forum youre referring to?

idiomancy14:09:26

oh nice! thanks!

Lambda/Sierra14:09:48

@idiomancy You could use resolve in the body of your macro. That's generally not a good idea, because then the macro-function argument to your macro would have different evaluation rules from normal Clojure code. For example, you could not pass an expression that returns a function to macropass. Typically, macros are easiest to understand when they change as little as possible about how code gets evaluated. Most macros only change when the code gets evaluated, not how.

idiomancy14:09:33

@stuartsierra basically, my big sticking point with macros is that they both manipulate code and evaluate that manipulated code. I want to be able to pass code around and manipulate using normal data structures, and then evaluate it when I'm ready

Lambda/Sierra14:09:00

@idiomancy Then you're not writing macros, you're writing an interpreter. 🙂

idiomancy14:09:39

ehhhh, I dont know if that was just trolling or what

Jeremie Pelletier14:09:44

@idiomancy you should write the body of your macro like this: `(apply macro-function code)

Jeremie Pelletier14:09:06

without the ` you’re evaluating the code you want to return inside the macro, not the program’s runtime

Jeremie Pelletier14:09:37

you could also remove the apply and use ~@code instead

idiomancy14:09:04

ahhh, thats right @lambdacoder. its that runtime vs compile time thing

idiomancy14:09:25

let me try that

Jeremie Pelletier14:09:27

macros run inside the compiler, not your program 🙂

Lambda/Sierra14:09:54

@idiomancy Sorry, not trolling, genuinely trying to help. Macros allow you to execute code at "compile time" which returns code for "runtime." If you're making arbitrary decisions about when things execute, you're already beyond the scope of what macros are designed to do.

Lambda/Sierra14:09:54

A macro has to treat all of its arguments as semi-opaque blobs of code, none of which can be executed until after the macro returns.

Jeremie Pelletier14:09:19

I like to see macros as receiving unevaluated arguments and returning unevaluated code

Jeremie Pelletier14:09:39

which really becomes clear once you implement a toy lisp VM

idiomancy14:09:59

that does help. rewriting it as

(defmacro macropass [macro-fn & code]
  `(~macro-fn ~@code))
causes it to return the unevaluated form (#object[clojure.core$PLUS 0x837cd4 "clojure.core$PLUS@837cd4"] 1 1) which starts to make the concept more clear

idiomancy14:09:08

although youd think id just be able to then evaluate that

Jeremie Pelletier14:09:27

oh I just noticed your infix is transforming code as well

Jeremie Pelletier14:09:50

I wonder if that could be done with macrolets?

idiomancy14:09:07

well, thats the basic idea, I was trying to write functions that manipulate the code, so that I could test them as things that just manipulate and return code without evaluating it

idiomancy14:09:21

and then put the evaluation part in the macro

idiomancy14:09:37

thats the concept. its not going well, hahaha

Jeremie Pelletier14:09:00

yeah in that case what stuart said holds, you’ll have to resolve the symbol into a var inside the macro, call it inside the macro and return its result as the macro’s result

idiomancy14:09:28

which is, of course, not a great idea

Jeremie Pelletier14:09:31

macros call normal functions all the time, but in your case you’re passing in a symbol not a function

idiomancy14:09:01

and of course theres no way to pass in a function to a macro

Jeremie Pelletier14:09:05

there could be quirks indeed, i’d probably use the fully qualified symbol if the defmacro and infix are in different modules

Jeremie Pelletier14:09:52

no because macros receive unevaluated arguments, so your “infix” is just a symbol at that point - it gets compiled into the infix variable but thats after macro expansion

Jeremie Pelletier14:09:23

resolving will work, its quirky but not that ugly

idiomancy14:09:34

I basically just want a function that goes "hey, see this stuff im writing? dont evaluate that until I've gotten a chance to play with it and arrange it how I like"

Jeremie Pelletier14:09:05

yeah it will have to resolve its symbol argument into a variable

Jeremie Pelletier14:09:43

basically if you directly call (+ 1 2) in your macro the + is already resolved into #’clojure.core/+ but if + came from the arguments its still the symbol + until passed into (resolve)

Jeremie Pelletier14:09:15

if your macro received the var, it wouldnt be a macro but a normal function 🙂

idiomancy14:09:49

right. I want a function that takes code and turns into unevaluated symbols, so that I can pass that into a function

Jeremie Pelletier14:09:57

and its only quirky because you’ll get the value of the variable at that point in the compile cycle, if the value changes at runtime the macro will have compiled in the initial value - thats the catch

Jeremie Pelletier14:09:04

in your case you wont rebind infix so its safe

idiomancy14:09:26

something like

(defn macropass [macro-fn & code]
  (macro-fn ~@code))

(macropass infix (code 1 + 1))

idiomancy14:09:46

^psuedo, obviously

Jeremie Pelletier14:09:31

(defmacro macropass [f & code] ((resolve f) code)) (defn infix [a o b] (list o a b)) (macropass infix 1 + 2)

Jeremie Pelletier14:09:37

off the top of my head

Jeremie Pelletier14:09:51

oh wait im missing an apply

Jeremie Pelletier14:09:57

(apply (resove f) code)

Jeremie Pelletier14:09:17

or if you want it more readable (-> f resolve (apply code))

idiomancy14:09:57

right, but because of that whole resolve issue, its kind of a problem, right? Well... or wait, how could that ever be a problem if you use ns qualified symbols? is the danger that someone else re-defs the function name to something else?

Jeremie Pelletier14:09:23

the danger is that if you rebind infix at runtime, your macro will already have run over the initial value

idiomancy14:09:41

isnt that something one shouldnt do anyway?

idiomancy14:09:49

rebinding a global name at runtime?

Jeremie Pelletier14:09:57

and im not sure what the context for resolve is: the macro’s ns or the caller’s ns - id pass in qualified symbols just to be sure

Jeremie Pelletier14:09:03

yeah you shouldnt do it

Jeremie Pelletier14:09:07

but its possible 😛

Jeremie Pelletier14:09:23

i usually only rebind vars in development inside my custom user.clj

idiomancy14:09:51

weird. isnt saying "you shouldnt use resolve because it will break if someone rebinds the name at runtime, which you also shouldnt do" kind of circular? like, if I do follow the guidelines, it wouldnt be a problem, and if I dont follow the guidelines, then it doesnt really matter if theres a guideline for it

idiomancy14:09:31

lol, i really need to write a lisp and see these things from the ground up at some point

Jeremie Pelletier14:09:37

yeah, i barely if ever need to use resolve

Jeremie Pelletier14:09:52

writing a lisp is a fun weekend project

Jeremie Pelletier14:09:14

and dont do it in clojure, thats cheating 😛

idiomancy14:09:30

well, ive always wanted a lisp that compiles to python

Jeremie Pelletier14:09:48

you should start with an interpreter first

idiomancy14:09:06

ive done basic dsl PEG's etc

Jeremie Pelletier14:09:12

that’ll get the data structures down, the reader & printer, evaluation & lexical scopes, etc

Jeremie Pelletier14:09:48

you dont need a PEG to parse a lisp, look at clojure’s clojure.lang.LispReader.java

Jeremie Pelletier14:09:18

its basically two dispatch tables on characters and reader macros respectively

idiomancy14:09:59

anyway, i know ive eaten like an hour of your day, but I wanted to say thanks a lot. I really appreciate your help. I've actually just secured my first professional clojure dev job (I know right, how did they let me in here?) and this kind of support is really awesome. might be keeping the lights on and bread on the table a bit longer!

Jeremie Pelletier14:09:38

nice! glad I could be of some help 🙂

idiomancy15:09:32

lol. I think I broke clojure. Getting an ExceptionInitializationError from this macro

Jeremie Pelletier16:09:28

I dont think I ever saw this exception hehe

Jeremie Pelletier16:09:46

whats your code like now?

idiomancy17:09:25

lol, it came from the way I was working with macros. basically, I was trying to eval stuff in a macro a and return eval'd stuff. it was no good.

idiomancy17:09:55

Honestly, I just moved to a solution where I pass a quoted list of forms into a regular function instead of having a macro at all

idiomancy17:09:21

so, in other words, something like

(infix '[1 + 1])

idiomancy17:09:46

the actual function was a bit more sophisticated (it actually builds a memoized version of a function based on the code you give) so I was trying to eval the code as a function and pass it to memoize, then return that memoized function

Jeremie Pelletier17:09:22

oh yeah you can only compile data, not objects

Jeremie Pelletier17:09:41

just like sending stuff on the wire basically

nickt18:09:01

hey all. Is there a way to hook some functionality into when a process will exit?

bfabry18:09:25

@nickt (.addShutdownHook (Runtime/getRuntime) (Thread. #(shutdown! system)))

bfabry18:09:29

assuming JVM

nickt18:09:26

cool thanks

fabrao18:09:08

Hello, a dumb question, Is there any way to (rest {"0814" 0,"0813" 0,}) => {"0813" 0} ?

pesterhazy19:09:19

why do you want that?

akiva19:09:20

You could do (first (rest… but, yeah, I echo @pesterhazy.

fabrao19:09:47

for recursive function

fabrao19:09:09

like car and cdr from Lisp

smw19:09:12

https://github.com/nathanmarz/specter does that sort of thing pretty well, @fabrao

pesterhazy19:09:13

no, maps aren't sequential

akiva19:09:31

first, second, ffirst, nth, rest, next, etc are basically the car and cdr of Clojure but I think this is an issue of wanting something from a particular data structure that it isn’t designed to meet.

akiva19:09:37

Again, echoing @pesterhazy.

akiva19:09:51

Maps are meant to be accessed by key.

fabrao19:09:21

thanks folks I´ll give a try

pesterhazy19:09:32

you can reduce over a map; you'll get k/v pairs

pesterhazy19:09:21

perhaps that fits your use case?

akiva19:09:48

Or you could use keys to get a list of keys and then ping back to the map structure to get values that way.

pesterhazy19:09:47

you can also traverse maps with first / rest, but the latter won't return a map but a sequence; it works by implicitly calling seq on the map

akiva19:09:20

And you can’t guarantee the order in which you’ll get results from that, I’m quite certain.

idiomancy20:09:33

is there any kind of version of

every?
where an empty collection causes it to resolve as false?

idiomancy20:09:00

would make my recursive searches a good bit cleaner

manutter5121:09:25

You could make one like (defn foo [coll pred] (and (seq coll) (every? pred coll))). Not sure what to call foo tho

idiomancy21:09:59

yeah, thats what I ended up doing

aaelony21:09:53

suppose you start using a library and you realize that you can add enhancements to a part of that library. You make the changes and now you want to test it sufficiently before submitting a Pull Request to the author. Is there a write up on how that is best done? What are the steps (create an uberjar, start a new project, make it a local repo)?? Is there a simpler way?

aaelony21:09:46

Thanks @hiredman, I'll read up on that

seancorfield22:09:20

@aaelony If you’re going to send a PR, many maintainers appreciate you adding tests to the existing suite of tests in the project. And often you can do lein test or lein test-all or some such to make sure your enhancements don’t break their existing tests.

seancorfield22:09:52

(i.e., it’s nice to include extra tests along with your source file changes, when you send a PR)

shaun-mahood22:09:42

@aaelony: It's also nice to open an issue and have a chat about the changes beforehand as well - you can probably ask about their preferences then.

seancorfield22:09:02

Hopefully the project you’re looking at already has a good suite of tests and documents how to contribute to the project, how to run tests etc.

aaelony22:09:29

yup, done that

aaelony22:09:46

thanks for all comments

shaun-mahood22:09:20

Thanks for caring about tests!

jrheard23:09:32

hi! i'm reading through the spec guide; i'm about 1/6 of the way in, so appologies if this question is addressed later in the document :] there seems to be a strong focus on defining "attributes" in the central spec registry by doing eg (s/def :a.namespace/thing int?), and referring to :a.namespace/thing everywhere. it seems like doing (def thing int?) in a-namespace, and referring to a-namespace's thing everywhere, would accomplish the same goal, and so i'm just trying to make sure i understand the purpose of (s/def) and the focus on namespaced keywords. my current theory is that s/def and namespaced keywords are good because you can refer to namespaced keywords without having to actually require the namespace, and so in this way you don't have to worry about circular import errors like i often ran into when using prismatic's schema library. is that the primary reason for this focus on s/def and namespaced keywords, or am i missing a bunch of other obvious upsides?

bfabry23:09:33

@jrheard namespaced keywords make good map keys, like regular keywords 🙂

jrheard23:09:04

fair point - i had just read the line that introduces s/merge, and so i was looking at eg (s/merge ::foo etc) and thinking "why's this better than (s/merge foo etc)?"; had sort of temporarily forgotten about maps 😄