beginners

Getting started with Clojure/ClojureScript? Welcome! Also try: https://ask.clojure.org. Check out resources at https://gist.github.com/yogthos/be323be0361c589570a6da4ccc85f58f.
Prashant 2021-06-17T02:56:24.270600Z

Second arity is the one expecting more parameters. First arity merely supplies a value for the skipped parameter while calling the function e.g. first arity supplies and hard codes the value for y-cutoff as 0 Consider 0 default value for parameter y-cutoff of function draw-board! . This is the closest in from C#.

Franco Gasperino 2021-06-17T17:08:11.278600Z

Working with spec, im writing a custom generator to produce UUID values. Experimenting with this, i've come up with the following:

(def gen-uuid (spec/gen 
                (into [] 
                  (take 1000
                    (repeatedly #(str (java.util.UUID/randomUUID)))))))
=> ; Execution error (NullPointerException) at java.util.regex.Matcher/getTextLength (Matcher.java:1770).
; null
However, the form works as expected outside the gen call. What am i missing?

dpsutton 2021-06-17T17:14:12.278900Z

what's the docstring of spec/gen?

Franco Gasperino 2021-06-17T17:25:02.279200Z

the argument must be a spec itself. Maybe i'm confused that a set can be used as an argument

2021-06-17T17:25:54.279400Z

there is no set in your code

Franco Gasperino 2021-06-17T17:27:15.279700Z

There is in the clojure spec guide:

<https://clojure.org/guides/spec>
First example has the following:
(def kw-gen (s/gen #{:my.domain/name :my.domain/occupation :my.domain/id}))
(gen/sample kw-gen 5)
I was unaware of its behavior here

2021-06-17T17:29:26.279900Z

yes, but your into call is constructing a vector

2021-06-17T17:29:29.280100Z

not a set

popeye 2021-06-17T17:29:47.280600Z

I am trying to destruct map

(let [keys [:my_id (:myid input)]]
     _ (println keys))

popeye 2021-06-17T17:30:22.281600Z

but when I print keys value I am getting as :myid not :my_id

2021-06-17T17:30:34.282Z

that doesn't look anything like the examples

popeye 2021-06-17T17:31:21.282600Z

i want to rename value from :myid to :my_id

Franco Gasperino 2021-06-17T17:31:39.282700Z

correct. my confusion is how a set behavior differs. I'm missing something fundamental about set behavior as a spec, compared to other sequences

alexmiller 2021-06-17T17:31:49.283Z

sets are specs of enumerated values

alexmiller 2021-06-17T17:32:02.283200Z

other colls are not

2021-06-17T17:32:30.283600Z

"Destructuring is a way to concisely bind names to the values inside a data structure."

2021-06-17T17:32:47.283900Z

it is not a way to modify datastructures

2021-06-17T17:33:06.284300Z

(the quote is first line in the guide linked above)

Franco Gasperino 2021-06-17T17:35:31.284400Z

alright. ill noodle on the implications of that

Franco Gasperino 2021-06-17T17:36:41.284600Z

(def uuid-regex
  (re-pattern #"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$"))

(spec/def ::uuid?
  (spec/with-gen
   (spec/and string? #(re-matches uuid-regex %))
   #(spec/gen (into #{} (take 100 (repeatedly (fn [] (str (java.util.UUID/randomUUID)))))))))

(spec-gen/sample (spec/gen ::uuid?))
This works when the vector is replaced with a set

Franco Gasperino 2021-06-17T17:53:31.285100Z

I have a related question regarding custom generators

2021-06-17T17:56:14.285300Z

you may also want to check out the built in uuid generate in test.check (https://github.com/clojure/test.check/blob/master/src/main/clojure/clojure/test/check/generators.cljc#L1520-L1553) that spec uses as the generator for the clojure.core/uuid? predicate

Franco Gasperino 2021-06-17T17:57:14.285600Z

(def uuid-regex
  (re-pattern #"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$"))

(spec/def ::uuid?
  (spec/with-gen
    (spec/and string? #(re-matches uuid-regex %))
    #(spec/gen
      (into #{}
       (take 100
        (repeatedly (fn [] (str (java.util.UUID/randomUUID)))))))))

(defn truncate-uuid [x] (apply str (take-last 12 x)))

(spec/fdef truncate-uuid
   :args (spec/cat :uuid ::uuid?)
   :ret string?)

;; clojure.spec.test.alpha :as spec-test
(spec-test/check `truncate-uuid)

=&gt; ({:spec
  #object[clojure.spec.alpha$fspec_impl$reify__2525 0x4d86324 "clojure.spec.alpha$fspec_impl$reify__2525@4d86324"],
  :clojure.spec.test.check/ret {:result true, :pass? true, :num-tests 1000, :time-elapsed-ms 45, :seed 1623952390632},
  :sym eventflow.schema/truncate-uuid})

Franco Gasperino 2021-06-17T17:57:48.285800Z

in this case, is the check, which is leveraging the custom generator, only supplying check with values coming from the generator?

Franco Gasperino 2021-06-17T17:59:03.286Z

or will it create produce values matching the spec predicate which are not produced by the generator as part of the check?

Franco Gasperino 2021-06-17T18:01:18.286200Z

A better illustration may be from https://clojure.org/guides/spec "Custom Generators"

2021-06-17T18:01:40.286400Z

you are asking if the spec will try "negative" cases?

Franco Gasperino 2021-06-17T18:01:56.286600Z

yes, when a custom generator is applied within the spec

2021-06-17T18:02:07.286800Z

no, custom generator or not

2021-06-17T18:02:49.287Z

a spec says the result is defined over some set of inputs, and says nothing about the result over inputs not in the that set

Franco Gasperino 2021-06-17T18:04:24.287200Z

how would you suggest i reason about a spec for the following:

(defn in?
  "Return true if x is in coll, false otherwise."
  [coll x]
  (if (some #(= x %) coll) true false))

(spec/fdef in?
  :args (spec/cat :coll coll? :x any?)
  :ret boolean?)

(spec-test/check `in?)

Franco Gasperino 2021-06-17T18:05:22.287400Z

the generator works. can i be certain that the affirmative case returning true is exercised without a custom generator? If not, how can i apply a custom generator and then affirm the inverse?

sova-soars-the-sora 2021-06-17T18:06:39.288300Z

making a calendar app in clojurescript... any recommendations on how I can find the number of days in a month programmatically, and the day of the week for a given date?

alexmiller 2021-06-17T18:06:51.288400Z

one technique is to use a custom generator that you know generates both cases

Franco Gasperino 2021-06-17T18:06:55.288600Z

or maybe more terse, how do i associate the argument :coll with :x both in the true and false case within the generator

2021-06-17T18:07:10.288800Z

no, you'll want a custom generator if you want to spec that

alexmiller 2021-06-17T18:07:35.289Z

s/fdef can have a :fn spec that receives both the conformed input spec and the conformed ret value

alexmiller 2021-06-17T18:08:18.289200Z

for something like this, it's helpful to make a generator that generates the :x, then builds the :coll to contain it

Franco Gasperino 2021-06-17T18:08:45.289400Z

ok. i see the :fn kwarg now in fdef

2021-06-17T18:09:12.289600Z

I would create a custom generator using, uh, I forget the test.check stuff, but there are combinators that say "generate something by choosing one this collection of generators, and generate from that" and have a generator that is completely random in coll and x

2021-06-17T18:09:30.289800Z

and a generator that generates a random coll and chooses an x from it

alexmiller 2021-06-17T18:09:46.290Z

either way

alexmiller 2021-06-17T18:10:13.290200Z

gen/fdef is a useful combinator for the latter (and gen/bind for the former)

2021-06-17T18:10:53.290500Z

i'd recommend using a date and time library. moment.js, for example

Franco Gasperino 2021-06-17T18:11:00.290700Z

thanks for the feedback. quite helpful

2021-06-17T18:12:00.290900Z

it's more difficult than i'd ever want to mess with, especially in the context of robust third party libs

sova-soars-the-sora 2021-06-17T18:13:28.291100Z

Right on. I have not worked with bringing in third party libs to CLJS at all.. gotta learn how to do that

Franco Gasperino 2021-06-17T18:17:37.291300Z

on the philosophy of spec and test, do you only write a spec for testing, not conforming, as part of your flow, or only where necessary / appropriate?

2021-06-17T18:19:29.291500Z

looks like there are cljs libs, too

Franco Gasperino 2021-06-17T18:19:37.291700Z

in many spots, it can add a significant amount of code overhead when a form can be proven in the repl. what do you find works best on teams?

2021-06-17T18:19:40.291900Z

i haven't used them. here's one: https://github.com/andrewmcveigh/cljs-time

alexmiller 2021-06-17T18:23:34.292400Z

I am judicious in where I write them - mostly for tricky low-level stuff where it's best to generate large input sets for verification, or for api-level contracts

alexmiller 2021-06-17T18:23:46.292600Z

where instrumentation can be useful during dev

ndonolli 2021-06-17T18:24:23.292800Z

cljs-time seems fine, but if you are thinking of pulling in a js library to interop on, I'd advise against moment.js. It's deprecated and the reasons why are documented on their website

2021-06-17T18:25:09.293Z

oh, good to know. had no idea. https://momentjs.com/docs/#/-project-status/

sova-soars-the-sora 2021-06-17T18:25:13.293200Z

Rockin. Tryin out cljs-time now.. it seems like it has all the fxns I would need to make a simple cal app

ndonolli 2021-06-17T18:25:28.293400Z

date-fns is a date library that is more functionally oriented and more modular, if you wanna go the js route

πŸ‘ 1
sova-soars-the-sora 2021-06-17T18:26:58.293600Z

So shadowcljs doesn't support cljsjs ... which makes sense because it's NPM based... gotta figure out how to bring the dependency in

ndonolli 2021-06-17T18:27:30.293800Z

if you are using npm https://shadow-cljs.github.io/docs/UsersGuide.html#_using_npm_packages

sova-soars-the-sora 2021-06-17T18:27:50.294Z

thank you... scanning now

Franco Gasperino 2021-06-17T18:28:17.294300Z

do you have a preferred path regarding external data on the application boundaries? Conform during runtime? Generators for testing?

sova-soars-the-sora 2021-06-17T18:33:28.294500Z

also asked in shadow-cljs... If a library exists in NPM such as "date-fns" do I still need to include it in theΒ `:dependencies [[]]`Β  key in shadow-cljs.edn?

sova-soars-the-sora 2021-06-17T18:36:43.295Z

Oh I see.. npm install date-fns covers the dependencies. ^.^

valtteri 2021-06-17T18:43:01.298500Z

Without dependencies you can do something like

(require '[goog.date :as gdate])
(gdate/getNumberOfDaysInMonth 2021 0)
31

valtteri 2021-06-17T18:43:51.299500Z

Google Closure Library has incredible amount of things in it. https://google.github.io/closure-library/api/goog.date.html#

sova-soars-the-sora 2021-06-17T18:44:07.300Z

Oh that's sweet. That's probably the way to go

Lukas 2021-06-17T18:47:30.301900Z

Hey, sorry to bother you. I try to remove forms from a tree structure. My solution is ... let's call it messy, so I just wanted to ask some experts if there is a more concise way of doing this?

(defn remove-tree [pred tree]
    (loop [n '()
           [h &amp; rst] tree]
      (let [e (if (pred h)
                n
                (conj n
                 (if (list? h)
                   (remove-tree pred h)
                   h)))]
        (if rst
          (recur e rst)
          e))))

(comment 
;; simple example for testing: remove expr begining with +
   (remove-tree
     (fn [x]  (and (list? x) (= '+ (first x))))
     '(-
       (- 1 1 (+ 1 1))
       3
       (+ 1 2)
       (- 2 3 (- 1 1))))
   ;; =&gt; (((1 1 -) 3 2 -) 3 (1 1 -) -)
   ,)
Furthermore, I still have to reverse the result πŸ™ˆ I also tried walk but I couldn't figure out a solution with it.

phronmophobic 2021-06-17T18:58:58.302Z

you could do this with https://github.com/redplanetlabs/specter, but I like using zippers!

(require '[clojure.zip :as z])
(defn zip-walk
  "Depth first walk of zip. edit each loc with f"
  [zip f]
  (loop [zip zip]
    (if (z/end? zip)
      (z/root zip)
      (recur (-&gt; (z/edit zip f)
                 z/next)))))

(defn tree-zip [obj]
  (z/zipper list?
            identity
            (fn [node children]
              (into '() (remove #{::remove} children)))
            obj))

(defn remove-tree [pred tree]
  (zip-walk (tree-zip tree)
            (fn [obj]
              (if (pred obj)
                ::remove
                obj))))

Lukas 2021-06-17T18:59:36.302500Z

Awesome, thanks for the input

phronmophobic 2021-06-17T19:00:00.302700Z

zippers work really well for functionally editing trees

sova-soars-the-sora 2021-06-17T19:15:07.302900Z

Hmmm. I don't know enough about cljs/js interop yet to know how to get the weekday for a given date

sova-soars-the-sora 2021-06-17T19:18:57.303100Z

I tried something like (. weekDay (gdate/Date 2023 1))

sova-soars-the-sora 2021-06-17T19:19:04.303300Z

but that doesn't work ... I am probably missing something vital

valtteri 2021-06-17T19:27:49.304400Z

(.getWeekday (gdate/Date.))

valtteri 2021-06-17T19:27:58.304700Z

Perhaps

valtteri 2021-06-17T19:28:30.305500Z

Not on a computer anymore so can’t verify :/

sova-soars-the-sora 2021-06-17T19:35:41.305800Z

Thanks πŸ˜ƒ I am trying (.info js/console (.-getWeekday (gdate/Date. 2023 1 1))) but I get a function definition printed in the console ;/

sova-soars-the-sora 2021-06-17T19:36:03.306Z

Oh you solved it.

sova-soars-the-sora 2021-06-17T19:36:13.306200Z

.Weekday works but the hyphen does not

sova-soars-the-sora 2021-06-17T19:36:23.306400Z

.getWeekday instead of .-getWeekday

sova-soars-the-sora 2021-06-17T19:36:38.306600Z

super ninja coder skills don't need no computing devices ^.^

2021-06-17T20:09:53.307200Z

walk works too

(clojure.walk/prewalk
 (fn [item]
   (if (list? item)
     (mapcat
      (fn [x]
        (if (and (list? x)
                 (= '+ (first x)))
          []
          [x]))
      item)
     item))
 '(-
   (- 1 1 (+ 1 1))
   3
   (+ 1 2)
   (- 2 3 (- 1 1))))
The main thing is you just have to keep straight the list you are splicing vs the list your are looking for to splice out

2021-06-17T20:10:31.307400Z

(that mapcat can just be a filter)

Lukas 2021-06-17T20:59:41.307600Z

Oh, very cool. Thank you. I had (tbh still have) some troubles to wrap my head around how walk works, but this helps a lot

ndonolli 2021-06-17T21:00:19.307800Z

Ooh yeah the hyphen is used for property access, without is for method invocation

sova-soars-the-sora 2021-06-17T21:35:17.309100Z

(doseq [o 2
	    d (range 1 31)
  :let [c (mod (+ d o) 7)]]
  	   (println d [c c]))
is giving me a "Don't know how to create ISeq from java.lang.Long" ... but if I remove the o 2 and hardcode in a (+ d 2) it works what am I doing wrong with doseq?

2021-06-18T14:30:57.339500Z

user=&gt;    
(ins)user=&gt; (doseq [:let [o 2] d (range 1 31) :let [c (mod (+ d o) 7)]] (println d [c c]))
1 [3 3]
2 [4 4]
3 [5 5]
4 [6 6]
5 [0 0]
6 [1 1]
7 [2 2]
8 [3 3]
9 [4 4]
10 [5 5]
11 [6 6]
12 [0 0]
13 [1 1]
14 [2 2]
15 [3 3]
16 [4 4]
17 [5 5]
18 [6 6]
19 [0 0]
20 [1 1]
21 [2 2]
22 [3 3]
23 [4 4]
24 [5 5]
25 [6 6]
26 [0 0]
27 [1 1]
28 [2 2]
29 [3 3]
30 [4 4]

sova-soars-the-sora 2021-06-17T21:37:12.309400Z

are there limitations on what I can put in the :let clause?

sova-soars-the-sora 2021-06-17T21:39:15.309600Z

πŸ˜„?

borkdude 2021-06-17T21:40:46.310700Z

@sova doseq expects you to provide sequences (rather: seqable object) in the right hand binding. 2 is not a seqable.

sova-soars-the-sora 2021-06-17T21:41:22.311Z

I see. (repeatedly 2) also did not work ;x

borkdude 2021-06-17T21:41:32.311200Z

try (repeat 2)

borkdude 2021-06-17T21:42:03.311700Z

(btw, that doseq won't step in that case)

sova-soars-the-sora 2021-06-17T21:42:08.311900Z

xD

sova-soars-the-sora 2021-06-17T21:42:14.312100Z

repl meltdown

R.A. Porter 2021-06-17T21:42:33.312700Z

Try [2]

borkdude 2021-06-17T21:42:42.313Z

what you probably wanted: (let [o 2] (doseq [d ...]))

sova-soars-the-sora 2021-06-17T21:42:52.313200Z

aha

sova-soars-the-sora 2021-06-17T21:43:09.313500Z

i'll get back to you on if i solved the halting problem or not :rolling_on_the_floor_laughing:

borkdude 2021-06-17T21:43:46.313900Z

how do you know if solving the halting problem will ever stop and when to stop trying?

sova-soars-the-sora 2021-06-17T21:45:12.314400Z

beginnings and ends are a duality, for every end there must be a beginning. it's a simple boolean πŸ˜›

sova-soars-the-sora 2021-06-17T21:45:29.314600Z

[2] worked

sova-soars-the-sora 2021-06-17T21:45:31.314800Z

πŸ˜„

sova-soars-the-sora 2021-06-17T21:49:08.315800Z

actually that still doesn't solve the halting problem... some beginnings don't end in a reasonable amount of time. hit the brake and if it doesn't do anything, eject? =D

sova-soars-the-sora 2021-06-17T21:50:12.316100Z

all those runaway computations must get tired eventually

vinurs 2021-06-17T22:34:54.317600Z

hello, i have a 2 dimensional array m x n like this 1 2 3 4 ..... m 1 1a 2a 3a 4a .... ma 2 3 4 ... n every element in the array has it own range, eg. 1a (-0.1 + 0.15 ), 2a ( -0.2 + 0.4), then how can i iterate all possible values for this array then do sth for each possible value for -0.1 ... +0.15 for -0.2 ... + 0.4

......
about m x n nested for loops

dpsutton 2021-06-17T22:39:59.318500Z

How many values are in the range (-0.1 +-0.15)?

vinurs 2021-06-17T22:40:52.319Z

0.01 is a step, -0.1 -0.09 -0.08 like this

vinurs 2021-06-17T22:42:27.319100Z

one step is 0.01, so like this: -0.1 -0.09 -0.08 ... 0, 0.01, 0.02....0.15

vinurs 2021-06-17T22:42:59.319300Z

@dpsutton every element's range is different