Fork me on GitHub
#beginners
<
2018-05-07
>
bolivier01:05:19

I’ve found it’s hard to run things through the repl with a let binding that references previous bindings, because if I try to execute some expression that has that reference, it isn’t defined in that context. Is there some better way to handle this situation?

bolivier01:05:48

Specifically I’m writing a database seeding mechanism like

(let [{foo-id :id} (create-foo! { :value 10})
      {another-id :id} (create-foobar! { :foo-id foo-id})])

bolivier01:05:40

So when I eval create-foobar!, there is no foo-id and I can’t use the repl effectively.

dpsutton02:05:52

Can you paste a bit more code? I'm not sure I'm following

dpsutton02:05:55

(let [a 1 b 2] (+ a b)) 3 works for me. are you sure that (create-foo! {:value 10} is returning a map with foo-id on it?

mfikes02:05:31

Another example that is close to yours @bolivier is

(let [{foo-id :id} {:id 123}
       {another-id :id} {:id (dec foo-id)}]
  another-id)
which evaluates to 122. As @dpsutton indicates, the let bindings work. We are wondering what is breaking for you.

bolivier02:05:18

Nothing is broken, per se

bolivier02:05:45

But when I try to eval a subsection of a let binding, it fails if there is some variable that is referenced from a previous binding.

noisesmith03:05:06

right, eval doesn't see locals

bolivier03:05:17

For instance, with your cursor after {:id (dec foo-id)}, it doesn’t work

dpsutton03:05:20

What do you mean by evaling a subsection

bolivier03:05:32

I suspect it’s more about my misuse of let than it is anything else

noisesmith03:05:57

no, that's just not how evaluation works

noisesmith03:05:02

there are debugging tools that show locals, but it can't be done partially like that directly

bolivier03:05:15

Is there a better technique for figuring out the oddities of code in that situation?

dpsutton03:05:44

This should get you started. It shows you a technique such that you can do exactly what you want

dpsutton03:05:38

if you're using CIDER there is a step through debugger. I'm pretty sure cursive has one as well if you want to do that

dpsutton03:05:51

but if you have small composable functions chances are you can just inspect them in the repl

bolivier03:05:32

I’m using CIDER (since I’m already familiar with emacs). I’ll read up on the documentation on it as well.

dpsutton03:05:06

any questions about that ask in #cider and people are more than willing to help

dpsutton03:05:33

CIDER related i mean. general questions about the lang and you'll find many people here willing to help and chat

hawari.rahman1703:05:52

Hi everyone, so I have this functions in namespace A:

(defn get-fn
  [config request]
  (let [{:keys [service]} config
        {:keys [uri params headers]} request]
    (do (log/info request)
        (-> (client/get (str service uri)
                        {:headers headers
                         :query-params params})
            (select-keys [:headers :body])))))

(defn choose-method-function
  [method]
  (eval (symbol (str (clojure.string/lower-case method) "-fn"))))

hawari.rahman1703:05:42

If I were to call:

(choose-method-function "GET")
in namespace A, then I will get the get-fn function

hawari.rahman1703:05:48

But if I call that in another namespace, let's say B, then it would result an error saying that my namespace B is unable to resolve get-fn

hawari.rahman1703:05:01

Now that is understandable, but it got me thinking on why it does that? I mean, does choose-method-function context changed based on the location it was called rather than where it's defined?

hawari.rahman1703:05:40

If so, how can I create a function in another namespace to return a function in that namespace, but it should work as well when it's called from another namespace

hawari.rahman1703:05:30

Modifying choose-method-function to eval a namespace qualified symbol seems working

noisesmith03:05:34

@hawari.rahman17 - two things about that - eval is expensive, and more power than you need, you can use symbol and resolve instead. Also multimethods are designed to do this kind of dispatch directly, you don't need to hack up this kind of thing by hand

hawari.rahman1704:05:42

You're right, I forgot about multimethod. Seems like it should be the way to go for me @noisesmith.

rodrigo.juarez.inf17:05:30

Hello, I’m trying out Clojure with quil, but this doesn’t seem to work as expected

(defn draw-state [state]
  (map #(apply println %) (produce-tiles (:tile-count state))))
Produce tiles returns something like this:
([0 1 2] [0 1 3] [0 1 4])

rodrigo.juarez.inf17:05:37

Probably I’m doing something really stupid

rodrigo.juarez.inf17:05:24

In the end I want something like this:

(defn draw-state [state]
  (map #(apply draw-line %) (produce-tiles (:tile-count state))))
(defn draw-line [pos-x pos-y tile-count]
  (q/stroke-weight (/ (q/mouse-x) 20))
  (q/line pos-x pos-y (/ (+ pos-x (q/width)) tile-count) (/ (+ pos-x (q/height)) tile-count)))

rodrigo.juarez.inf17:05:59

Map to call draw-line with each one of the childs of the vector produced produce-tiles

rodrigo.juarez.inf17:05:06

(defn produce-tiles [tile-count]
  (for [y (range tile-count)
        x (range tile-count)] [(calc-pos-x x tile-count) (calc-pos-y y tile-count) tile-count]))

hiredman17:05:51

using map (lazy) to drive something you very much don't want to be lazy (drawing stuff), is likely to be a bad idea

hiredman17:05:20

map as a pattern is for when you want the result of the operation

hiredman17:05:19

common ways to process sequences when you don't care about the results are doseq or run!

rodrigo.juarez.inf17:05:21

perfect! I totally didn’t know that map is lazy, I need to take a look at those concepts from Clojure 🙂

rodrigo.juarez.inf17:05:37

kind of working now 😛, this makes me happy 😄

ramblurr18:05:28

not sure this is the right channel or not, but please tell me to GTFO if necessary 🙂 I'm creating a process scheduler (with cljs) like an operating system would have (cooperative multitasking, no interrupts/setTimeout, multi-level queues) to explore some OS ideas in clojure with immutable data and state handling.

ramblurr18:05:33

Processes are pure functions, their "local" memory is passed to them and then returned on every time-slice. They cooperatively "yield" control of the "cpu" whenever the feel like it.

ramblurr18:05:49

This has worked well so far. Each processes memory is a map in the :process-table of the kernel's own memory, itself also a map.

ramblurr18:05:39

But now I want to enable a process to start a child process.. there is a start-process function but as its first parameter it accepts the kernel memory map.

ramblurr18:05:01

Passing the kernel memory to a process (and having it become the return value) is something I want to avoid 😕

ramblurr18:05:40

What sort of pattern should I use to allow a process to start another process without making exposing the kernel memory to the process function directly?

ramblurr18:05:40

Storing the kernel memory in an atom, and making a user-land accessible start-process! function that mutates the atom is a possibility, but is there a better way?

ramblurr18:05:00

must start-process be a side effect?

michael.gaare18:05:45

@ramblurr This project sounds really cool! The way I would go about this is to have starting a process (and other system calls) be part of the return signature of your process functions. So presumably the signature right now is, (process-fn [local-memory]) => new-local-memory?

michael.gaare18:05:34

The way I’ve modeled things like this in the past is by making the signature something like, (process-fn [local-memory]) => [new-local-memory [effects]]

ramblurr18:05:01

> So presumably the signature right now is, (process-fn [local-memory]) => new-local-memory?

ramblurr18:05:06

yea, exactly!

ramblurr18:05:58

hmm that's a neat idea

michael.gaare18:05:19

You’d express your system calls as data structures in effects, so it could look something like, [:kernel/start-process :some-internal-id arg1 arg2 arg3]

michael.gaare18:05:22

or a map, or whatever you want

michael.gaare18:05:11

putting some kind of id in there might be good so that the kernel can put the outcome of the system call in the local memory datastructure somewhere so the process can see what happened

ramblurr18:05:17

one consequence of this would be that the process wouldn't know about the return-value of the system call until the next time its assigned to the cpu

ramblurr18:05:46

which seems weird, but i guess isn't different than a normal os anyways

michael.gaare18:05:48

but isn’t that the case in real systems anyway? you make a system call and you’re yielding control

ramblurr18:05:27

very cool @michael.gaare! thanks for the idea 😄

michael.gaare18:05:36

you’re welcome! good luck

sova23:05:02

Good Day everyone, I am using java-time in clojure and I have a newbie question, how can I alias java-time in my project? I just have my require lines at the top, and then a (use 'java-time) line, but I'd like to alias java-time to j or jt so I can do (jt/plus (jt/local-date 2018) (jt/years 5))

sova23:05:30

maybe there's a nice place I can read about require vs use ? or someone can give me a concise explanation 😄?

sova23:05:43

Nevermind, I figured it out looking at clojuredocs / use. There is an easy way to add it to the (ns ...) macro, namely (:use [java-time :as jt])

sova23:05:43

Hmmm... everything seems to work great except I cannot seem to call java-time/interval

sova23:05:12

Oh, or it might be because there is an interval method in joda-time but not in java-time...

sova23:05:57

I'm hoping I'm wrong here, but as far as I can tell java-time does not actually implement (interval o) ;_;