beginners

Getting started with Clojure/ClojureScript? Welcome! Also try: https://ask.clojure.org. Check out resources at https://gist.github.com/yogthos/be323be0361c589570a6da4ccc85f58f.
Fredrik 2021-06-27T01:30:26.057700Z

You're right, I was being crude. I should have said: Having defined a spec, you also get more than something just capable of producing boolean-valued expressions, like ways to generate data of wanted shape and s/conform to "pick apart" and say in what way a value satisfies a spec.

alexmiller 2021-06-27T02:21:44.058Z

:thumbsup:

km 2021-06-27T02:46:12.059600Z

Hey guys, I'm trying to design a running delay. Multiple processes could add time to the delay, and a function would run whenever the remaining time reaches zero. Any ideas how to simply implement this?

2021-06-27T02:50:34.061900Z

The easiest is just keep an atom, and have a loop that reads the atom sets it to 0, and sleeps until the atom is 0

1๐Ÿ™Œ
2021-06-27T02:50:57.062500Z

Adding a delay is just swap + n on the atom

2021-06-27T02:54:52.062600Z

If you read a string like that from a file or user input, there is no need to escape them.

2021-06-27T02:55:42.062800Z

If you have a string typed into your Clojure source code, then it is a lot like a Java or C string, where there are special characters like \n for a newline, so a backslash itself must also be escaped if you want a backslash in the resulting string.

2021-06-27T02:56:21.063Z

I've never heard of anyone writing a bit of code that takes such strings you want to put in your source code, and escape them for you, but it wouldn't be difficult to write one if you really want it.

2021-06-27T02:56:43.063200Z

Most such strings in source code are relatively infrequent, and I believe developers typically escape them by hand-editing their programs.

olaf 2021-06-27T09:40:57.067100Z

(def pika-evolutions    (r/atom ["Pichu"
                                 "Pikachu"
                                 "Raichu"]))
(def selected-evl (r/atom nil))

(defn vec-remove
  "Remove elem in coll"
  [pos coll]
  (into (subvec coll 0 pos) (subvec coll (inc pos)))) ;; <--- Uncaught Error: Index out of bounds

