This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2020-12-09
Channels
- # adventofcode (197)
- # announcements (25)
- # aws (1)
- # babashka (21)
- # beginners (138)
- # calva (21)
- # cider (5)
- # clara (1)
- # clj-kondo (35)
- # clojure (97)
- # clojure-australia (4)
- # clojure-dev (37)
- # clojure-europe (100)
- # clojure-nl (2)
- # clojure-spec (7)
- # clojure-uk (36)
- # clojurescript (11)
- # conjure (15)
- # cursive (20)
- # datomic (12)
- # emacs (10)
- # events (2)
- # fulcro (83)
- # graalvm (14)
- # jobs (1)
- # jobs-discuss (27)
- # kaocha (75)
- # lambdaisland (21)
- # off-topic (27)
- # pedestal (5)
- # reitit (2)
- # reveal (20)
- # rewrite-clj (24)
- # sql (9)
- # tools-deps (37)
- # xtdb (93)
What's people takes on shadowing global vars with local ones? Like say calling a local binding str
?
been bitten more times than i can count by naming things type
and then messing up a reference somewhere in the file
Haha, so I guess its a controversial issue 😛
I'm in the camp of it being totally fine as well. I've never really gotten confused by it, though I guess it would be confusing if it binds to a function. Like a function that took an arg called str
which also happened to be a function, that be confusing. But I've never done that.
It's bitten me once or twice but I still do it. There are just too many nice, short, useful names in clojure.core
to avoid them all for local bindings.
type
and name
are probably the two most common global names that I shadow @didibus -- I have str
as an alias for clojure.string
but I've never found a need for it as a local symbol. A generic string might just as well be s
🙂
(it would be interesting to scan the codebase to see what else we shadow... is that something clj-kondo
can detect @borkdude? I suspect it is... but off by default?)
Currently there is a bug in the linter in that it only works when you use either :include
or :exclude
certain symbols, but not without those options. This has been fixed on master.
I will release probably soon, but when using either of these options, the linter should work. The default level is :off
.
See https://github.com/borkdude/clj-kondo/blob/master/doc/linters.md#shadowed-var
It seems to be at least partially working already in the extension for VS Code, based on my brief experiments last night.
Even that I'm not sure of now. There was a pretty stupid bug. Let me just roll a release.
I remember him asking about this recently. It might be recently added or abandoned based on feedback
:shadowed-var
-- off by default. Just looked it up.
Maybe I'll turn it on at work and see what we get 🙂
at some point, the number of experts who have been bitten by it says all you need to say
I realized you can freely mix vars and namespace, so even when I alias clojure.string as str
its still fine to do: (fn [str] (str/upper-case str))
Anyway, I was just using it as an example. The example that prompted me to ask was we have a thing called Agent in our app, and so the bindings are often (defn [agent ...] ...)
and our team were discussing not shadowing the core agent
function. So maybe that's a better example?
Yes, clj-kondo has a linter for that. I fixed an issue with it on master last weekend
Humdum, trying to remember the name of a tracing debug library for Clojure that came about recently (not sayid), but my memory fails me
https://github.com/jpmonettas/flow-storm was announced pretty recently, at least.
hi, I have a quick question: I have this list of strings that are all numeric. Before I process it, I map over the list to get numeric values: (map (Integer/parseInt %) my-list) I compile it with no complaint. However, when I run the code, the first time I run it I get a number format exception for the value of "2622048027". When I run it the second time without changing code or recompiling or anything, the code works fine. I understand that Integer/parseInt is supposed to give number format exception. What I do not understand though is why it works the second time I run the code. Anyone has any idea what is happening here?
you forgot #
in front of (Integer/parseInt %)
is this lambda inside of another anonymous function declaration?
map is lazy so if you're not using all of the result, you won't actually do the parsing
@alexmiller I get that, but what is getting "2622048027" to be a number the second time I run the code?
the first time I need that value, map is evaluated, and that is when (Integer/parseInt "2622048027") is called, and it gives the exception. The second time I run the code, Integer/parseInt has already been called, so it is not called... buut what got "2622048027" into 2622048027?
I think that number is too big to be an Integer
Integer/MAX_VALUE is 2147483647
in general, I almost always use Long/parseLong (because that's the default integer size in Clojure)
it is, and I understand why Integer/parseInt must throw an exception. But I do not understand how it is turning into a number in spite of the eception being thrown
can you share the actual code?
from your description, doesn't make sense so must be missing something
yes sure. the code is my solutions to advent of code. I am giving url directly to day 9 solution https://github.com/bibiki/aoc-2020/blob/main/src/aoc_2020/day_9/solution.clj
I get not found on that link. Might be on my end.
@U0CMVHBL2 @alexmiller I just made my repo public, please try again
well, in
is lazy so you could use it for a while before discovering an issue
@alexmiller I am not sure that explains why it works the second time I run the code, why is that string turning into a number the second time I run the code?!?!
that does explain why I get a problem after having read many values from in, not immediately, but not why it succeeds the second time...
stepping away for a meeting
I can try to evaluate (count in)
and the first time it throws an exception, but the second time it returns 608 with no exception.
If I change Integer/parseInt to Long/parseLong and do (count in), I get 1000.
So I would not say it is "working" when it returns 608, except to say it is returning the 608 elements out of the 1000 before the exception occurred.
lazy sequences do cache their results when realizing elements, i.e. they actually allocate memory for elements of the lazy sequence as it is being realized. I suspect when it is realizing it the first time, it is creating the first 608 elements, getting the exception on the 609th, and then leaving the lazy sequence in a state where after 608 elements that is a normal end of the list, rather than a "try to realize this next thing" the way it was when the exception occurrred.
in cases like this, all bets are off - we don't try to protect you from "broken" lazy seqs
you guys are right, as measured against the expectation that (count in) should be 1000, it is not working. as measured against the expectation of giving an answer to second part of the puzzle... it does produce the correct answer. I need to think further why it gets to evaluating "2622048027" before finding an answer to the puzzle in the first run
I guess (partition ... is ran against the 608 elements the second time, and the correct answer to the puzzle is producible with those 608 elements. yeah, I think that is
if you fetch the code and want to reproduce the bug, just run (solution-second-part) twice after compiling the code
This is surprising:
(case (int -1)
-1 true
nil false)
Execution error (IllegalArgumentException) at .../eval21818 (form-init2370325502731369149.clj:398).
No matching clause: -1
(case (int -1)
-1 true
-2 false)
true
that is a bug and we have a ticket for it
well, maybe it's not the same thing - you might be seeing mismatch between int and long too?
nah, it's probably the same thing as that bug
locking
is the canonical answer
functions are not synchronized in Clojure, but you can add that semantic inside the function if you really need to
(but I'd try hard to not need to :)
locking
lets you use the low level object monitors that synchronized
blocks and methods in java use, but you also have access to https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/locks/package-summary.html
I wouldn't
common case is to def/let an (Object.)
to act as the lock
no, that looks ok
no, but I'd put that around the defn
not in the defn
yeah, have done