code logs -> 2019 -> Thu, 03 Oct 2019< code.20191002.log - code.20191004.log >
--- Log opened Thu Oct 03 00:00:12 2019
01:15 Vornicus [Vorn@ServerAdministrator.Nightstar.Net] has quit [Connection closed]
01:52 celmin|away is now known as celticminstrel
01:53
<@celticminstrel>
So basically are you suggesting the real problem with exceptions is that functions aren't required to declare every exception they could possibly throw?
01:54
<@celticminstrel>
I guess result types are similar to a variant<bool, T> but with the added restriction that you cannot retrieve T until you have retrieved bool?
01:54
<@celticminstrel>
Wait, not a variant, a tuple.
01:54
<@celticminstrel>
Well, I suppose maybe either would work...
02:31 celticminstrel [celticminst@Nightstar-ocfc15.dsl.bell.ca] has quit [Connection closed]
03:15 Reiv [NSkiwiirc@Nightstar-ih0uis.global-gateway.net.nz] has quit [[NS] Quit: http://www.kiwiirc.com/ - A hand crafted IRC client]
03:15 Reiv [NSkiwiirc@Nightstar-ih0uis.global-gateway.net.nz] has joined #code
03:15 mode/#code [+o Reiv] by ChanServ
03:41
<@Alek>
wtf https://i.imgur.com/TSVZcWi.jpg
03:52 celticminstrel [celticminst@Nightstar-ocfc15.dsl.bell.ca] has joined #code
03:52 mode/#code [+o celticminstrel] by ChanServ
05:06
<&McMartin>
celticminstrel: A variant that checks its own type on access is what it actually is
05:06
<@celticminstrel>
Hm?
05:07
<&McMartin>
That's how you implement checked-result types.
05:08
<&McMartin>
It's an <Error, T> variant.
05:08
<&McMartin>
With as mechanism that says when you call asT() on it you can only do that if it is in fact a T.
05:12
<@celticminstrel>
I'm a bit confused, how is that different from regular variants...?
05:17
<&McMartin>
You could have a language like C, whose variant types just let you access memory wrong~
05:19 Vorntastic [uid293981@Nightstar-6br85t.irccloud.com] has joined #code
05:19 mode/#code [+qo Vorntastic Vorntastic] by ChanServ
05:21
<@celticminstrel>
So IOW if using the C++ standard library, std::variant<some_error_type, some_other_type> precisely satisfies the definition of a result type?
05:23
<&McMartin>
It would, if things returned those instead of error codes.
05:24
<&McMartin>
My guess is the result would be pretty unergonomic. Rust has an operator that forces an early return that echoes the error to the caller on first access that makes this much easier to manage.
05:24
<@celticminstrel>
So something like...
05:25
<@celticminstrel>
If you do r.asT() but it's not a T, then it prints r.asErr()?
05:25
<@celticminstrel>
Or wait no.
05:25
<@celticminstrel>
If you do r.asT() but it's not a T, then it actually returns r from the function?
05:25
<&McMartin>
Close but not quite.
05:26
<&McMartin>
If you're a function of type <E, T>, and you call a function that returns <E, U>, when you do the operator, it either evaluates to the U value or it returns immediately with an <E, T> set to the E value.
05:26
<&McMartin>
You can't just return r without requiring that T == U, which is inconvenient.
05:26
<@celticminstrel>
I see.
05:27
<@celticminstrel>
So if you do r.asT() but it's not a T, then it returns r.asErr().
05:27
<@celticminstrel>
Cast to the result type of the current function, basically.
05:28
<&McMartin>
Right
05:28
<@celticminstrel>
What if the current function doesn't return a result type?
05:28
<&McMartin>
Also only when you use that operator.
05:28
<&McMartin>
If it doesn't, then you aren't allowed to use the operator, and have to destructure the result yourself.
05:28
<&McMartin>
Basically "match r with T(t) -> success case | Err(e) -> error case"
05:28
<@celticminstrel>
I guess this operator could be replicated with a macro in C++, probably still wouldn't be quite as nice to use as Rust tho.
05:29
<@celticminstrel>
I guess having first-class syntactic support for variants makes it a lot nicer huh.
05:29
<&McMartin>
The Rust one *is* a macro. It used to be named try! before they made it an operator.
05:29
<&McMartin>
v.
05:29
<&McMartin>
That is honestly what I use as my marker for a properly modern language these days.
05:30
<@celticminstrel>
That actually looks a lot like a switch statement?
05:30
<&McMartin>
Yep
05:30
<&McMartin>
It's better than a switch statement, but it's basically a switch statement that also assigns variables within each branch.
05:30
<@celticminstrel>
I wonder if that could be implemented in C++ as a macro...
05:30
<@celticminstrel>
Or two macros.
05:31
<&McMartin>
It's a destructuring variable assignment
05:31
<&McMartin>
So if you have a morass of lists and nested tuples or whatever
05:32
<&McMartin>
If you can kind of say "if let (a, (b, c), d) = val { stuff with a, b, c, and d; }"
05:32
<&McMartin>
And it picks apart the tuples/lists/etc for you.
05:33
<&McMartin>
ML is the earliest language I saw do this, though Lisp macros are often similar and Haskell's the one that pushed it the hardest for a long time.
05:33
<@celticminstrel>
Kinda like the "auto [a, b, c] some_tuple" syntax in C++ then... tho that definitely doesn't work for variants.
05:33
<@celticminstrel>
Oops - ^ =some_tuple
05:33
<&McMartin>
I think auto also won't nest arbitrarily, or let you pick fields out of a struct, etc.
05:33
<@celticminstrel>
Yeah, I think it won't nest, indeed.
05:34
<@celticminstrel>
And IIRC it can pick fields out of a struct, but only if the struct was explicitly written to support that.
05:34
<@celticminstrel>
I can't remember how that works, maybe it was by providing a cast to tuple?
05:41
<&McMartin>
Because the platforms I've profesionally targeted with C++ don't support C++17 and only kind of support C++14, my expertise in that space drops off rapidly.
05:42
<&McMartin>
As to your other question...
05:42
<&McMartin>
17:53 <@celticminstrel> So basically are you suggesting the real problem with exceptions is that functions aren't required to declare every exception they could possibly throw?
05:42
<&McMartin>
I'm saying that my main problem with exceptions (which is not necessarily the only problem with them) is strongly mitigated, though not eliminated, if you do this.
05:42
<@celticminstrel>
I see...
05:42
<&McMartin>
We learned in 1996 that you can't really make people do this, though.
05:43
<@celticminstrel>
What happened in 1996 exactly? Java?
05:43
<&McMartin>
Yeah, which tried this, and which resulted in everything just being declared to throw everything, or just swallowing everything, neither of which are great.
05:43
<&McMartin>
Let's see if I can synthesize the various things I've been arguing over the past few days.
05:43
<&McMartin>
There are two things I want out of reading code.
05:44
<&McMartin>
1. I don't want it to be mostly boilerplate nonsense.
05:44
<@celticminstrel>
(Somehow I initially read that as "sympathize".)
05:44
<&McMartin>
2. I want to be able to follow the control flow of a chunk of code just by reading it.
05:44
<&McMartin>
Point 2 is a sticky one because it puts very strong constraints on what the entire rest of the world is allowed to do.
05:46
<&McMartin>
In the absence of setjmp and longjmp operating on data that I'm somehow forwarding on to the functions I call, C gives me pretty strong guarantees on (2), but it's pretty awful about (1) if the author is being a stickler for error checking.
05:46
<&McMartin>
Golang ends up in a similar space, where it returns (value, error) tuples.
05:47
<&McMartin>
Exceptions enable (1) very easily, letting you centralize error handling code at appropriate points in your application.
05:47
<@celticminstrel>
But they violate 2.
05:47
<&McMartin>
Yup. Any call out of your function to anything potentially never returns or returns to a different point in your function (the exception handler).
05:48
<&McMartin>
Chacked exceptions mitigate this but don't eliminate it; any function call might drop you into your handler, or end the function as it throws something you declare yourself to rethrow.
05:48
<&McMartin>
But if I have a searchable API document, each call says whether or not it might do this, so I can at least in principle *find out* what it's doing while leaving it as a black box.
05:49
<&McMartin>
Using variants as error codes solves a problem I didn't list here, because it's a thing I want while *writing* code, not reading it: it guarantees that all error conditions are checked.
05:49
<&McMartin>
(A thing exceptions also guarantee.)
05:50
<&McMartin>
The unwrap-variant-or-return-the-error-in-it macro/operator, though, gets me (1) *and* (2).
05:51
<&McMartin>
The error checking boilerplate is no longer boilerplate consuming the implementation. It's instead a marker that the compiler enforces placement of, and whenever I encounter it while reading, I can read it as "here's a split point where computation terminates on failure".
05:51
<&McMartin>
Not only does it get me (1) and (2), it then also does the guarantee-all-errors-are-checked result.
05:51
<&McMartin>
So that is very nice indeed!
05:51 * celticminstrel nod
05:53 celticminstrel [celticminst@Nightstar-ocfc15.dsl.bell.ca] has quit [[NS] Quit: And lo! The computer falls into a deep sleep, to awake again some other day!]
05:53
<&McMartin>
And insisting on checked exceptions produces problems, come to think of it, because it only mitigates (2) instead of eliminating it and it costs you (1), as most code ends up having large numbers of tightly-bound try blocks to serve the role of a quick error check for cases where you *do* want to mitigate locally.
06:05 Kindamoody[zZz] is now known as Kindamoody
06:26 Kindamoody [Kindamoody@Nightstar-eubaqc.tbcn.telia.com] has quit [[NS] Quit: Rebooting again]
06:27 Kimo|autojoin [Kindamoody@Nightstar-eubaqc.tbcn.telia.com] has joined #code
06:27 mode/#code [+o Kimo|autojoin] by ChanServ
06:29
<&jeroud>
There's another thing that makes Rust's Result type more ergonomic that hasn't been mentioned yet.
06:30
<&jeroud>
The From<T> and Into<T> traits allow almost-implicit type conversions.
06:34
<&jeroud>
The ? operator's error branch isn't just `Err(e) => Err(e)` (which would allow `Result<T, E> -> Result<U, E>`), it's `Err(e) => Err(e.into())` (which allows `Result<T, E> -> Result<U, E2>` for any E and E2 where E implements `Into<E2>`.)
06:36
<&jeroud>
Implementing From<U> for T gives you an automatic implementation of Into<U> for T.
06:36
<&jeroud>
Err, not that.
06:37
<&jeroud>
Implementing From<U> for T gives you an automatic implementation of Into<T> for U.
06:42
<&jeroud>
So you can can use `let foo = read_file("blah.txt")?.do_something()?;` and automatically wrap or convert whatever error you might get from read_file() (presumably something I/O related) and also whatever different error you might get from do_something() (presumably something related to whatever you read from the file) into whatever error type your own function returns.
06:43
<&jeroud>
Without that, you'd need to manually wrap or convert error values everywhere.
06:46
<&jeroud>
This neatly sidesteps the major issue with checked exceptions, which is that you need to either do the conversions manually, declare a dozen different exceptions in your signature, or declare that you raise Exception and thus lose all useful information.
06:46
<&McMartin>
Ah, right. I touched on that but didn't know that it relied on the From<T> and Into<T> mechanisms.
06:52
<&jeroud>
The stdlib has a lovely little `impl<T, U> Into<T> for U where T: From<U> {...}` that gives you free Into<>s for all your From<>s (but not the other way around), so always prefer to implement From<> over Into<>.
07:04
<&McMartin>
Retrofitting types in stdlib classes after the fact is my favorite part of traits.
07:17
<&jeroud>
Sadly it's a bit awkward to add traits that aren't yours to types that aren't yours.
07:17
<&jeroud>
(You have to wrap them in new types, usually a tuple struct with one field because that has zero runtime cost.)
08:21 Kimo|autojoin is now known as Kindamoody
10:47 Emmy [Emmy@Nightstar-9p7hb1.direct-adsl.nl] has joined #code
10:52 ErikMesoy1 [Bruker@Nightstar-gilb7q.bb.online.no] has joined #code
10:52 ErikMesoy [Bruker@Nightstar-gilb7q.bb.online.no] has quit [Ping timeout: 121 seconds]
10:53 Kindamoody [Kindamoody@Nightstar-eubaqc.tbcn.telia.com] has quit [Ping timeout: 121 seconds]
12:14
<&Reiver>
Possibly of interest, especially to Vorntastic: https://www.humblebundle.com/software/make-your-card-game
12:14
<&Reiver>
Given how often you wrestle with art, especially the tiles & tokens may be of interest.
12:15
<~Vorntastic>
Ooh
12:21
<@TheWatcher>
Huh, shiny
12:22
< ErikMesoy1>
Aaaargh specifying layouts
12:24
<~Vorntastic>
Unfortunately, css to the rescue
12:26
<@TheWatcher>
But surely everyone loves css! It's the best!
12:30
<~Vorntastic>
Unfortunately it is
12:49
< ErikMesoy1>
frame.getContentPane().add(BorderLayout.SOUTH, panel);
12:50
<@TheWatcher>
Oh, in swing
12:50
<@TheWatcher>
you poor sod.
12:51
< ErikMesoy1>
Coworker is quite critical of swing too
12:52
< ErikMesoy1>
On the other hand, I've got three different stubs up and he's still looking for a better framework :P
12:52 ErikMesoy1 is now known as ErikMesoy
13:00
<@TheWatcher>
Swing is no worse than most other UI toolkits...
13:31 celticminstrel [celticminst@Nightstar-ocfc15.dsl.bell.ca] has joined #code
13:31 mode/#code [+o celticminstrel] by ChanServ
14:45
< ErikMesoy>
Oracle docs: "You should override paintComponent() rather than paint()."
14:45
<&ToxicFrog>
Most UI toolkits are a disaster so uh
14:46
< ErikMesoy>
Me: "But overriding paintComponent() isn't making my stuff show up. Maybe I need to override paint()... ok, now it eats the whole screen and erases everything I drew previously."
14:46 * ErikMesoy then has the clever solution of overriding paint() but packing all his components into paint() with a dozen conditionals and control flows determining which set of them to draw all in one, more or less.
14:46
< ErikMesoy>
Definitely feeling the disaster here. :D
15:15 Vornicus [Vorn@ServerAdministrator.Nightstar.Net] has joined #code
15:15 mode/#code [+qo Vornicus Vornicus] by ChanServ
15:34 Vornicus [Vorn@ServerAdministrator.Nightstar.Net] has quit [Connection closed]
16:10
<@TheWatcher>
ToxicFrog: I didn't say the bar was very high~
16:11
<&ToxicFrog>
Fair
16:51 Pink [user1@Nightstar-g7hdo5.dyn.optonline.net] has quit [Ping timeout: 121 seconds]
17:17 Vorntastic [uid293981@Nightstar-6br85t.irccloud.com] has quit [[NS] Quit: Connection closed for inactivity]
17:41
<&jeroud>
ErikMesoy: Better to understand why paintComponent isn't working.
18:51
< ErikMesoy>
jeroud: After the two of us stared at it and mucked around randomly changing parameters for fifteen minutes, we found that drawing a very large geometric shape resulted in a 10px high bar of that color at the very top of the window, and settled for blaming the JPanelLayoutManager in our confusion. We'll probably investigate further tomorrow.
18:59
<&ToxicFrog>
Sounds like something wrong with the origin or coordinate space you're using. The Graphics object passed to paintComponent() should have the correct origin set alright, though -- (0,0) at the upper left and the clip rectangle set to the area of the component being repainted.
19:10
< ErikMesoy>
I don't have code at hand, but the relevant bit went something like this: @Override paintComponent(Graphics g) {super.paintComponent(g); g.fillRect(200,200,60,40); }
19:15
<&ToxicFrog>
What happens if you just do something like: g.setColor(Color.CYAN); g.fillRect(0, 0, getSize().width, getSize().height);
19:15
<&ToxicFrog>
(and I guess make sure the component is actually positioned where you think it is and it's clipping out of the window or something)
19:18
< ErikMesoy>
I'll try that tomorrow. Whose size is getSize() supposed to be getting in that context?
19:19
<&ToxicFrog>
That's the getSize on the component that this paintComponent() definition is part of.
19:19
<&ToxicFrog>
I.e. this.getSize()
19:20
<&ToxicFrog>
That should fill the entire area that Swing thinks the component occupies with cyan; if that doesn't match the position and size you think it has, it's much more likely something has gone wrong with component layout than that the Graphics object was initialized wrong by the rendering loop.
20:21
<&McMartin>
Godspeed, Erik
20:21
<&McMartin>
It's been a long time since I've Swing'd, and IIRC the layout madness isn't even Swing. It's still the AWT mess, isn't it?
20:22
<&McMartin>
Also, Swing is, at worst, the third best GUI toolkit I've ever used, and I've used quite a few >_<
20:22
<&McMartin>
(Qt4+ definitely beats it, and Cocoa might. Cocoa's alien enough that it's hard to get ordering information out.)
20:23
< ErikMesoy>
Still bits of AWT hanging around in there, yes.
20:23 Pink [user1@Nightstar-g7hdo5.dyn.optonline.net] has joined #code
20:51 Pink [user1@Nightstar-g7hdo5.dyn.optonline.net] has quit [Ping timeout: 121 seconds]
20:59 Pink [user1@Nightstar-g7hdo5.dyn.optonline.net] has joined #code
21:43 Vornicus [Vorn@ServerAdministrator.Nightstar.Net] has joined #code
21:43 mode/#code [+qo Vornicus Vornicus] by ChanServ
21:44 Emmy [Emmy@Nightstar-9p7hb1.direct-adsl.nl] has quit [Ping timeout: 121 seconds]
22:37 Kimo|autojoin [Kindamoody@Nightstar-eubaqc.tbcn.telia.com] has joined #code
22:37 mode/#code [+o Kimo|autojoin] by ChanServ
22:37 Kimo|autojoin is now known as Kindamoody
22:53 Kindamoody is now known as Kindamoody[zZz]
22:56 Vorntastic [uid293981@Nightstar-2dc.p8m.184.192.IP] has joined #code
22:56 mode/#code [+qo Vorntastic Vorntastic] by ChanServ
23:30 himi [sjjf@Nightstar-v37cpe.internode.on.net] has quit [Ping timeout: 121 seconds]
--- Log closed Fri Oct 04 00:00:14 2019
code logs -> 2019 -> Thu, 03 Oct 2019< code.20191002.log - code.20191004.log >

[ Latest log file ]