(defn remove-evolution-form []
  [:div
   (into [:select {:size 4
                   :on-change #(reset! selected-evl (-> % .-target .-value))}]
         (for [idx (range (count @pika-evolutions))]
           (let [evl (get @pika-evolutions idx)]
             [:option {:key evl
                       :value idx} evl])))
   [:button
    {:on-click (fn []
                 (let [evl-left (vec-remove @selected-evl
                                            @pika-evolutions)]
                   (reset! pika-evolutions evl-left)))}
    "Remove Evolution"]])
1. I get an error when trying to remove an item from the ratom vector. Uncaught Error: Index out of bounds Where I'm doing wrong? 2. Do you have any hints on how to debug cljs properly? It seems that the js console doesn't help that much and I feel lost every time a new error came out. Atm I'm trying to reproduce the error with a small sample like the code above, but when the error persist I don't know where to debug properly or check for documentation

olaf 2021-06-27T10:14:12.068100Z

Found the error, the value from the on-change event is a String and needs to be converted to int

Nazral 2021-06-27T10:46:21.068200Z

Keep in mind that I am way more familiar with Clojure than with CLJS, but when I have to debug things related to states in CLJS, I create a bunch of helper functions to allow me to dump it (or part of it) whenever I need. https://github.com/Tyruiop/syncretism/blob/main/datops-frontend/src/main/live_opts/core.cljs#L26. In some other cases I also create writer functions to allow me to interact easily with it.

Nazral 2021-06-27T10:56:18.068500Z

Also I think you could so with only one atom (and have pika-evolutions be immutable), by doing something like (let [local-pika-evolutions (->> pika-evolutions (split-with #(not= % @selected-evl)) last)] ...)

olaf 2021-06-27T11:11:09.068900Z

Wow, cool. Thanks for sharing! I will try to refactor the code with this idea :thumbsup:

aratare 2021-06-27T11:19:05.071800Z

Hi there. Iโ€™m looking into moving from lein to clj deps for some of my projects, but they all contain some Java files. In lein this is easily set up with :java-source-paths. Does clj deps offer a way to do the same thing, i.e. to include Java source files along with the CLJ ones as well? My google-fu is not strong enough because I canโ€™t seem to find anything about this. Thanks in advance.

alexmiller 2021-06-27T12:47:56.072600Z

Not yet, but support for that is imminent !

2021-06-27T12:52:28.073Z

I tried this code: (ns emotion-modeling-lfb.core (:require [clojure.spec.alpha :as s] [clojure.spec.test.alpha :as stest] [clojure.spec.gen.alpha :as sgen])) (s/def ::between-0-100 (s/and int? #(> 101 % 0))) (s/exercise ::between-0-100) And got this error message on the exercise function: Execution error (FileNotFoundException) at emotion-modeling-lfb.core/eval1617 (form-init13010486330272312439.clj:1). Could not locate clojure/test/check/generators__init.class, clojure/test/check/generators.clj or clojure/test/check/generators.cljc on classpath. And [org.clojure/test.check โ€œ1.1.0โ€] is in my Leiningen project dependencies How can I resolve this?

Fredrik 2021-06-27T13:03:15.073100Z

Have you tried restarting your REPL?

Fredrik 2021-06-27T13:26:10.073600Z

Did that solve your issue?

2021-06-27T13:31:24.073900Z

Yes it did

Apple 2021-06-27T13:46:01.074100Z

Seems like subvec error e.g. (subvec [] 1)

Apple 2021-06-27T13:50:54.074300Z

if (subvec [] "1") then the error is class String cannot be cast to class Number

Fredrik 2021-06-27T13:52:05.074500Z

Awesome! Good luck with the rest of your project, just ask if there's anything more

2021-06-27T13:56:25.075200Z

Spec question:

(defn label-map [arousal valence]
  {:arousal arousal :valence valence})
(s/fdef label-map
        :args (s/cat :is-arousal ::between-0-100 :is-valence ::between-negative-100-and-100))
(stest/instrument 'emotion-modeling-lfb.core/label-map)
(s/exercise-fn label-map)
I receive the error code on exercise-fn: No :args spec found, can't generate

2021-06-27T13:56:42.075600Z

Iโ€™m confused why, because isnโ€™t that what I did in the fdef?

dgb23 2021-06-27T14:21:16.076400Z

you just supply the symbol

Fredrik 2021-06-27T14:21:25.076900Z

You need to pass s/exercise-fn a fully namespace qualified symbol. A handy way is to write `label-map

Fredrik 2021-06-27T14:24:10.078700Z

The backtick will resolve the symbol, for instance label-map => namespace.example/label-map`

2021-06-27T16:20:19.079200Z

The backtick worked perfectly, thank you

2021-06-27T16:28:02.080400Z

(defn emotion-map [arousal valence]
  {:arousal arousal :valence valence})
(s/fdef emotion-map
        :args (s/cat :is-arousal ::between-0-100 :is-valence ::between-negative-100-and-100))
(stest/instrument 'emotion-modeling-lfb.core/label-map)
(s/exercise-fn `emotion-map)
Okay, so now this is working fine when I only exercise the function ten times. Example output: `=> ([(26 -1) {:arousal 26, :valence -1}] [(15 0) {:arousal 15, :valence 0}] [(5 -1) {:arousal 5, :valence -1}] [(10 -2) {:arousal 10, :valence -2}] [(1 -1) {:arousal 1, :valence -1}] [(6 -1) {:arousal 6, :valence -1}] [(4 -1) {:arousal 4, :valence -1}] [(5 0) {:arousal 5, :valence 0}] [(7 -37) {:arousal 7, :valence -37}] [(1 29) {:arousal 1, :valence 29}])

2021-06-27T16:28:42.080900Z

Then I try

(s/exercise-fn `emotion-map 100)
and it works sometimes, but other times I get: Error printing return value (ExceptionInfo) at clojure.test.check.generators/fn (generators.cljc:435). Couldn't satisfy such-that predicate after 100 tries.

2021-06-27T16:29:02.081300Z

What does this error message mean?

dpsutton 2021-06-27T16:35:19.081900Z

check out https://clojure.org/guides/spec#_custom_generators. The paragraph before this section hits this very error. Probably quite worth your time to read this guide carefully

2021-06-27T19:10:26.085Z

What's the CJ alternative to ...var in JS (or *var in Ruby) for list expansion for a fn that takes multiple arguments rather than one argument which is a list? I want to call something like (sh "ls" "foo"), but I have all the arguments in a list, so I need something like (sh ...args). How can I expend the list?

seancorfield 2021-06-27T19:17:37.086100Z

apply

seancorfield 2021-06-27T19:17:45.086600Z

(apply sh args)

2021-06-27T19:17:53.086800Z

Right!

2021-06-27T19:17:55.087100Z

Thanks.

mathpunk 2021-06-27T19:19:04.088800Z

I would like to read some edn I didn't produce. Evidently there's a reader function I need to provide to (edn/read-string {:readers ...} s)

mathpunk 2021-06-28T20:09:48.202800Z

had to put this down but, the string was getting parsed as clojure yet it had complaints about not being able to find... uh.... datascript.db in data-readers?

mathpunk 2021-06-28T20:09:52.203Z

something like that

mathpunk 2021-06-28T20:11:00.203200Z

ah, i'm reading now i gotta quote them

2021-06-30T16:51:53.282900Z

or provide custom readers for them - thus the extra arg

mathpunk 2021-06-27T19:19:58.088900Z

What is it expecting, exactly? I think it's something like... a map from the quoted missing tag name to, anything?

mathpunk 2021-06-27T19:20:35.089100Z

I'm figuring I'd assign identity until i get what I'm looking at

mathpunk 2021-06-27T19:21:27.089300Z

I'll keep looking for an example in or near the docs.

mathpunk 2021-06-27T19:30:51.089500Z

oh, i might get what i need from datascript docs. that's the name in this unknown tag

mathpunk 2021-06-27T19:45:26.089700Z

Still having trouble but I took it to #datascript

2021-06-27T20:14:17.089900Z

You don't have to pass read two args, if you just pass it a valid Edn as string I believe it should just parse it as clojure.

2021-06-27T20:15:07.090100Z

I'm not sure what you can pass on opts to reader, likely how to interpret any new data/literals.

yiorgos 2021-06-27T21:01:16.093200Z

When typing (map inc (range)) in the repl the form is executed and I have to ctrl-c to stop it. The doc for map says that it returns a lazy seq. If map returns a lazy seq, why it runs in the repl? Thanks!

2021-06-27T21:03:04.094Z

Repl stands for Read Eval Print Loop

2021-06-27T21:03:20.094400Z

When you print the lazy sequence, it attempts to realize every element.

2021-06-27T21:03:44.095200Z

Your input is read, the code is evaluated, then the result is printed

yiorgos 2021-06-27T21:04:15.095600Z

okay, that makes sense now. Thank you very much!

2021-06-27T21:24:22.103800Z

I have an issue with a macro. I simplified the macro to: (defmacro block [name & sexps] (println "BEFORE") ~@sexps (println "AFTER"))` And the usage to: (block "test" (println "A") (println "B")). But I'm getting unquote-splice not in list. What am I doing wrong? ---- I'd like to also check whether I'm doing the right thing. So the use-case is I'm using babashka to run some sysadmin stuff. block is supposed to print "Starting <block-name>", execute all the commands in the block (install this and that, compile emacs 28, that sort of stuff) and then print "Block <block-name> took <number> seconds." I went for a macro here, since a fn would evaluate all the arguments first, rather than sequentially, so when it'd print out "Starting <block-name>", at that point it would already have run all the sexps as well. I imagine macro is the answer to this issue here, is it not?

borkdude 2021-06-27T21:30:23.104700Z

@jakub.stastny.pt_serv You can only use unquote-splice in a list (or something which expands into a list):

(defmacro foo [xs] `[~@xs])

borkdude 2021-06-27T21:31:35.105700Z

the expansion of the backtick happens in the reader:

$ bb -e "'\`[~@xs]"
(clojure.core/vec (clojure.core/sequence (clojure.core/seq (clojure.core/concat xs))))

borkdude 2021-06-27T21:31:47.106200Z

(so that is what "list" refers to)

seancorfield 2021-06-27T21:33:50.107100Z

dev=&gt; (defmacro block [name &amp; sexps] `(do (println "Starting" ~name) (do ~@sexps) (println "Completed" ~name)))
#'dev/block
dev=&gt; (block "foo" (println "hello") (println "world") (* 1 2 3))
Starting foo
hello
world
Completed foo
nil
dev=&gt; 

seancorfield 2021-06-27T21:34:24.107800Z

As your macro stands it would print BEFORE/AFTER at macro-expansion time -- I assumed you wanted that printed at runtime instead?

2021-06-27T21:35:13.108100Z

@seancorfield yes at runtime.

2021-06-27T21:36:29.109200Z

@seancorfield great, this seems to solve it.

2021-06-27T21:36:52.109700Z

@seancorfield @borkdude thank you guys ๐Ÿ™:skin-tone-3:

2021-06-27T21:36:52.109800Z

I have a lot to study, macros are really new to me. Very cool thing though!

seancorfield 2021-06-27T21:37:04.110100Z

The first rule of Macro Club is...

seancorfield 2021-06-27T21:37:08.110300Z

...don't use macros ๐Ÿ™‚

seancorfield 2021-06-27T21:37:23.110700Z

(but, yes, sometimes they delayed evaluation is exactly what you want)

seancorfield 2021-06-27T21:39:17.113Z

Bear in mind you could use functions, if you don't mind wrapping the commands in a fn:

dev=&gt; (defn block [name thunk] (println "Starting" name) (thunk) (println "Completed" name))
#'dev/block
dev=&gt; (block "foo" (fn [] (println "hello") (println "world") (* 1 2 3)))

seancorfield 2021-06-27T21:40:51.114Z

That transformation -- from &amp; body to (fn [] ~@body) -- is fairly common in macros that wrap functions. See https://github.com/seancorfield/next-jdbc/blob/develop/src/next/jdbc.clj#L350-L362 for example.

2021-06-27T21:44:57.118Z

@seancorfield yeah I thought of that, but the intended result is essentially a (moreless) declarative DSL for specifying how the system should be (with (package &lt;xyz&gt;) rather than (install &lt;xyz&gt;)) and I didn't want to litter it with lambdas, as it really is meant to be a declarative abstraction. It's a good point though!

2021-06-27T22:18:17.121600Z

What if I need to add something to the list, such as (defn zsh [&amp; chunks] (sh "zsh" "-c" ...chunks))? Do I need to manually create a new list with all the arguments or is there a shortcut? In Ruby it'd be sh *["zsh", "-c", *chunks], just like in JS, only replacing * with ....

seancorfield 2021-06-27T22:20:48.121800Z

(apply sh "zsh" "-c" chunks)

seancorfield 2021-06-27T22:21:24.122Z

dev=&gt; (doc apply)
-------------------------
clojure.core/apply
([f args] [f x args] [f x y args] [f x y z args] [f a b c d &amp; args])
  Applies fn f to the argument list formed by prepending intervening arguments to args.

seancorfield 2021-06-27T22:22:09.122200Z

See also https://clojuredocs.org/clojure.core/apply

2021-06-27T22:24:01.123200Z

Ah, I see. Cool the (doc ..) thing, I didn't know about it at all.

seancorfield 2021-06-27T22:24:27.123400Z

Also

dev=&gt; (source apply)
(defn apply
  "Applies fn f to the argument list formed by prepending intervening arguments to args."
  {:added "1.0"
   :static true}
  ([^clojure.lang.IFn f args]
     (. f (applyTo (seq args))))
  ([^clojure.lang.IFn f x args]
     (. f (applyTo (list* x args))))
  ([^clojure.lang.IFn f x y args]
     (. f (applyTo (list* x y args))))
  ([^clojure.lang.IFn f x y z args]
     (. f (applyTo (list* x y z args))))
  ([^clojure.lang.IFn f a b c d &amp; args]
     (. f (applyTo (cons a (cons b (cons c (cons d (spread args)))))))))

seancorfield 2021-06-27T22:25:13.123600Z

(although the source isn't always very instructive, esp. when it just calls into Java under the hood!)

icosahedron 2021-06-27T23:50:06.124600Z

Looking for advice on using ClojureCLR in an IDE? Calva seems like a good choice, given the VS Code <-> CLR connection? Looked at Cursive, and no obvious way to select the CLR.

icosahedron 2021-06-27T23:51:07.125800Z

I have installed ClojureCLR with dotnet tools install --global Clojure.Main and can get a repl with just Clojure.Main. My understanding is that nrepl does not work with ClojureCLR.

icosahedron 2021-06-27T23:51:46.126700Z

I've seen introductions on using clojure.core.repl with socket servers. They all pass Java properties. What might the .NET equivalent be?

seancorfield 2021-06-27T23:54:32.128100Z

I don't know much about ClojureCLR but I'll point you at https://gitter.im/clojure-clr/community which is where the Clojure CLR community is, apparently (there's a #clr channel here but it just points to that Gitter URL).

icosahedron 2021-06-27T23:57:03.128300Z

Thanks! I'll look there.