clojure-uk

A place for people in the UK, near the UK, visiting the UK, planning to visit the UK or just vaguely interested to randomly chat about things (often vi and emacs, occasionally clojure). More general the #ldnclj
dharrigan 2021-04-07T05:22:01.129900Z

Good Morning!

1
1
seancorfield 2021-04-07T05:22:49.130600Z

If y'all could change any Clojure error message to improve it, what would you change?

seancorfield 2021-04-07T15:06:23.149Z

@folcon I’d love to see specific examples of that.

2021-04-07T15:10:10.149200Z

Well even given the examples you've shown here: https://clojurians.slack.com/archives/C064BA6G2/p1617773331132400 Contrast that with this:

<http://foo.rs:4:5|foo.rs:4:5>: 4:11 error: cannot assign to `x` because it is borrowed [E0506]
<http://foo.rs:4|foo.rs:4>     x += 1;
             ^~~~~~
<http://foo.rs:3:14|foo.rs:3:14>: 3:15 note: borrow of `x` occurs here
<http://foo.rs:3|foo.rs:3>     let y = &amp;x;
                      ^
<http://foo.rs:4:5|foo.rs:4:5>: 4:11 help: run `rustc --explain E0506` to see a detailed explanation
error: aborting due to previous error
From rust

2021-04-07T15:11:03.149500Z

I can copy the code in the error and grep my codebase for it, when you eval a code block into the repl, you don't get anything other than relative line numbers...

2021-04-07T15:11:16.149700Z

I don't know, more info that can be given is better?

2021-04-07T15:12:28.149900Z

I don't know how much of this is possible, but I thought that there was some recorded metadata about the current form that was stored which could be retrieved? (could be completely misremembering that)...

2021-04-07T15:13:15.150100Z

Even just better errors during eval would make things nicer for REPL experience 😃...

2021-04-07T15:14:56.150400Z

Sorry I'm not just throwing together a clojure example, today isn't supposed to be a coding day for me so not in the headspace for it >_<...

seancorfield 2021-04-07T15:16:30.150600Z

NP. Yeah, I think in the general case the actual form that threw the exception isn’t available to the error reporting mechanism in Clojure so that’s a bit of a non-starter.

2021-04-07T15:23:38.151800Z

I thought the reader recorded all line numbers of the code that it read as metadata against the functions?

2021-04-07T15:24:11.152100Z

So my thought was just lookup that and display it

2021-04-07T15:25:48.152500Z

If it was recently evaled it might be more problematic, as I'm not sure how locally evaled code is assigned a "file", but they look like generated names, so I was under the impression it would be possible to map an exception's stacktrace info to that same "file" / line number...

seancorfield 2021-04-07T15:43:41.154600Z

I don’t think the full file path is always available — and it’s probably not going to help in a lot of cases where the exception occurs in “other” code: the “Don’t know how to create ISeq from” exception comes from line 557 of clojure.lang.RT for example.

2021-04-08T10:31:42.162300Z

When you say it's not available, is it a unique value per eval? Or nil? If it's unique that should be sufficient to work out what it came from? To be honest at this point I probably should be checking my assumptions about how that all works anyway 😃...

seancorfield 2021-04-08T16:21:42.165Z

By the time the exception is caught all you have is a stacktrace with munged class names (or classpath-relative filenames) + line numbers and the exception itself could have occurred in arbitrary code, not user code — and if it was in a thread, it’s possible that there’s no user code at all in the stack trace.

seancorfield 2021-04-08T16:23:01.165200Z

There are some heuristics that can be applied to sometimes arrive at the place in user code that called whatever blew up (but if the stack includes 3rd party libraries, you can’t tell those from user code really).

2021-04-08T18:00:40.170900Z

Hmm, that's not quite what I meant, what I meant is if you call meta on a var you get line info + file info. Just did this a the repl within a comment block:

