beginners 2025-05-25

is it possible to access the result of a test in a cond in it's corresponding branch?

(cond ...
      (some-test? args) test-result
      ...)

the test should only execute once the above tests have failed and if this test passes I don't want anything after it to compute hence I chose to use a cond

so basically is there a cond-let or something similar to if-let that we have

the only approach I can think of is memoising the some-test? but if some better cleaner approach is doable then I'd prefer that

yeah this is what I'm doing at the moment

I guess that's the only approach...

You can make your own macro, or use a utility lib

will check it out, thanks!

although for now memoise is a good enough hack

🔥 1

Multiple ways to handle it, with a custom macro being somewhere at the very bottom of the list. :) Memoize is also not great as it's just unnecessary complexity.

E.g. when you need something like

(if-let [x (get-x args)]
  (process-x x)
  (if-let [y (get-y args)]
    (process-y y)
    ...))
it might be possible to replace it wit
(or (some-> (get-x args) (process-x))
    (some-> (get-y args) (process-y)))

interesting, although correct me if I'm wrong in the first case both process-* functions can execute OR only the process-x but in the other impl (using the or and some->) it is possible for either to execute but never both, correct?

although the some-> function does solve another issue I was having, wherein I wanted to run a series of steps based on results of the previous one, so thanks for the indirect assist xD

In the first case, how would process-y be executed when process-x has already been executed? They're in different branches of the same if.

ah my bad, I switched to indentation block semantics in my head 😳

> is it possible to access the result of a test in a cond in it's corresponding branch? this is what condp is for

well - maybe not a perfect fit here, but often this can be squeezed into the shape condp needs with the right pred arg

eg (example from docs website)

(condp some [1 2 3 4]
  #{0 6 7} :>> inc
  #{4 5 9} :>> dec
  #{1 2 3} :>> #(+ % 3))

The :>> is new will check out, thanks!

condp might be a bad fit here as it uses the same comparison function at each step

but its behavior reminded me of what you wanted, it might match your use case if you massage it right

not in this case, but definitely good to know

I don't think there's anything wrong with using a macro if it makes the code clearer. There are lots of different takes on cond-let in the wild, https://cloogle.phronemophobic.com/name-search.html?q=cond-let&tables=var-definitions. Rather than memoize, I've used delay. You can set up all the variables in a regular let statement and only calculate necessary results. It's ok, but not great.

Regarding macros, quoting hiredman. :D https://clojurians.slack.com/archives/C053AK3F9/p1747276940117959?thread_ts=1746958763.518749&cid=C053AK3F9 I'm fortunate enough to only rarely stumble upon usages of such macros. And in what feels like 90% of the time, they're used very few times in the whole project, sometimes just once. Which makes the cognitive load ratio completely not in favor of them.

what are currently some of the most popular libraries for writing web APIs in clojure?

I use https://cljdoc.org/d/metosin/reitit/0.9.0/doc/introduction which supports ring and provides OpenAPI docs. The routing is defined as a data structure. Reitit is also used by projects like https://kit-clj.github.io/

Ring is the most popular library I'd say. A web API can be implemented with any Ring compliant server like ring-jetty (the default for ring) or http-kit. Then you just set it up to accept and return content-type json and you got yourself a basic web API

The second most popular after that is Pedestal probably: https://github.com/pedestal/pedestal

thank you all for the suggestions, I'll be looking into these!

can the fspec spec be used for runtime validation, or is it only used when enabled with the spec instrumentation tools? I'm asking because trying to do (valid? myfspec myfunc) attempts to call generators

How else would it tell if a function is valid?

I thought that maybe there could be a wrapper that automatically adds :pre and :post conditions to a function call, or something of the sort, by using the spec declaration

But valid? returns true or false right away

How would it know if those pre/posts are triggered?

is it a macro?

Even if it was, how could it immediately return true or false by instrumenting the function?

well 'immediately' is ambiguous here, you may know how valid? works, but I'm asking whether something else exists that behaves like a wrapper, I don't know how the spec system works in depth yet

No, the only way for spec to decide if a function follows the spec or not is to generate inputs from the spec and attempt to call the function on them

Immediately is not ambiguous at all

If you call valid? In the repl you get an answer back right there

sorry I don't mean to argue about the behaviour of valid?, I'm asking about what the spec system can do

the manual page has examples of using specs in the post and pre conditions of functions

Sure, calling valid? there to check arguments

But if you call valid? on a function it will generate data to check it

For data it can just walk it to see if it follows the spec

My answer starting with "No ..." above doesn't mention valid? and is a broad statement about spec itself

ty I see, so there are no analogues to e.g. racket function contracts?

Just manually calling valid? to check arguments that are not functions against a spec

hm I see, ok tyvm for your time

I haven't found spec'ing functions to be super useful, but spec'ing data to both validate data at runtime or generate it in tests can be very nice

hm when you spec data, do you explicitly call an assert or a valid?, or is there something similar to function input instrumentation that automatically enables checking at runtime?

When I have done it I call assert and valid? both, valid? is just a predicate so you need something like assert to do something with the result

I see ty!

It needs to be instrumented.

By default Spec only instruments the input. But you can use 3rd party libs like: https://github.com/jeaye/orchestra to instrument everything.

There's also https://github.com/fulcrologic/guardrails that gives you a replacement defn with fancier syntax for define the function spec.

very neat, ty!

is there a way to define a coll-of or every spec such that the error message on assert only reports the high-level collection failed spec, not the concatenation of all individual failures for each element of the collection?