Fork me on GitHub
#clojure
<
2016-10-24
>
jotaro00:10:57

@gfredericks yes, that would be good. sorry for late response.

gfredericks00:10:57

@jotaro I think generally the innermost ones have to be executed first, since otherwise the outer ones don't have a well-defined object to be applied to

jotaro00:10:48

@gfredericks hm, that's reasonable. Is there any source to check the real code?

jotaro00:10:20

and much thanks. I need more investigation simple_smile

gfredericks00:10:41

I think experimenting at the repl is likely to be more efficient

dadair02:10:00

Is it possible to provide a simple string in the db-spec for HugSQL? (i.e., jdbc:<postgresql://host:port/db?user=USER&password=PW>) I’ve tried :connection-uri, :uri, raw string (not map), and keep getting Invalid dbspec format from jdbc.impl Alternatively, is there anything that parses a jdbc string and transforms it into a suitable db-spec map?

hiredman02:10:17

wrap it in a java URL or URI (I forget which)

hiredman02:10:26

I mean, I dunno, the error you are seeing likely isn't from hugsql at all, but from clojure.java.jdbc, so if you look at the docs for clojure.java.jdbc's get-connection function, and see how it describes its dbspec format

dadair02:10:58

Get NPE if just straight URI, invalid dbspec otherwise =/

vigilancetech06:10:51

does anyone know where I can find boot-bucket?

sveri07:10:09

@dadair For clojure.java.jdbc I use {:connection-uri db-url} as db-spec and it works for me

igosuki09:10:41

hi guys, say I have a java interface

public interface KVM<K, V, R> { 
    R some(K k, V v);
}
Is it impossible to reify it ? I get "Can't define method not in interfaces” when trying the following :
(deftype GenericKVM []
  KVM
  (some [k v]
    nil))

mpenet09:10:20

its missing the "this" argument

mpenet09:10:31

some [this k v]

blkt11:10:11

hello everyone

blkt11:10:40

is there a way to limit pmap's threads pool?

blkt11:10:00

say, something less than 2 + cpus available

val_waeselynck11:10:31

@blkt I don't think so, but making your own implementation by adapting the source should be pretty straightforward

mhjort12:10:53

@blkt I've been using Claypoole library when there's a need for better control for thread pool. https://github.com/TheClimateCorporation/claypoole

eslachance13:10:30

@kumarshantanu sorry if I'm a bit late but thanks for the lein deps command, that made me see that it's required by http.async.client.

amacdougall13:10:36

I'm trying to extend and modify some existing code, and I'm not sure of the right approach. I have a namespace called (to simplify slightly) svg.core. You feed it this grid structure, and it renders it out as an SVG graph: render calls render-cell, render-cell calls render-rect (for the graph boxes) and render-line (for the connections among them). So far, so good! But now I want the option to pass in some metadata and get some additional styling. In an OO language, I would define a subclass of my renderer, and override only the functions which are different (let's say render would take a single extra argument and set an instance variable, and then render-rect and render-line would change to read that instance variable). In Clojure, however, I'm not entirely sure of the best approach. If I make a new namespace with a top-level render which calls svg.core/render, well, svg.core/render is going to call all the svg.core versions of functions, not the ones in the new namespace. I suspect that I'm approaching things from the wrong angle.

amacdougall13:10:55

I could just mush all the additional behavior into svg.core, since I'm already passing around a big render-environment map with a bunch of optional formatting properties, but that seems like a recipe for disaster.

mtnygard14:10:11

@amacdougall You have a bunch of options.

mtnygard14:10:37

- You could define a protocol for the renderer and supply an instance of that protocol.

amacdougall14:10:51

I've been researching protocols and multimethods, but I just don't understand them well enough to know how to apply them here.

mtnygard14:10:25

That would be wide-open for extension, but each new renderer might need a bunch of similar code.

mtnygard14:10:47

So you'd use the instances to coordinate calls to more atomic functions for e.g., drawing a styled box.

mtnygard14:10:00

Then different renderers could use the same atomic functions but pass different arguments.

mtnygard14:10:32

- Alternatively, you could define all your style attributes as data and pass that around

amacdougall14:10:27

Yeah, the main thing is that I want to re-use existing code with just minor embellishments. For instance, it would be entirely acceptable to do:

(defn render-cell [env grid]
  (let [env (...modify things...)]
    (into (svg.core/render-cell env cell) ; uses the formatting from the modified env
      (render-extra-stuff ...))))

amacdougall14:10:58

That env thing contains a ton of style attributes already, yeah. The idea was that the consumer can say (svg/render {...lots of format options...}).

mtnygard14:10:32

OK, so if you want to go with protocols, they might look like this:

mtnygard14:10:15

(defprotocol Renderer (render-cell [this env grid])) (defrecord PlainRenderer [] (render-cell [_ env grid] (svg.core/render-cell env grid))) (defrecord StylingRenderer [base customizations] (render-cell [_ env grid] (into (render-cell base env grid) (render-extra-stuff customizations ,,,))))

amacdougall14:10:56

Oh interesting... I never quite realized that defrecord could be used to produce (if you'll pardon the Java-ism) "thing-doers".

amacdougall14:10:18

What's the this?

mtnygard14:10:22

Yeah, it's like ala-carte OO.

mtnygard14:10:35

this is the self-pointer for the object.

amacdougall14:10:09

Oh, I get it—if I were implementing a special data structure or something, this would be more meaningful. But in this case, we don't really care about the object.

amacdougall14:10:54

Then again, perhaps that complex env I'm passing around is a good candidate to be the renderer record? ...that strikes me as too closely coupled.

mtnygard14:10:40

Maybe. It's hard for me to judge. But we generally say that data is better than functions, which are better than macros.

mtnygard14:10:32

My advice would be to express "what you want" in the data and use functions for "how to produce the effect". Protocols are for "different ways to produce the effect."

amacdougall14:10:27

Yeah. I think this will be really helpful. I'll try it out!

amacdougall14:10:23

Ah, I see—with this approach, the metadata I want to render would be an additional property of the renderer, not an additional function argument. I have a feeling that I will still end up having to duplicate some of the higher-level stuff, though. For instance, the current top-level render function is:

(defn render
  "Given a render environment and a grid, returns an SVG rendering as Hiccup
  data structures. All numeric values are in user units."
  [render-env grid]
  (into (svg render-env)
        (map (partial render-cell render-env)
             (g/all-cells grid))))
And if I had two different Renderer protocol implementations, I would have to do:
(defrecord PlainRenderer []
  (render [env grid]
    (...as above, calling the base version of render-cell)))

(defrecord StylingRenderer [metadata]
  (render [env grid]
    (...as above, but calling a specialized version of render-cell)))

amacdougall14:10:41

Only render-cell has a substantially different implementation here, but the render function has to be different in order to call it, right? I can think of workarounds, but they're all clumsy—again, I think I'm missing some perspective.

amacdougall14:10:48

This isn't onerous, though. I'll try it!

amacdougall15:10:37

So this works fine:

(defprotocol Renderer
  (render [this grid])
  (render-cell [this grid]))

(defrecord PlainRenderer [env]
  Renderer
  (render [this grid] (map (partial render-cell this) (g/all-cells grid)))
  (render-cell [_ cell] (format "render-cell [%d %d]: plain" (::g/x cell) (::g/y cell))))

(defrecord FancyRenderer [env metadata]
  Renderer
  (render [this grid] (map (partial render-cell this) (g/all-cells grid)))
  (render-cell [_ cell] (format "render-cell [%d %d]: fancy! %s" (::g/x cell) (::g/y cell) metadata)))

(let [grid (g/create-grid 2 2), env {}
      r (->FancyRenderer env {:a 1})]
  (render r grid))
My only problem is that the implementation of render is duplicated. But it's not truly duplicated, because render-cell refers to the specific protocol's implementation in each case. I can live with this. But I'm curious whether there's a general solution to this shared-implementation situation.

achesnais15:10:25

@amantena any reason why you’re using a record instead of a multi-method if you’re looking for different implementations depending on a dispatch value, and don’t care about the this object?

achesnais15:10:06

oh haha just read further above, sorry

achesnais15:10:34

Based on what I’m reading above, I’d suggest you group all your custom styling stuff into one data structure (a config map) and then pass this around as the first arg or your multimethod calls

amacdougall15:10:51

Yeah, I was considering making the specialized metadata (specifically, a distance map generated by Dijkstra's Algorithm) be just another key of render-env. Then if it exists, I could delegate to an implementation which can handle it.

amacdougall15:10:19

At this point, I probably shouldn't worry about whether render-env picks up too many passengers. Passing big data structures around seems pretty idiomatic anyway.

amacdougall15:10:41

So in this approach, I'd have a core namespace with a defmethod for each function which might have multiple implementations, and they'd just point to namespaced methods. Hm... and if the implementation of render should be the same in each case, I guess I could implement it in the core namespace, so that the render-cell it's invoking is the multimethod. I think that might clear things up a bit.

sophiago15:10:14

hi. is this an appropriate place to ask about help with lein/maven related stuff? i don't come from a jvm background and have been trying to get checkouts working for the first time all weekend 😛

sophiago15:10:21

i'm often on irc, but trying here for the first time in case possibly different hours/crowd may yield further resources

val_waeselynck16:10:08

@sophiago you may want to check out the #leiningen channel

sophiago16:10:25

@val_waeselynck ah, did not know there was one! hope it's active, but from their github i would imagine quite welcoming and friendly 🙂 thanks!

val_waeselynck16:10:59

@sophiago you're welcome, good luck!

amacdougall16:10:20

@achesnais: I think this approach is going to be the simplest. With some test code, it's working fine! @mtyngard: Thanks for your help as well—I understand protocols better now.

jrheard16:10:53

@amacdougall whatcha working on? 🙂

amacdougall17:10:32

@jrheard: In the long run, I'm trying to make a system which randomly generates world/city/etc maps, and then overlays a plausible interactive-fiction-style map whose structure and descriptions accurately reflect the world. "Path approaching lake", etc. In the very long run, I aim to make a single-player party-based MUD-like rogue-like RPG. In the short run, I'm giving a tech talk at work where I describe my progress on maze generation and solution—so I want to upgrade my re-frame app to show the inner workings, step-by-step progress, and ultimate solution of Dijkstra's Algorithm.

jrheard17:10:07

nice! i’m looking into randomly generated maps for roguelikes too!

jrheard17:10:20

setting my sights much lower than yours, but we’re at least working on the same subject matter

jrheard17:10:37

i’ve been working with http://www.gridsagegames.com/blog/2014/06/mapgen-cellular-automata/ as my starting point, this guy’s whole series of posts on map generation is great

jrheard17:10:43

and, like, all of his other posts

amacdougall17:10:48

I've read a lot of resources about roguelike dungeon generation, but my particular input (a large open world) and output (MUD-style linked rooms) means that a lot of the rooms-and-tunnels generators are less relevant. I'm still figuring out what I'm going to do.

amacdougall17:10:43

But I think that I'm going to devise and tweak maze generation algorithms so that they generate "sparse mazes" (i.e. grids where not all cells are reachable), and then try to overlay algorithms upon terrain areas generated by more conventional algorithms.

jrheard17:10:45

so your rooms/world will be more like a graph with nodes/edges, rather than a 2d grid of full/empty cells? or somewhere inbetween?

amacdougall17:10:56

So if I know that a certain area of the world grid is rolling plains, I can use a maze algorithm which generates highly interconnected adjacent squares, to create visibility and mobility. If the area is a mountain pass, I can use a maze algorithm biased heavily toward up and down movement and narrow passages with few branches, trending toward the exit of the mountain pass. Then stitch the mazes together to form the overworld.

amacdougall17:10:31

It's going to be a Euclidian 3D grid space, but such as grid can easily be represented as a graph.

jrheard17:10:53

sounds like a great project!

amacdougall17:10:58

(grid/move grid cell ::grid/east) gives you the cell one step east of the supplied cell, for instance.

amacdougall17:10:13

You can see my paltry existing progress at http://github.com/amacdougall/mazes.

amacdougall17:10:33

I'm really just starting by working through Jamis Buck's Mazes for Programmers, translating from Ruby to Clojure.

fellshard17:10:44

^^ Hahahah I was doing the same

fellshard17:10:01

And came up with a lot of the same kinds of abstractions 😄

jrheard17:10:09

nice, i’m http://github.com/jrheard/voke (the ‘generation’ branch); a several-days-out-of-date version of my extremely basic dungeon level explorations is at http://jrheard.com/voke/generation.html

amacdougall17:10:12

It's been a good exercise!

amacdougall17:10:35

Hey, cool! I'll check it out.

jrheard17:10:54

likewise 🙂 keep us posted on your progress!

amacdougall17:10:10

Hey, this is fun to watch!

jrheard17:10:19

you kinda start rooting for the little green dot

jrheard17:10:26

the idea’s to have this tool help visualize what the algorithms are actually doing, so i can see how the finished result is arrived at; i haven’t done this for anything besides the simple drunkard’s walk algorithm yet, but i plan to get around to doing it for every algorithm i explore

jrheard17:10:02

in the meantime it’s been handy to have sliders like this so i can easily see what effect different thresholds / input values have on the finished product

jrheard17:10:33

i don’t have much intuition around cellular automata birth/survival thresholds, but i can drag sliders around and say “that looks like a cave” or “that doesn’t look like a cave” 🙂

amacdougall17:10:53

Yeah, I've gone kind of the same route, if you lein figwheel my own app—it's a simple web UI for generating and displaying mazes. I'm hoping I'll be able to add a step-by-step solution demo in time for that presentation...

jrheard17:10:08

i’ll take a look!

jrheard17:10:18

oh nice, this looks like a super handy tool for the problem you’re working on

josh.freckleton18:10:48

what are the best practices for connecting to a postgres database? I notice a lot of options and want a decision I won't regret in months 🙂

josh.freckleton18:10:04

@trptcolin interesting, I'd started along with duct yesterday, wanting to learn component simultaneously, but then decided to go the mount route instead for now, based on things I read about both.

josh.freckleton18:10:15

I'll look into hikaricp with mount

josh.freckleton19:10:40

@trptcolin thanks for putting me on the trail of Hikaricp, i just implemented hikaricp, mount, and a connection pool to postgres,

josh.freckleton19:10:51

does it look alright, or is there anything i need to tweak?

hiredman19:10:51

I am curious what you read about mount and component that lead you to pick mount

trptcolin19:10:42

@josh.freckleton as long as it works, the hikari stuff looks fine - may want to tweak timeouts or add additional config options, but nothing that's going to take long to change. on projects i work on, i'd typically lobby for component (due to its non-global-ness), but i don't have time to make that case here

josh.freckleton19:10:13

@trptcolin @hiredman i'm still happy to change my mind about deciding on mount, basically it seemed lighter-weight (lib vs. framework(ish), can be added in at any time vs not.), and more inline with how I understand clojure's philosophy. I also saw, among other research, a blogpost by, I think it was yogthos, that seemed to support that view. I'm choosing between the two libs for new projects (which if not, could preclude component), and I'd love any direction, or resources you could point me to in making that decision!

hiredman19:10:07

I would draw exactly the opposite conclusion

hiredman19:10:11

and I have had this argument with yogthos

hiredman19:10:23

and he is very wrong

hiredman19:10:19

component is simpler and a more principled way to structure runtime state

hiredman19:10:49

mount is, as far as I can tell, global atoms with extra bits

josh.freckleton19:10:52

> mount is, as far as I can tell, global atoms with extra bits ya, i formed my opinion of mount before using it, and now that i've gotten some demo code working, i kindof agree with you and i think i'm missing the "promise" that mount offers, so, time for me to update my belief

josh.freckleton19:10:20

but i still can't see that component is better, due in part to not understanding it all the way

josh.freckleton19:10:45

@trptcolin thanks, i'd looked those over, and probably will again now.

yogthos19:10:23

@hiredman my experience using both mount and component has convinced me that I’m very right 🙂

yogthos19:10:18

I have yet to see a clear argument for any tangible advantages to using component

trptcolin19:10:12

wow! that's a pretty strong statement. i'd certainly agree there are tradeoffs, but seriously you claim no tangible advantages??

yogthos19:10:23

what are they?

trptcolin19:10:41

i'm not going to rehash

yogthos19:10:43

what I’ve noticed often happens in practice is that systems built with component tend to pass state all over the place as a variable

yogthos19:10:54

and then you can’t even test anything without having to create mock resources

yogthos19:10:08

mount encourages keeping resources at the edges, and having a pure business logic core

trptcolin19:10:10

explicitness has advantages

trptcolin19:10:16

as does implicitness

yogthos19:10:30

they’re a different way to address the problem

yogthos19:10:38

what I’m saying is that both seem to work equally well

trptcolin19:10:50

despite one having no tangible advantages

yogthos19:10:56

hence I don’t see advantages of one over the other

yogthos19:10:06

that’s what working equally well means

yogthos19:10:46

if anything I think mount has the advantage of managing all the relationships automatically, where you have to do that by hand with component

trptcolin19:10:48

it's hard for me to believe you'd have said "I have yet to see a clear argument for any tangible advantages to using mount"

yogthos19:10:57

once your dependency graph gets big enough, it’s not exactly a lot of fun

fellshard19:10:05

You're talking past each other 🙂

fellshard19:10:41

He's arguing they are equal choices, not that there is no reason to use component

fellshard19:10:33

CSE 341?? That's the olden days of the undergrad PL course!

trptcolin19:10:12

i'm going to roll my status back to > i'm not going to rehash > sorry

yogthos19:10:29

if you really like to pass your resources around explicitly, that works perfectly fine with mount

Prakash20:10:44

I think mostly being explicit with resources is more clear and maintainable, definitely more testable 😄

donaldball20:10:23

I like the way component encourages me to think carefully about my stateful resources and the protocols they may present to my application

yogthos20:10:01

@pcbalodi I find that keeping resources at the edges makes things more testable, whether you pass resources as an argument or reference a var, you’re still tying them to your business logic

yogthos20:10:31

I would argue that if you need resources for most of the testing, then there’s too much coupling going on

yogthos20:10:50

@donaldball note that mount is perfectly compatible with using protocols

yogthos20:10:24

I can define a protocol for a resource and then manage the state of the resource using mount

donaldball20:10:24

Of course. It just doesn’t seem to encourage that as a matter of course, while component nudges you pretty heavily in that direction.

Tim20:10:24

@yogthos are you not essentially referencing a var in some way with mount?

yogthos20:10:13

that’s the most common way, the other option is to use yurt and to create a system the same way you’d do with component

yogthos20:10:44

note that mount vars are reload aware, so you don’t have the problem of getting into a stale state that you have with regular vars

donaldball20:10:50

Far as I can tell, for an application with e.g. a database, a message queue, and an email sender, mount will give you a var for each and the fns that need them will reference them directly. Component would suggest one system atom or var for all the state, and fns that need stateful resources should expect them to be passed in.

yogthos20:10:46

typically you would use a namespace to house the var for mount and the functions there could either use it implicitly or have it passed in

yogthos20:10:59

mount is completely unopinionated in that regard

donaldball20:10:06

Some find the ambient state nicer and requires less fiddly orchestration. Some find the explicit state nicer and easier to compose in novel ways.

yogthos20:10:11

you could even have a protocol same way as with component

yogthos20:10:32

if you use yurt, then you get an explicit system that you can pass around

yogthos20:10:05

one thing that mount does for you though is automatically build the hierarchy of resources, you have to manage this by hand using component though

yogthos20:10:56

but you can use both mount and component in exact same way, mount is just less opinionated, while component can only be used one specific way

sveri20:10:40

When mount came out, I switched an application back and forth between mount and component and found mount to be less reliable over restarts

sveri20:10:03

But that was a year ago, these problems might be fixed already

hiredman20:10:26

nonsense, I've seen applications use component to setup big hair balls of global state too, but at least it isn't the default

yogthos20:10:02

I actually find that it is

danboykis20:10:14

sveri it's probably because in the beginning it probably was less reliable since it was new, I've been using it in prod for a while now and haven't had any restart issues

hiredman20:10:18

I think the best argument for how to organize things is a quote from rich

yogthos20:10:21

most code I’ve seen in the wild using component ends up threading state all over the place

hiredman20:10:24

You want to build components up from subcomponents in a sort of direct injection style. You don't want to, like, hardwire what the subcomponents are. You want to, as much as possible, take them as arguments because that's going to give you more programmatic flexibility in how you build things.

yogthos20:10:50

sure, but mount isn’t at odds with that in any way

hiredman20:10:52

that is entirely the point

hiredman20:10:02

threading state makes it explicit

yogthos20:10:08

the point is you shouldn’t be coupling your business logic to resources

yogthos20:10:19

I’m sure Rich isn’t advocating doing that anywhere at all

yogthos20:10:42

component makes it easy for state to bleed into your business logic

yogthos20:10:52

hence why people have these elaborate mocking setups with it

donaldball20:10:59

FWIW that has been precisely the opposite of my experience

hiredman20:10:02

where if you don't thread it, and instead just call some function that calls another function, and somewhere down that callstack it fiddles some global state, how it not that not coupled? and shouldn't that coupling be evident?

danboykis20:10:15

hiredman I asked rich about it at the last clojure conj, he's using one atom to store everything, doesn't use either component or mount

yogthos20:10:21

that’s not what I’m advocating at all

yogthos20:10:39

I’m saying that the core business logic should be pure and the code that deals with resources should be kept at the edges

yogthos20:10:46

regardless of how you mange its state

danboykis20:10:48

hiredman if datomic was open sourced we'd know for sure

hiredman20:10:13

@danboykis you'll notice I didn't say it was a nargument for component or mount, just that it is an argument for how to organize your code

yogthos20:10:13

I think the point @danboykis is making is that Rich doesn’t always organize code this way himself

hiredman20:10:42

shrug I don't know the context @danboykis asked in, or the context that rich was replying in

hiredman20:10:10

datomic hold state in a single atom doesn't mean anything in component vs mount

weavejester20:10:14

I don’t think component makes it easy to bleed in state per se. I think it’s more that components look like objects, and so people are inclined to treat them that way.

yogthos20:10:15

the main point here though is that you can use mount exact same way as component, and you can pass state around explicitly

hiredman20:10:17

either can have a single stateful atom

sveri20:10:22

@danboykis I never tried it in production, only in development, which is where I need a lot of restarts and this is where I had problems

yogthos20:10:34

@weavejester yes, that’s a better way to put it

weavejester20:10:52

Ideally one should ask the question - does this have a start/stop or open/close or setup/cleanup? If yes, then make it a component. If no, then don’t.

danboykis20:10:14

@sveri was it clojure or clojurescript?

danboykis20:10:16

my primary experience is in clojure and depending on how early you tried it you might've experienced bugs, i know that the last say 6 months i've been restarting a bunch and never had issues

sveri20:10:20

@danboykis It was clojure, never tried it in clojurescript and yes, I never tried it again afterwards. Would be nice if he figured out all the problems 🙂

danboykis20:10:41

i believe he did

danboykis20:10:18

although i don't know your code/use-case so I can't state that authoritatively 🙂

sveri20:10:11

🙂 I settled on components afterwards. I dont see that much benefits in mount over component, so it is not worth the hassle for me changing my template

danboykis20:10:03

out of curiosity what made you choose mount in the first place?

sveri20:10:59

One year before mount came out I was trying out component and had a hard time getting it running within my web template. And when it came out I was just curious and liked how easy it was to setup.

sveri21:10:48

I would be using mount now if the restart would have been hassle free back then when I tried it, but, it wasnt and so I stayed with component.

jrheard21:10:00

@amacdougall i promise i won’t ping you about this often, just figured i’d mention in case you’re interested - i’ve uploaded the latest version to http://jrheard.com/voke/generation.html , got rid of animation in favor of stable rng (so the sliders all sort of function as history sliders), which makes the tool 100x more useful for me because now i can see what these various settings to do specific generated maps 🙂

jrheard21:10:33

also i stopped using reagent to draw the grid portion of the tool (seemed like a good idea at the time…) and am just using a canvas, because reagent is super awesome for interactive UI but isn’t quite intended for rapidly drawing thousands of changing <div>s 😄 ended up speeding the thing up by ~6x

fellshard21:10:19

Love the ability to forward and backtrack along a single generation in the Drunkard's Walk

fellshard21:10:03

Are you memoizing the randomly generated values for each parameter or something?

fellshard21:10:29

Or just using a stable seeded RNG?

jrheard22:10:38

(sorry, in transit) - the latter

jrheard22:10:09

i’m toying with the idea of adding a save-map-to-gallery button, so you can play around with a few favorite slider settings and then see their results side-by-side, and that’ll probably look like a simple combination of those two

jrheard22:10:27

where a saved state is like (rng-seed & [algorithm-params])

jrheard22:10:16

i was surprised to find that vanilla js doesn’t support seeding your random number generator; i poked around and quickly found http://davidbau.com/archives/2010/01/30/random_seeds_coded_hints_and_quintillions.html#more , which i plopped into my application without looking at it too closely

jrheard22:10:57

the code’s in https://github.com/jrheard/voke/blob/generation/src/voke/world/visualize.cljs ; it’s a WIP, still needs lots of cleaning up (there are traces of an animate-this-grid’s-generation feature that’s been obsoleted by having stable rng, still need to track ‘em all down and delete ‘em), particularly in voke.world.generation, but linking in case it’s helpful to anyone 🙂

jrheard22:10:42

(i should probably have written all of this in #clojurescript, oh well)

fellshard23:10:06

> i was surprised to find that vanilla js doesn’t support seeding your random number generator tbh that's not terribly surprising, given it's JS. 😛