Fork me on GitHub
#beginners
<
2017-03-23
>
stuartrexking00:03:02

Why would one use a var quote instead of the symbol? As example, @yogthos uses the var quote for home-routes in the luminus template. Why not use the unquoted symbol? https://github.com/luminus-framework/luminus-template/blob/master/resources/leiningen/new/luminus/core/src/handler.clj#L38

noisesmith00:03:51

stuartrexking a symbol is a function that looks itself up in an associative data structure

noisesmith00:03:15

it has nothing to do with the function of the same name (unless you use it to look up a function in a namespace via resolve)

noisesmith00:03:29

oh - unquoted symbol

noisesmith00:03:45

@stuartrexking every time you call a var, it looks up its definition to call it

noisesmith00:03:19

when you pass a function by name, it is only looked up once (when it gets passed in) and the recipient gets that specific value closed over

noisesmith00:03:35

if you change the definition, the closure doesn't see it, and still uses the old version

stuartrexking00:03:55

And by change definition you mean rebind?

noisesmith00:03:03

I mean using def or defn again

noisesmith00:03:50

so, using the var-quote form allows changing the definition on the fly without having to restart the server process using it

stuartrexking00:03:04

Ok, I understand.

noisesmith00:03:24

this is incompatible with using clojure.tools.namespace/refresh

seancorfield00:03:32

With routes, it’s nice to use #‘sym so that while you’re developing in the REPL, you can redefine sym and the new version is picked up automatically.

noisesmith00:03:46

refresh destroys the old var (or at least thinks it does) - but you hold onto it - which means def changes a new var and not the one you are using

noisesmith00:03:10

so don't use var-quote for a server, and clojure.tools.namespace/refresh, in the same project

stuartrexking00:03:30

Ok, thanks @noisesmith, @seancorfield

jumar04:03:01

@stuartrexking I think the specific use case for #'home-routes is that you want to "wrap" just these routes with wrap-csrf and wrap-formats without wrapping also oauth-routes and service-routes.

stuartrexking04:03:00

Yes. What I wanted to know was why use the var-quoted #'home-routes rather than just home-routes

jumar04:03:08

That's the reason

stuartrexking04:03:11

All good now. I understand the difference.

stuartrexking04:03:28

You can still wrap with unquoted symbol.

jumar04:03:36

@yogthos explains it in "Web development with Clojure, 2nd edition" on page 35:

The macro makes sure that the route is resolved before the middleware is applied. This ensures that middleware is only applied to specific routes, instead of being run globally for all routes. 

stuartrexking04:03:41

You just can't redefine it.

jumar04:03:40

no, there's a diffrence - using #'home-routes ensures that middleware is applied only to home-routes and not to the other routes

noisesmith04:03:37

jumar var quoting has nothing to do with that separation of middlewares though

jumar04:03:34

well, my understanding is that you need to use #'home-routes instead of plain home-routes to achieve that - but I might be wrong

noisesmith05:03:24

you are - the difference is that the var quote sees later redefinitions when used as a first class argument - it's not about the middleware wrapping per se

noisesmith05:03:49

function calls inside another defn are looked up when used, but functions passed as args are captured, the var quote overrides the capture and allows a fresh lookup

jumar06:03:47

@noisesmith thanks for clarification. This is indeed described on p. 31 in Web Development with Clojure

b0607:03:26

I'm trying to iterate through a ByteBuffer with map-indexed or doseq but I get

Caused by: java.lang.IllegalArgumentException: Don't know how to create ISeq from: java.nio.HeapByteBuffer

b0607:03:48

something like

(doseq [byte buffer]
    (.get byte))

b0607:03:57

or

(map-indexed (fn [idx byte] (.get byte)) buffer)

b0607:03:20

any hints are greatly appreciated

camdenclark07:03:08

dumb question—do I have to restart the REPL every time I edit a clj file? Or does the REPL autoload my clojure files when edited?

b0607:03:13

@camdenclark if you're using Cursive just right-click then Load file to REPL

camdenclark07:03:18

(for reference, I’m using vim fireplace with vim and my repl is hooked in)

camdenclark07:03:15

hm, maybe I should bite the bullet and learn cursive

camdenclark07:03:12

ooh! I figured it out!

andfadeev07:03:54

@camdenclark in general you start repl once, and then only sync changed files, loading them

andfadeev07:03:27

sometimes you should restart repl, for ex if you have new dependency in project.clj, but in some editors (ex. emacs) you can hotload deps as well

noisesmith17:03:34

that’s not emacs though, that’s pomegranate - you don’t even need an editor to do it

camdenclark07:03:45

yeah I think I can hotload deps too with this

schmee08:03:08

b5

(defn get-values [byte-buffer]
  (let [inner
        (fn f [byte-buffer limit pos]
          (when-not (= limit pos)
           (cons (.get byte-buffer) (lazy-seq (f byte-buffer limit (inc pos))))))]
    (inner byte-buffer (.limit byte-buffer) 0)))

schmee08:03:11

that will get you a lazy seq of the values in the byte buffer 🙂

schmee08:03:26

which you can the map over, for instance

noisesmith17:03:16

why not just use (map f (.array buf)) ?

noisesmith17:03:29

or more specifically

(map f (java.util.Arrays/copyOf (.array bb) (.limit bb)))

schmee18:03:17

that’s better, didn’t know about the .array method

noisesmith18:03:04

I actually think the first version might be better - I thought .limit reflected what had been put in the buffer rather than the size of the underlying array, but it’s the latter, so it’s redundant

yonatanel10:03:32

Is it possible to call a macro from within a macro while preserving the literal arguments and then continue using the result before returning from the enveloping macro? For example, wrapping clojure.spec/keys with a macro that calls it and uses the spec object before returning another.

not-raspberry10:03:43

you can generate code that uses the returned object

not-raspberry10:03:32

user=> (defmacro a [n] `(+ 1 ~n))
#'user/a
user=> (a 1)
2
user=> (macroexpand-1 `(a 1))
(clojure.core/+ 1 1)
user=> (defmacro b [n] `(+ 1 (a ~n)))
#'user/b
user=> (b 1)
3
user=> (macroexpand-1 `(b 1))
(clojure.core/+ 1 (user/a 1))

not-raspberry10:03:19

I don't understand the 'preserving literal arguments' part of the question.

yonatanel10:03:32

It means that calling (b (some expression)) will pass that expression as is to macro a.

not-raspberry10:03:38

You can pass quoted forms.

not-raspberry11:03:11

user=> (defmacro q [arg] `(quote ~arg))
#'user/q
user=> (q `(+ 2 2))
(clojure.core/seq
 (clojure.core/concat
  (clojure.core/list (quote clojure.core/+))
  (clojure.core/list 2)
  (clojure.core/list 2)))
Does it help in any way?

yonatanel11:03:30

Maybe... I'm trying several things

yonatanel11:03:47

@not-raspberry Thanks. Your first comment about generating code helped.

limix22:03:55

Is there an equivalent to bundle install for lein? lein install? I am trying to build a dockerfile where all the deps get installed. Currently when I run lein run the deps get installed each time. Thanks

limix22:03:45

I see, lein install and lein deps does install also run deps?

limix22:03:19

Anyone here ever play audio files from an RPi using clojure? What is the lightest audio lib for clojure?

raspasov23:03:51

@limix you probably want to look at "lein uberjar"