Fork me on GitHub
#clerk
<
2023-03-10
>
genmeblog12:03:33

I have an issue with caching/state inside clerk/example . Code snippets and results in the thread.

genmeblog12:03:30

Having following code:

(def rng1 (java.util.Random. 2288)) 

^{::clerk/no-cache true}
(clerk/example
 (repeatedly 3 #(.nextDouble rng1))
 (repeatedly 3 #(.nextDouble rng1))
 (do (.setSeed ^java.util.Random rng1 2288) rng1)
 (repeatedly 3 #(.nextDouble rng1))) ;; <------ seed is not set!

(def rng2 (java.util.Random. 2288)) 

^{::clerk/no-cache true}
(repeatedly 3 #(.nextDouble rng2))
^{::clerk/no-cache true}
(repeatedly 3 #(.nextDouble rng2))
^{::clerk/no-cache true}
(do (.setSeed ^java.util.Random rng2 2288) rng2)
^{::clerk/no-cache true}
(repeatedly 3 #(.nextDouble rng2)) ;; <------- seed is set back to 2288

genmeblog12:03:37

Moreover. With this code (aftere clearing cache):

(def rng1 (java.util.Random. 2288)) 

^{::clerk/no-cache true}
(clerk/example
 (.nextDouble rng1)
 (.nextDouble rng1)
 (do (.setSeed ^java.util.Random rng1 2288) rng1)
 (.nextDouble rng1))

(def rng2 (java.util.Random. 2288)) 

^{::clerk/no-cache true}
(.nextDouble rng2)
^{::clerk/no-cache true}
(.nextDouble rng2)
^{::clerk/no-cache true}
(do (.setSeed ^java.util.Random rng2 2288) rng2)
^{::clerk/no-cache true}
(.nextDouble rng2)

genmeblog12:03:25

Everything looks ok, unless I add another

^{::clerk/no-cache true}
(.nextDouble rng2)
somewhere below.

genmeblog12:03:34

Then everything is messed...

genmeblog12:03:50

(it's not deterministic though 😕 )

genmeblog12:03:05

Global no-cache solves the issue. well, doesn't solve...

genmeblog09:03:17

@U5H74UNSF can you look at this? thanks!

mkvlr09:03:22

@U1EP3BZ3Q unlikely I’ll have much time to look into this before next week

mkvlr09:03:39

don’t fully understand looking at the pictures what the problem is

mkvlr09:03:01

is it related to clerk/example or not?

genmeblog09:03:57

Originally I thought it was related to clerk/example

genmeblog09:03:16

My later experiments have shown that it appears also with regular forms

mkvlr09:03:47

could you create an issue with the minimal repro?

mkvlr09:03:29

thank you!

genmeblog09:03:57

well... 🙂 when I apply no-cache to def forms as well it works. I don't know why I missed that previously :/

genmeblog09:03:01

Sorry guys for generating false positive case

genmeblog09:03:14

(anyway still experimenting)

genmeblog10:03:17

Ok, found it. It affects clerk/exemple only when sequences are returned: https://github.com/nextjournal/clerk/issues/435

Andrea13:03:17

Hi @U1EP3BZ3Q, thanks for the repro. I think this behaviour is not strictly due to a caching issue, but rather something in clerk’s eval phase which forces the top-level lazy-sequences constructed with repeatedly (Case 2) but not when they’re nested into other collections, like it’s the case for the code emitted by the clerk/example macro (Case 1). If in your example, you force your lazy seqs with e.g. a doall in your first case, you get back the expected behaviour. In Case 3, no lazyness is involved. That said, if we’d expect lazy seqs to be forced only at display time and not at eval time, then .setSeed would always be called before calls of .nextDouble. Is this correct? I don’t have a clear picture of what’s going on exactly.

genmeblog14:03:35

I've started to suspect that lazyness could be involved here but didn't check this. Yes, if lazy seqs are evaluated at display time then setSeed is called before generating random numbers.

genmeblog14:03:15

Anyway it would be great to have clerk/example evaluating examples step by step.

Andrea14:03:59

> if lazy seqs are evaluated at display time and I don’t think this is the case, at this spot https://github.com/nextjournal/clerk/blob/23214a719e191c822901b749bf5f8be867421066/src/nextjournal/clerk/eval.clj#L139 I think we force seqs to check they stay within some limits prior to computing their hash and that’s right after their evaluation

Andrea14:03:55

> evaluating examples step by step but then you’d also have to use eager seqs, right?

genmeblog14:03:44

It works like that without clerk/examples , ie. forms are evaluated in the order they appear (case 2).

genmeblog14:03:38

I treat clerk/examples as a nice way to display (kind of) repl session, so the order of evaluation and print should be preserved.

Andrea14:03:54

the order is correct in both cases, but the clerk/example macro wraps single forms in a vector which gets evaluated all at once

genmeblog14:03:29

Yep, got it, so the only way is to force lazy seqs to be eager. Wrapping into vec works.

👍 2
genmeblog14:03:08

Still, from dumb user perspective there should be no difference between forms wrapped into clerk/example (or possible other forms) and unwrapped. 🙂 Just the opinion.

genmeblog14:03:30

Wrapping into clerk/table also reveals this issue.

Andrea15:03:59

> there should be no difference I agree 🙂, the somewhat confusing part is that the unwrapped behaviour is somehow off wrt clojure lazyness

genmeblog15:03:50

Ok, corrected issue title and left a comment as a summary of our discussion.

genmeblog15:03:03

Thanks for the discussion!

mathpunk20:03:50

I’ve got either a best practices question or possibly a bug report (I’m using @sritchie09’s clerk-utils)…. I’ve been making files in my notebooks directory and doing literate programming to write about a problem I’m trying to understand and solve. If an exploration gets lengthy, it seems to make sense to start a new file that builds on previous work. But I think there might be inconsistencies in how namespaces get loaded, and displayed. Observations/example in 🧵

mathpunk20:03:59

Example: Say I’ve got notebooks/mathpunk/some_problem/day_01.clj. If I start a day_02 file, I can reference that namespace. But if I close the clerk watcher, when I go back and edit day_02, it doesn’t find the namespace, until I go and edit day_01, and then day_02 will be able to find it. Okay so, maybe instead the Right Way is to extract functions for reuse into the src directory. But when I’ve edited something in the src directory, I’m not seeing Clerk automatically show file while I’m editing it.

mathpunk20:03:20

I could be holding things wrong, I could be a few commits behind, etc

Sam Ritchie20:03:36

The issue might be that “notebooks” is not listed in the paths specified in deps.edn

Sam Ritchie20:03:26

So when you require, day1 isn’t seen on the class path until you manually load it

Sam Ritchie20:03:07

The watcher issue is probably that you’ve only passed “notebooks” to the watcher in dev/user.clj. You can add “src” to that list if you like!

Sam Ritchie20:03:52

Apologies if this is my template and it’s been confusing; let me know what we should change here to make the experience better. Adding notebooks to deps.edn seems like a no-brainer here

mathpunk20:03:38

hmmm

:paths ["src" "dev" "notebooks" "artifacts" "data"]

mathpunk20:03:12

I think notebooks started out in the template

Sam Ritchie20:03:27

Interesting… @U5H74UNSF any ideas?

mathpunk20:03:46

it’s POSSIBLE i added these things after observing that…

mathpunk20:03:28

sidenotes, I haven’t gotten the hang of dev dependencies…. do people use that for their repl utility belts then?

mathpunk20:03:32

I’m going to try and reproduce what I’m complaining about, lest I encourage you to chase an unmannered goose

❤️ 4
Sam Ritchie20:03:42

When I am developing a library I will have dev dependencies for things like test runners, or maybe something like SCI where I don’t want to force the dependency on someone

mathpunk20:03:06

it really looks like editing something in src is not displaying it

mathpunk20:03:12

while notebooks, yes

mathpunk20:03:31

there’s two .edn files right? a bb.edn and a deps.edn?

Sam Ritchie20:03:08

This setting controls what directories get watched

Sam Ritchie20:03:41

Some people don’t like source to get watched since maybe it’s a collection of utilities for example and you don’t want Clerk navigating away from your notebook while you work on that

mathpunk20:03:27

I thought that it was the :paths in deps.edn that mattered here

Sam Ritchie20:03:31

Is there a chance that your namespaces don’t match the file path?

mathpunk20:03:32

I’ve barely looked at dev.clj

mathpunk20:03:42

there is absolutely a chance my namespaces don’t match the file path

Sam Ritchie20:03:16

That might be it. Is this a Clojure problem too? Like is it just clerk that can’t find notebook 1 from 2, or the repl as well

Sam Ritchie20:03:53

I guess you wouldn’t know if you’re only using the bb task! That is another guess though, that would break the namespace resolution in require

Sam Ritchie20:03:28

Should be mathpunk.some-problem.day-01

mathpunk21:03:56

Cool. Notebooks can refer to other notebooks, if the user has the namespaces right

mathpunk21:03:17

And if I want editing src to trigger a view change, put it in dev.clj

Sam Ritchie21:03:28

Dev/user.clj, that’s right

mathpunk21:03:48

thanks, looks like it was a liveware problem :)

Sam Ritchie21:03:03

Haha well, the tech should mold to us ideally

Sam Ritchie21:03:30

But keep notes on what you want the “explore problems with Clerk” experience to feel like, I’m super interested

mathpunk21:03:37

broadly: • explore in a literate way — writing is as or more important than coding to get me to understand a new thing • reference previous work • extract what’s reusable to a library or “script” file

Sam Ritchie21:03:24

Hard agree on all! I want a world where maybe 3 isn’t as necessary (the extract part), or at least the extraction brings along a bunch of the writing and exploration

mathpunk21:03:29

and probably • generate a ✌️site ✌️ or something for people who aren’t running Clojure

Sam Ritchie21:03:41

That should work from the template already

Sam Ritchie21:03:03

And I agree it’s critical

mathpunk21:03:11

yes, I just haven’t gotten there yet. Also we’re on Gitlab rather than Github, there might be differences in the way they do their “Pages”

👍 2
Sam Ritchie21:03:37

I want a https://Maria.cloud mode that opens a clerk notebook for live editing / exploration there

mathpunk21:03:10

also i should mention, I haven’t even been turning on my repl in my editor, just because I think I misconfigured some stuff

mathpunk21:03:24

so it’s nice to be able to still get this live coding experience, but i also should take some time to fix that

👍 2