--- 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 |