Is there a trick I can use to declare an extra variable in a function declaration? In Common Lisp and some other dialects there is a way to put an aux variable in the function declaration. sort of like this (defun x (a b c &aux (d (+ a b))) …) The aux variable cannot be accessed from the call-site, but it saves having to put a let inside the defun. This same &aux syntax is available in anonymous function definitions, and macros, and methods etc.
one advantage of this syntax is for refactoring later. I don’t have to change the indentation of a function just to add a new local varaible.
Clojure doesn’t have variables so i’m not sure what this would accomplish
ok, well not variables as such but names bound to values.
"save an extra let": why have another obscure way to do it
you can just def some values outside of the body if that’s what it would accomplish? just some constants?
that sounds like a prime place for a macro tbh, if that's your cup of tea
So much negativity! Fellow panelists!! This is a perfect case for a macro. And might be regretted later. But such is the lot of a macro! defn itself is a macro, and could serve as an example.
I think you can use default values like:
(defn x [a b c & {:keys [aux] :or {aux (+ a b c)}}]
aux)
(x 1 2 3) ;;> 6
But I haven't tested.
Wouldn't say it's a great idea, cause it would surprise me a bit. And it also lets the caller overwrite the value of aux by optimally passing it as an option like:
(x 1 2 3 :aux 10) ;;> 10I believe that is heavily discouraged and not officially supported
@dpsutton Might be, but are you sure referring to the arguments is discouraged? Or is it referring to other keys being destructured that is?
yes i believe it is undefined to refer to bound arguments. but maybe it’s more subtle and it is just in maps? i’m not sure
(let [{:keys [a b] :or {b (if (even? (rand-int 2))
(+ 1 a)
(+ 5 a))}}
{:a 4}]
{:a a :b b})
{:a 4, :b 9}
api=>
(let [{:keys [a b] :or {b (if (even? (rand-int 2))
(+ 1 a)
(+ 5 a))}}
{:a 4}]
{:a a :b b})
{:a 4, :b 5}
stuff like thisI think when referring to other destructured variables the issue is it becomes brittle and order dependent, because the map doesn't really guarantee what keys will be destructured first. I believe. So I can see that being not recommended. But referring to the argument at least should work consistently. Could still be "an implementation accident" they'd rather you not rely on.
https://clojurians.slack.com/archives/C0744GXCJ/p1743795860620099?thread_ts=1743792825.545519&cid=C0744GXCJ perhaps it is just in the same map and not when referring to previously bound things
I’m using cloverage to examine the code coverage of a suite of tests. I see the following output. What does it mean that line 1006 is yellow, and lines 1007 through 1014 are not colorized at all?
does coverage instrument the case macro call, or does it macro expand and then wrap the case* call?
good question, we’d have to do dig in to find out
I think it expands and tracks macros @jimka.issy, but it can't map the expanded macro coverage back to your source code, hence the white lines.
@seancorfield whats the difference between red and uncolored? My suspicion mean that uncolored lines do not appear in the macro expansion.
Hmm, maybe. I could never get Cloverage working on our codebase at work so I didn't dig into it too deeply.
I do not know what it means to have not all branches taken. Shouldn’t that simply be implemented as branches taken in green, and branches not taken in red? Or does it mean that it is a macro which expands to code, and in that expanded code, some lines are covered and some are not?
I guess the project really does need @lee’s documentation additions! 🙂
@seancorfield OK, so I’ve now written explicit tests for this function which explicitly exercises all three cases, asserting that I get false, true, and the default value. The tests pass, so I think that all code paths are being executed. but the coloring in cloverage is still confused.
I suspect that cloverage simply doesn’t work for case or maybe it doesnt work for true and false as there’s probably no real code to execute in these case clauses???
I haven't studied the cloverage code yet, but https://github.com/cloverage/cloverage/blob/f3954a6f2533cb0e7aab4e4b0d3e3da7facb1d47/cloverage/src/cloverage/report/html.clj#L136-L140 is probably a good hint:
(let [cls (cond (:blank? line) "blank"
(:covered? line) "covered"
(:partial? line) "partial"
(:instrumented? line) "not-covered"
:else "not-tracked")]
Combined with the https://github.com/cloverage/cloverage/blob/f3954a6f2533cb0e7aab4e4b0d3e3da7facb1d47/cloverage/src/coverage.css#L1-L22:
.covered {
font-family: 'Bitstream Vera Sans Mono', 'Courier', monospace;
background-color: #558B55;
}
.not-covered {
font-family: 'Bitstream Vera Sans Mono', 'Courier', monospace;
background-color: red;
}
.partial {
font-family: 'Bitstream Vera Sans Mono', 'Courier', monospace;
background-color: orange;
}
.not-tracked {
font-family: 'Bitstream Vera Sans Mono', 'Courier', monospace;
}
.blank {
font-family: 'Bitstream Vera Sans Mono', 'Courier', monospace;
}
My current best guess is white is blank lines & uninstrumented (not tracked) code.
Red is not covered at all.
Orange is partially covered ( not all branches executed)
Green is covered.
I agree that the true meaning of red and white seems confusing in your example above.Perhaps this is simply related to the macro expansion? I’ve expanded the case macro callsite and here Is what I see
(let [G__20471 satisfiability]
(case*
G__20471
0
3
(throw
(java.lang.IllegalArgumentException.
(str "No matching clause: " G__20471)))
{1 [:indeterminate default],
2 [:satisfiable true],
3 [:unsatisfiable false]}
:compact
:hash-identity
nil))my guess is that the coverage analyzieris simply not able to map the code in the expanded macro back to lines of user code.
I think it might mean partial coverage? BTW, there is also #cloverage
Yellow: partial coverage -- in this case, "not all branches" were taken.
Uncolored lines: not executed.
Green: executed.
In this case it looks like your tests only pass through satisfiability = :indeterminate -- so nothing exercises the :unsatisfiable or :satisfiable cases.
(at least, that's what Cloverage things)
I've offered to document this for cloverage: https://github.com/cloverage/cloverage/issues/364
is there a good api in clojure for making terminal-ui's ?
Also Java with a very Java API, but it's feature-rich: https://codeberg.org/AutumnMeowMeow/jexer
"Good" is subjective, but FWIW I've seen https://github.com/TimoKramer/charm.clj mentioned a few times here.
bb also bundles https://github.com/jline/jline3, if you'd consider such a thing an indication of quality. It's in Java, but maybe you don't have an aversion to interop.
no, interop is fine for me 🙂
There's also Lanterna (Clojure wrappers exist, not sure if maintained) and (paintparty) Bling.
I've been using https://github.com/phronmophobic/membrane/blob/master/src/membrane/example/terminal_todo.clj but it felt very limited