(def a 1)
=&gt; #'example.core/a
(meta #'example.core/a)
=&gt;
{:line 21,
 :column 3,
 :file "/Users/folcon/Documents/Code/clojure/example/src/example/core.clj",
 :name a,
 :ns #object[clojure.lang.Namespace 0x65f2460b "example.core"]}
(defn mult [x] (* x x))
=&gt; #'example.core/mult
(meta #'example.core/mult)
=&gt;
{:arglists ([x]),
 :line 23,
 :column 3,
 :file "/Users/folcon/Documents/Code/clojure/example/src/example/core.clj",
 :name mult,
 :ns #object[clojure.lang.Namespace 0x65f2460b "example.core"]}
I didn't mean use the exception directly to get that data, I was thinking whether this could be looked up when an exception occurred so we could grab the file name and line number, look it up return the actual var/symbol and use that to get the source... But it might be a bit too complicated...

seancorfield 2021-04-08T18:43:55.172800Z

There is no control over the code when an exception occurs though — only where it is caught.

seancorfield 2021-04-08T18:44:26.173Z

You can’t get at the context of the throw except via the Java stacktrace.

2021-04-08T20:12:24.173200Z

A valid point.

seancorfield 2021-04-07T05:23:04.131Z

(this is spurred by the State of Clojure thread on r/Clojure)

dharrigan 2021-04-07T05:23:45.131500Z

Yes, interesting. I was reading the discussion too on reddit, quite animated 🙂

dharrigan 2021-04-07T05:24:07.131800Z

I will have to have a ponder

seancorfield 2021-04-07T05:28:51.132400Z

I've been experimenting with a doctored REPL locally:

seanc@DESKTOP-30ICA76:~/oss$ clj -M:dev/repl
Selected port 35617 for the Socket REPL...
Starting clojure.main as the REPL...
Clojure 1.10.3
user=&gt; (-&gt;&gt; [1 2 3] (group-by identity) (map #(reduce + %)))
Error printing return value (ClassCastException) at clojure.lang.Numbers/add (Numbers.java:153).
class clojure.lang.PersistentVector cannot be cast to class java.lang.Number (clojure.lang.PersistentVector is in unnamed module of loader 'app'; java.lang.Number is in module java.base of loader 'bootstrap')
(user=&gt; @2
Execution error (ClassCastException) at user/eval271 (dev.clj:296).
class java.lang.Long cannot be cast to class java.util.concurrent.Future (java.lang.Long and java.util.concurrent.Future are in module java.base of loader 'bootstrap')
user=&gt; (seq 2)
Execution error (IllegalArgumentException) at user/eval273 (dev.clj:1).
Don't know how to create ISeq from: java.lang.Long
user=&gt; (1 2 3)
Execution error (ClassCastException) at user/eval275 (dev.clj:1).
class java.lang.Long cannot be cast to class clojure.lang.IFn (java.lang.Long is in module java.base of loader 'bootstrap'; clojure.lang.IFn is in unnamed module of loader 'app')
user=&gt; (filter [1 2 3] inc)
Error printing return value (IllegalArgumentException) at clojure.lang.RT/seqFrom (RT.java:557).
Don't know how to create ISeq from: clojure.core$inc
(user=&gt;
seanc@DESKTOP-30ICA76:~/oss$ clojure -M:rebel:dev/repl
Selected port 43003 for the Socket REPL...
Starting Rebel Readline as the REPL...
[Rebel readline] Type :repl/help for online help info
dev=&gt;  (-&gt;&gt; [1 2 3] (group-by identity) (map #(reduce + %)))
Error printing return value (ClassCastException) at clojure.lang.Numbers/add (Numbers.java:153).
Expected a number, found value of class clojure.lang.PersistentVector
dev=&gt; @2
Execution error (ClassCastException) at dev/eval5971 (dev.clj:296).
Expected something derefable, found value of class java.lang.Long
dev=&gt; (seq 2)
Execution error (IllegalArgumentException) at dev/eval5973 (dev.clj:1).
Expected sequence, found: java.lang.Long
dev=&gt; (1 2 3)
Execution error (ClassCastException) at dev/eval5975 (dev.clj:1).
Expected function, found value of class java.lang.Long
dev=&gt; (filter [1 2 3] inc)
Error printing return value (IllegalArgumentException) at clojure.lang.RT/seqFrom (RT.java:557).
Expected sequence, found: clojure.core$inc
dev=&gt;
Is that better or not?

seancorfield 2021-04-07T05:30:09.133300Z

(this is literally just a regex replace on some messages -- I'm trying to gauge whether these are worth tackling at source, if possible)

dharrigan 2021-04-07T05:33:39.134Z

Certainly the removal of the (clojure.lang.PersistentVector is in unnamed module of loader 'app'; java.lang.Number is in module java.base of loader 'bootstrap') is a boon. I've taught myself to just filter that out on the trace for it never showed anything of real value to me

dharrigan 2021-04-07T05:34:20.135200Z

I'm still consider myself a beginner in the language, and all this about "loader 'app' and loader 'bootstrap'" is like eh?

dharrigan 2021-04-07T05:35:12.136400Z

The tidy-ups you've got are a lot better in helping me understand what I've done wrong.

seancorfield 2021-04-07T05:35:18.136600Z

TBH, I've gotten to the point where I translate "X cannot be cast to Y" into "expected Y, found X" anyway but I gather a lot of people find the "cannot cast" part to be confusing...

dharrigan 2021-04-07T05:35:40.136900Z

definitely, esp anyone who has zero java/jvm background

seancorfield 2021-04-07T05:36:11.137200Z

Good point.

seancorfield 2021-04-07T05:36:35.137700Z

I got started with Java back in '97 so it's hard for me to know what is obvious and what is intimidating...

dharrigan 2021-04-07T05:37:29.138700Z

The one that also is raised a lot, which I see sometimes at learner sessions (I think I saw also at clojurebridge too) is this old chestnut:

dharrigan 2021-04-07T05:37:36.139Z

user=&gt; (defn foo [x] x)
#'user/foo
user=&gt; (foo 1 2)
Execution error (ArityException) at user/eval24625 (REPL:1).
Wrong number of args (2) passed to: user/foo

seancorfield 2021-04-07T05:38:00.139800Z

OK, I don't understand what is surprising / confusing about that?

dharrigan 2021-04-07T05:38:03.140100Z

It would make sooo much more sense if it was "Wrong number of args passed to : user/foo. Expected 1 got 2"

2021-04-07T12:02:55.145500Z

Not sure if that would be rejected on perf grounds?

seancorfield 2021-04-07T05:38:33.140600Z

Really? OK. Good to know.

dharrigan 2021-04-07T05:38:41.140800Z

Beginner's mind 🙂

seancorfield 2021-04-07T05:39:17.141400Z

I'm going to try to track down some of these at source and submit patches to try and get these improved in 1.11

dharrigan 2021-04-07T05:40:07.142300Z

I'm going to ponder on some more. I was writing some code yesterday that produced some stack (my errors), so will reproduce to see if there is anything obvious that would have helped me understand better the problems.

seancorfield 2021-04-07T05:41:28.142500Z

Thanks!

dharrigan 2021-04-07T05:47:46.143300Z

There was some really good too-and-fro in the reddit discussion. Yes, some charged, but at the same time, it shows a level of passion for the language and community.

djm 2021-04-07T05:50:49.143500Z

👋

1
mccraigmccraig 2021-04-07T06:56:34.144200Z

mawning

alexlynham 2021-04-07T06:59:16.144300Z

morning

thomas 2021-04-07T07:26:35.144500Z

moin moin

jasonbell 2021-04-07T08:09:25.144700Z

Morning

jiriknesl 2021-04-07T10:18:32.145Z

Morning

dharrigan 2021-04-07T13:36:27.147300Z

man, it's so easy to buy on amazon

dharrigan 2021-04-07T13:36:29.147500Z

click click buy

djm 2021-04-07T13:54:19.148Z

Especially for digital things

dharrigan 2021-04-07T13:56:59.148300Z

🙂

jiriknesl 2021-04-07T15:23:33.151700Z

I would happily buy from alternatives, but it seems to me, there are none.

jiriknesl 2021-04-07T15:24:27.152400Z

But yes, it is very easy.

2021-04-07T15:39:47.154500Z

I've managed to not buy anything from amazon in over a year. I guess there's always the "not buy it" alternative :P

thomas 2021-04-07T15:45:03.155100Z

I'm using AWS now and it feels a bit dirty TBH.

dharrigan 2021-04-07T15:57:57.156300Z

I'm curious, for anyone using clojurescript, what components do you use to make your site pretty, aka bootstrap, but clojurescript aware? I'm not totally aware of the clojure ecosystem, do I don't know what people use

minimal 2021-04-07T16:53:11.156600Z

Have used https://github.com/priornix/antizer

dharrigan 2021-04-07T17:34:35.157Z

ta

Adrian Smith 2021-04-07T18:43:31.157300Z

Meetup starting now: https://www.meetup.com/Bristol-Clojurians/events/hnctgsyccgbkb/