Fork me on GitHub
#clojure
<
2023-08-25
>
Asher Serling07:08:49

I'm using the ring-refresh library to reload my browser whenever my code changes. However, the browser is going crazy, reloading the code every moment. On investigation it seems that it's because the way ring-refresh works is by tracking changes to the files and storing the time of the most recent change in an atom. It injects some javascript which regularly sends a request back to the server with the current time (of the browser). If the server considers the files to have been updated at a later point in time it responds to the request with a message indicating as such, triggering a reload. The problem is that the browser is sending the time based on my actual timezone, whereas the server time is using java.util.Date which is UTC. Is there anything i can do to deal with this?

Asher Serling07:08:26

I'm not sure this is the issue actually because i have it working in another project, and over there as well there's the same discrepancy between time zones

Asher Serling07:08:21

using the watchtower library which ring-refresh uses i added my own watcher with

(watcher ["src" "resources"]
         (rate 100)
         (on-change
           (fn [n] (println n))))
and it is returning a list of files which it says were modified, but which i did not touch. what's going on here?

p-himik08:08:35

What if you run watch -d -n1 'stat -c %Y filename on one of the files? Perhaps something is running in the background touching your files for some reason. Or maybe you have some weird filesystem that doesn't store mtime and always returns the current time when asked.

Asher Serling08:08:38

when i run

watch
it show no changes

Asher Serling08:08:08

as far as the filesystem, i do not have this issue on a different project on this same computer

Asher Serling08:08:47

i dont know if this is relevant, but for previous projects i was using calva. for this project i am using cursive. though when i tried opening this same project in calva it has the same issue

countgizmo10:08:34

Might be the Cursive's aggressive autosaving? I had a similar problem with a CLJS project. It made hot-reloading pretty much unusable. I couldn't find a way to disable the auto-save or make it less aggressive.

Asher Serling12:08:39

i don't know, there's nothing to save

chrisn15:08:37

Old tidbit - how do I get a java identifier from a clojure symbol? 'doit! -> "doitBANG"

mkvlr15:08:10

beat me to it

