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#.
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?what's the docstring of spec/gen
?
the argument must be a spec itself. Maybe i'm confused that a set can be used as an argument
there is no set in your code
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 hereyes, but your into call is constructing a vector
not a set
I am trying to destruct map
(let [keys [:my_id (:myid input)]]
_ (println keys))
https://clojure.org/guides/destructuring#_associative_destructuring
but when I print keys value I am getting as :myid
not :my_id
that doesn't look anything like the examples
i want to rename value from :myid
to :my_id
correct. my confusion is how a set behavior differs. I'm missing something fundamental about set behavior as a spec, compared to other sequences
sets are specs of enumerated values
other colls are not
"Destructuring is a way to concisely bind names to the values inside a data structure."
it is not a way to modify datastructures
(the quote is first line in the guide linked above)
alright. ill noodle on the implications of that
(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 setI have a related question regarding custom generators
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
(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)
=> ({: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})
in this case, is the check, which is leveraging the custom generator, only supplying check with values coming from the generator?
or will it create produce values matching the spec predicate which are not produced by the generator as part of the check?
A better illustration may be from https://clojure.org/guides/spec "Custom Generators"
you are asking if the spec will try "negative" cases?
yes, when a custom generator is applied within the spec
no, custom generator or not
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
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?)
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?
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?
one technique is to use a custom generator that you know generates both cases
or maybe more terse, how do i associate the argument :coll with :x both in the true and false case within the generator
no, you'll want a custom generator if you want to spec that
s/fdef can have a :fn spec that receives both the conformed input spec and the conformed ret value
for something like this, it's helpful to make a generator that generates the :x, then builds the :coll to contain it
ok. i see the :fn kwarg now in fdef
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
and a generator that generates a random coll and chooses an x from it
either way
gen/fdef is a useful combinator for the latter (and gen/bind for the former)
i'd recommend using a date and time library. moment.js, for example
thanks for the feedback. quite helpful
it's more difficult than i'd ever want to mess with, especially in the context of robust third party libs
Right on. I have not worked with bringing in third party libs to CLJS at all.. gotta learn how to do that
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?
looks like there are cljs libs, too
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?
i haven't used them. here's one: https://github.com/andrewmcveigh/cljs-time
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
where instrumentation can be useful during dev
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
oh, good to know. had no idea. https://momentjs.com/docs/#/-project-status/
Rockin. Tryin out cljs-time now.. it seems like it has all the fxns I would need to make a simple cal app
date-fns
is a date library that is more functionally oriented and more modular, if you wanna go the js route
So shadowcljs doesn't support cljsjs ... which makes sense because it's NPM based... gotta figure out how to bring the dependency in
if you are using npm https://shadow-cljs.github.io/docs/UsersGuide.html#_using_npm_packages
thank you... scanning now
do you have a preferred path regarding external data on the application boundaries? Conform during runtime? Generators for testing?
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?
Oh I see.. npm install date-fns
covers the dependencies. ^.^
Without dependencies you can do something like
(require '[goog.date :as gdate])
(gdate/getNumberOfDaysInMonth 2021 0)
31
Google Closure Library has incredible amount of things in it. https://google.github.io/closure-library/api/goog.date.html#
Oh that's sweet. That's probably the way to go
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 & 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))))
;; => (((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.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 (-> (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))))
Awesome, thanks for the input
zippers work really well for functionally editing trees
Hmmm. I don't know enough about cljs/js interop yet to know how to get the weekday for a given date
I tried something like (. weekDay (gdate/Date 2023 1))
but that doesn't work ... I am probably missing something vital
(.getWeekday (gdate/Date.))
Perhaps
Not on a computer anymore so canβt verify :/
Thanks π
I am trying (.info js/console (.-getWeekday (gdate/Date. 2023 1 1)))
but I get a function definition printed in the console ;/
Oh you solved it.
.Weekday works but the hyphen does not
.getWeekday instead of .-getWeekday
super ninja coder skills don't need no computing devices ^.^
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(that mapcat can just be a filter)
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
Ooh yeah the hyphen is used for property access, without is for method invocation
(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
?user=>
(ins)user=> (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]
are there limitations on what I can put in the :let
clause?
π?
@sova doseq
expects you to provide sequences (rather: seqable object) in the right hand binding. 2
is not a seqable.
I see. (repeatedly 2) also did not work ;x
try (repeat 2)
(btw, that doseq won't step in that case)
xD
repl meltdown
Try [2]
what you probably wanted: (let [o 2] (doseq [d ...]))
aha
i'll get back to you on if i solved the halting problem or not :rolling_on_the_floor_laughing:
how do you know if solving the halting problem will ever stop and when to stop trying?
beginnings and ends are a duality, for every end there must be a beginning. it's a simple boolean π
[2] worked
π
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
all those runaway computations must get tired eventually
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 loopsHow many values are in the range (-0.1 +-0.15)?
0.01 is a step, -0.1 -0.09 -0.08 like this
one step is 0.01, so like this: -0.1 -0.09 -0.08 ... 0, 0.01, 0.02....0.15
@dpsutton every element's range is different