tag:blogger.com,1999:blog-8875558920754897232.post1853720055149928325..comments2022-10-25T06:09:25.930-07:00Comments on Programmatically Speaking: Checked exceptions exposes implementation?Torgnyhttp://www.blogger.com/profile/12146418455302215748noreply@blogger.comBlogger11125tag:blogger.com,1999:blog-8875558920754897232.post-58602313724634076642008-08-29T16:45:00.000-07:002008-08-29T16:45:00.000-07:00Nice article. I didn't realize that it's possible ...Nice article. I didn't realize that it's possible to expose implementation details this way.Andrei Savuhttps://www.blogger.com/profile/01293099573586126940noreply@blogger.comtag:blogger.com,1999:blog-8875558920754897232.post-61594615106196894802008-08-28T08:05:00.000-07:002008-08-28T08:05:00.000-07:00Ah, yes, that would make the test-case more convol...Ah, yes, that would make the test-case more convoluted and hard to understand. In fact, I'm not even going to try to implement it... I would probably mess it up. :)<BR/><BR/>I understand what you ment with "more composable" now...Torgnyhttps://www.blogger.com/profile/12146418455302215748noreply@blogger.comtag:blogger.com,1999:blog-8875558920754897232.post-19331603183490307022008-08-27T11:59:00.000-07:002008-08-27T11:59:00.000-07:00I think I need to be clearer:"Given your Ruby impl...I think I need to be clearer:<BR/><BR/>"Given your Ruby implementation of this test case, how big a difference is it if you want to adjust the test case to show *ALL THE ELEMENTS THAT* cause failures?"<BR/><BR/>Your version only shows the first, because the assert dumps out of the method at the first problem. In and of itself that's not a bad thing, but because you need to make large (well, large is an overstatement for such small amounts of code) changes for small changes in behaviour, things aren't ideal.<BR/><BR/>I'm glad you found the explanation of Either interesting.Ricky Clarksonhttps://www.blogger.com/profile/13845104548520132930noreply@blogger.comtag:blogger.com,1999:blog-8875558920754897232.post-90732815197605202032008-08-27T11:12:00.000-07:002008-08-27T11:12:00.000-07:00It pretty easy to add a message to the assertion:(...It pretty easy to add a message to the assertion:<BR/>(1..10).step(2) { |n|<BR/>__assert_raise(Exception, "#{n} throws exception") {<BR/>____piece_of_code(n)<BR/>__}<BR/>}<BR/><BR/>Thank's for the explanation of Either. I understand now that it works differently in functional languages, where the only "side-effect" of a function is its return value. Ignoring a return value is impossible since that the only reason the function is called! :)Torgnyhttps://www.blogger.com/profile/12146418455302215748noreply@blogger.comtag:blogger.com,1999:blog-8875558920754897232.post-88254685404042413232008-08-26T14:38:00.000-07:002008-08-26T14:38:00.000-07:00togge,You're quite correct, if Java had closur...togge,<BR/><BR/>You're quite correct, if Java had closures the test case would be easier to write.<BR/><BR/>Range.from(1, 100).by(2).forall( { int a => raises(SomeException.class){ x(a); } } );<BR/><BR/>seems to be the best I can get with the BGGA proposal for Java closures, if I invent the Range type with from(int, int), by(int), forall({int => boolean}).<BR/><BR/>Given your Ruby implementation of this test case, how big a difference is it if you want to adjust the test case to show which elements cause failures? I think it's difficult, because assert_raise itself throws an exception, but I might be wrong.<BR/><BR/>Either is different to the traditional C-style error code that doesn't get checked, because code that uses Either would typically not otherwise have a void return type. And assuming you read the return value you cannot forget to check it, as your code just won't compile if you do that.<BR/><BR/>int foo() throws IOException; becomes:<BR/><BR/>Either[Integer, Failure] foo();, and there's no way to get at the Integer without also 'caring' about the Failure.<BR/><BR/>Either is more of a concept than necessarily what's in Functional Java, but it's likely that FJ's version is quite sound. I've used FJ once only - most of the features I would use are fun to roll myself. And for work I might need different names, e.g., F becomes Conversion.Ricky Clarksonhttps://www.blogger.com/profile/13845104548520132930noreply@blogger.comtag:blogger.com,1999:blog-8875558920754897232.post-9515748193089223492008-08-26T09:35:00.000-07:002008-08-26T09:35:00.000-07:00@Ricky: That test-case would be so much easier to ...@Ricky: That test-case would be so much easier to write if Java had closures. In Ruby we have 'assert_raise(SomeException) { piece_of_code }' that tests that a piece of code raises a specified exception.<BR/>Actually, closures are not needed per se... it just gives much better syntax.<BR/><BR/>As I don't know much about Funcitonal Java and haven't tried using Either there are probably cases where Eiter is much better than the closure-approach.<BR/><BR/>I don't, however, like that error cases are indicated by a return value that you explicitly have to check. But then again, I've never used Either so I'm probably missing somthing in all my ignorance. :)Torgnyhttps://www.blogger.com/profile/12146418455302215748noreply@blogger.comtag:blogger.com,1999:blog-8875558920754897232.post-31183622392161023192008-08-26T07:21:00.000-07:002008-08-26T07:21:00.000-07:00didroe,Consider writing a test that says: for ever...didroe,<BR/><BR/>Consider writing a test that says: for every odd number y between 1 and 100, method x(y) throws an IOException.<BR/><BR/>for (int a = 1;a < 100;a += 2)<BR/>. . try<BR/>. . {<BR/>. . . . x(a);<BR/>. . . . fail();<BR/>. . }<BR/>. . catch (IOException e)<BR/>. . {<BR/>. . }<BR/><BR/>Now consider what happens if x returns Either[Integer, Failure].<BR/><BR/>for (int a=1; a < 100; a += 2)<BR/>. . assertTrue(x(a).isRight);<BR/><BR/>And with a more convenient syntax (Scala):<BR/><BR/>1 to 100 by 2 forall (a => x(a).isRight)<BR/><BR/>The try..catch syntax is statement orientated, i.e., you can't *compose* expressions that do any processing of exceptions.Ricky Clarksonhttps://www.blogger.com/profile/13845104548520132930noreply@blogger.comtag:blogger.com,1999:blog-8875558920754897232.post-71303023494545695552008-08-26T07:03:00.000-07:002008-08-26T07:03:00.000-07:00@Ricky: What do you mean by "more composable"? Exc...@Ricky: What do you mean by "more composable"? Exceptions seem pretty composable to me.Anonymousnoreply@blogger.comtag:blogger.com,1999:blog-8875558920754897232.post-10273712330276277672008-08-26T05:04:00.000-07:002008-08-26T05:04:00.000-07:00Option, everywhere I've seen it, has only one type...Option, everywhere I've seen it, has only one type parameter. So Option[int, Reason] would be unusual. The usual name for that is Either.Ricky Clarksonhttps://www.blogger.com/profile/13845104548520132930noreply@blogger.comtag:blogger.com,1999:blog-8875558920754897232.post-86261262176678285082008-08-26T04:57:00.000-07:002008-08-26T04:57:00.000-07:00You could also use Option[int, Reason]You could also use Option[int, Reason]mateusz.fiołkahttps://www.blogger.com/profile/09019915478026785150noreply@blogger.comtag:blogger.com,1999:blog-8875558920754897232.post-77789564891386098402008-08-26T00:53:00.000-07:002008-08-26T00:53:00.000-07:00An alternative to checked exceptions that is more ...An alternative to checked exceptions that is more composable is the Either monad.<BR/><BR/>Replace: int parse(String s) throws Ex<BR/><BR/>With: Either[int, Reason] parse(String s)<BR/><BR/>There is also the Maybe (aka Option) monad for when there is no failure reason.Ricky Clarksonhttps://www.blogger.com/profile/13845104548520132930noreply@blogger.com