(munge 'doit!)
;; => doit_BANG_

chrisn15:08:42

Thats it - perfect thanks both of you 🙂. Finally adding pass-by-value to dtype-next's ffi mapping.

🎉 2
DeepReef1115:08:39

How to return multiple values? I have a for loop and I would need to return 3 elements on each for iteration and also have the restult of the for loop to be all these values. Ex:

(for [x (range 0 3)] [:div] [:div] [:div])
Expected result:
[:div] [:div] [:div] [:div] [:div] [:div] [:div] [:div] [:div]
I'm only using hiccup (no reagent)

Samuel Ludwig15:08:49

I'd suppose you'd just stick all of your results in a vector and return that, no?

mmer15:08:03

(flatten (for [x (range 0 3)] [ [:div] [:div] [:div]]))

DeepReef1115:08:15

Figured it out. flatten wouldn't work, because it would flatten the hiccup. But

(apply concat (for ... [[:div] [:div] [:div]]))
is working

DeepReef1115:08:39

Because it only remove one layer of array

Samuel Ludwig15:08:04

so, what apply does is it basically picks out the elements of a collection, and places each of the elements into the place of one of the arguments the function expects (someone can probably explain that better than I)

mmer15:08:11

Useful lesson.

p-himik15:08:14

Note that there's also #C053AK3F9.

phill16:08:33

(for [x (range 0 3) i (range 0 3)] [:div i]) Added the "i" inside the div so you can see what's going on

potetm23:08:06

Just so you know, (apply concat ...) returns almost the same thing as [ ... ]. The reason the first works and the other doesn't is because apply concat returns a seq instead of a vector, and hiccup treats the two differently. Vectors are always assumed to be html elements and seqs are allowed to be a seq of elements.

2
phill01:08:42

True enough. But also: "Clojure Don't's: concat" https://stuartsierra.com/2015/04/26/clojure-donts-concat ... If you have a vector and wish you didn't, you may efficiently wrap it with seq to cloak its concrete structure.

Jacob Rosenzweig23:08:19

Are there any good lein templates that give you ring, reitit, and malli all in one? Preferably with all the JSON <-> EDN middleware already setup? I feel like this is like the 4th time I've manually set this up.

timo06:08:01

I don't think so, mainly because there would be two router-libs in there. compojure and reitit are routers and it wouldn't make too much sense imho to add both of them.

Jacob Rosenzweig21:08:33

Ah I mispoke, I meant ring not compojure.

timo07:08:55

well, I was using kit lately. it's basically comprised of the libs that I would use. it's based on reitit and integrant. you can just add malli to it. maybe it's good for you?

danielsz16:08:17

Meyvn does what you want. In my latest https://www.youtube.com/watch?v=RimWHVLkkTw, I've shown how templates work. You'll want to look for "Hello Meyvn web" or "react" if you want client-side deps too. You can use Meyvn to kickstart the template and then turn back to your preferred build tool.

Jacob Rosenzweig19:08:59

@U067TPTUL Ha I didn't connect "Meyvn" with מבין until I went to your site. Love how it's also a pun for Maven as well.

😉 2
❤️ 2
Bobbi Towers23:08:41

I'm trying to get a high-level idea of how loop/recur are implemented. I've looked through the compiler but it's hard for me to understand it. I'm writing my own interpreter and what's tripping me up is the common situation where one loop calls another, e.g.

(defn loop1 [coll]
  (loop [s coll res1 []]
    (if (empty? s) res1
      (recur (rest s) (conj res1 (first s))))))

(defn loop2 [colls]
  (loop [s colls res2 []]
    (if (empty? s) res2
      (recur (rest s) (conj res2 (loop1 (first s)))))))

(loop2 [[1 2] [3 4]])
I've tried using macros, using a stack, and metadata to store the bindings/body/env and just can't seem to get it working. Anyone know a good approach for this?

clojure-spin 2
emccue23:08:11

Loop/recur do not work across function call boundaries

emccue23:08:19

if thats what you are trying to figure out

emccue23:08:30

trampoline is the mechanism for that

Bobbi Towers23:08:08

the above code works in Clojure though:

user=> (loop2 [[1 2] [3 4]])
[[1 2] [3 4]]

emccue23:08:13

oh it works

emccue23:08:27

but it doesn't get rid of stack frames

Bobbi Towers23:08:09

hmm, so that's not a good thing to use anyway?

emccue23:08:16

loop/recur are implemented in the really basic

Object s = ...;
Object res1 = ...;

loop:
while (true) {
  if (...) {
     s = rest(s);
     res1 = conj(res1, first(s));
  }
  else {
     break loop;
  }
}

emccue23:08:42

its fine - but this is ~= to how its implemented

emccue23:08:57

i'm just saying that your example doesn't do anything special

emccue23:08:15

within loop1 , loop2 is the same as any function

Bobbi Towers23:08:22

no, it's just a contrived example of mutually recurring loops

emccue23:08:35

right. loop does not handle mutual recursion

Bobbi Towers23:08:25

hmm, interesting. I haven't actually tried using a regular loop in the host language so I'll give that a try

emccue00:08:13

what is the host language you are targetting, if i can ask?

Bobbi Towers01:08:06

it's based on kanaka/mal (Make-a-Lisp)

Bobbi Towers01:08:21

I might have figured out the problem. At loop, I store just the body in a variable for recur to jump back to with the redefined locals. But I'm thinking maybe if I jump back to the actual (loop ...) form and replace the binding vector, I won't have this issue where it doesn't know which loop we are in

Bobbi Towers01:08:57

I put in some printlns to get a clear picture of the execution flow:

(defn loop1 [coll]
  (loop [s coll res1 []]
    (do (println "loop1 coll:" coll " res:" res1)
    (if (empty? s) res1
      (recur (rest s) (conj res1 (first s)))))))

(defn loop2 [colls]
  (loop [s colls res2 []]
    (do (println "loop2 colls:" colls " res:" res2)
    (if (empty? s) res2
      (recur (rest s) (conj res2 (loop1 (first s))))))))

(loop2 [[1 2] [3 4]])

loop2 colls: [[1 2] [3 4]]  res: []
loop1 coll: [1 2]  res: []
loop1 coll: [1 2]  res: [1]
loop1 coll: [1 2]  res: [1 2]
loop2 colls: [[1 2] [3 4]]  res: [[1 2]]
loop1 coll: [3 4]  res: []
loop1 coll: [3 4]  res: [3]
loop1 coll: [3 4]  res: [3 4]
loop2 colls: [[1 2] [3 4]]  res: [[1 2] [3 4]]
[[1 2] [3 4]]

Bobbi Towers02:08:38

omg I finally got it

case "loop":
    var loop_body = [types._symbol('do')].concat(ast.slice(2))
    var loop_env = new Env(env);
    var loopLocals = []
    for (var i = 0; i < a1.length; i += 2) {
        loop_env.set(a1[i], EVAL(a1[i + 1], loop_env));
        loopLocals.push(a1[i], EVAL(a1[i + 1], loop_env))
    }
    ast = loop_body
    env = loop_env
    break
case "recur":
    loopLocals.__isvector__ = true;
    // duplicate each recur form
    var recurForms = ast.slice(1).flatMap(i => [i, i])
    for (let i = 1; i < recurForms.length; i += 2) {
        let f = EVAL(recurForms[i], loop_env)
        f.__isvector__ = true;
        loopLocals[i] = f
    }
    ast = [types._symbol('loop')].concat([loopLocals, loop_body])
break

Bobbi Towers02:08:54

It seems so innocent sitting there like that. This took me like a whole week