tag:blogger.com,1999:blog-5975524006824862804.post2079781155350765091..comments2024-02-10T02:23:08.475-08:00Comments on Paul's Pontifications: Composability and ProductivityPaul Johnsonhttp://www.blogger.com/profile/07353083601285449293noreply@blogger.comBlogger10125tag:blogger.com,1999:blog-5975524006824862804.post-45979687842525602042009-04-25T09:52:00.000-07:002009-04-25T09:52:00.000-07:00"Mutable state is actually another form of manual ...<I>"Mutable state is actually another form of manual memory management: every time you over-write a value you are making a decision that the old value is now garbage, regardless of what other part of the program might have been using it."</I>I like this insight very much. Thanks!Conalhttps://www.blogger.com/profile/05756984502464196668noreply@blogger.comtag:blogger.com,1999:blog-5975524006824862804.post-35649955939896022212009-04-25T09:48:00.000-07:002009-04-25T09:48:00.000-07:00This comment has been removed by the author.Conalhttps://www.blogger.com/profile/05756984502464196668noreply@blogger.comtag:blogger.com,1999:blog-5975524006824862804.post-9147004650587159042009-02-13T22:16:00.000-08:002009-02-13T22:16:00.000-08:00+1 for mentioning erlang. Loving FP these days. OO...+1 for mentioning erlang. Loving FP these days. OO got boring kinda fast, when I got stuck working with someone else's ObjectXFactory class.Unknownhttps://www.blogger.com/profile/08425435755112948327noreply@blogger.comtag:blogger.com,1999:blog-5975524006824862804.post-25053639308393218442009-02-13T11:20:00.000-08:002009-02-13T11:20:00.000-08:00Correction about the semantics of GC: The GC doesn...Correction about the semantics of GC: The GC doesn't free an object once it sees module X and Y are done with it... that's way too hard (impossible because it's equivalent to the halting problem). Most GCs instead delete an object at some arbitrary point when it is unreachable, which is guaranteed to be after the last time the object is ever used.Anonymousnoreply@blogger.comtag:blogger.com,1999:blog-5975524006824862804.post-58788846246650151762007-09-03T12:23:00.000-07:002007-09-03T12:23:00.000-07:00Sorry eelis, I was a bit rushed for time yesterday...Sorry eelis, I was a bit rushed for time yesterday. Here is a fuller reply.<BR/><BR/>Its not just a matter of putting two modules together, its a matter of putting lots of them together.<BR/><BR/>Lets say I have a module that allocates some memory for data and exposes the resulting pointer (along with a lot of other data) as part of its API. Client modules use all this data to compute derived data that includes the original pointer (e.g. lists sorted by different criteria). Then the original module does something that removes the original data from view. At this point you have a problem: when is it safe to free this memory. Any one of the client modules may still be holding on to a copy of the pointer, so it is only safe to free the memory when all the clients have dropped their copies of pointer. But the original module has no way of knowing when this is unless detailed knowledge of all those clients has been programmed into it.<BR/><BR/>There are various workarounds for this, most of which involve reference counting. But reference counting is not an alternative to GC, its a slow, buggy ad-hoc implementation of GC, which is why this perfectly illustrates Greenspun's Tenth Rule.<BR/><BR/>Of course you could just have the clients take copies of the data, so each has exactly one copy to delete. But that just replaces the GC problem with a precisely equivalent data consistency problem.Paul Johnsonhttps://www.blogger.com/profile/07353083601285449293noreply@blogger.comtag:blogger.com,1999:blog-5975524006824862804.post-18374158220065050452007-09-03T08:12:00.000-07:002007-09-03T08:12:00.000-07:00JP Moresmau:You must be arguing a different point ...JP Moresmau:<BR/><BR/>You must be arguing a different point than Paul, who did not include a "must be enforceable by a tool" clause in his notion of composability.<BR/><BR/>That said, it's a good thing he didn't add such a clause, because with it, Haskell wouldn't qualify either. After all, in Haskell too is the developer absolutely required to "read documentation, understand it, and code perfectly according to it", because the compiler-checked types of functions generally barely scratch the surface of their semantics (including interface pre- and postconditions).<BR/><BR/>Just like in C++ you have to read the documentation for a function returning an int* to find out how long the pointer will remain valid, in Haskell you have to read the documentation for a function taking a [Int] to find out if it requires the list to be finite, non-empty, or something else. Both are examples of interface/compatibility aspects that have to be checked by programmers.Anonymousnoreply@blogger.comtag:blogger.com,1999:blog-5975524006824862804.post-32349675955241860542007-09-03T05:22:00.000-07:002007-09-03T05:22:00.000-07:00I think the "more help from the compiler" is NOT b...I think the "more help from the compiler" is NOT beside the point. There is a world of difference between a compatibility that is enforced by a tool and a compatibility that requires a developer to read documentation, understand it, and code perfectly according to it (assuming the documentation is 100% correct all the time). And Haskell does enforce more than just interface type checking (or, more precisely, the type checking check for side effects thanks to monadic types, etc.)JP Moresmauhttps://www.blogger.com/profile/09964251063221757176noreply@blogger.comtag:blogger.com,1999:blog-5975524006824862804.post-1403364945229735132007-09-02T20:02:00.000-07:002007-09-02T20:02:00.000-07:00"That, of course, is the big "if"."(I'm not sure w..."That, of course, is the big "if"."<BR/><BR/>(I'm not sure why I'm even bothering to give such a meagre cop-out a dignified response, but here goes.)<BR/><BR/>The point is that this "if" can simply be verified by the programmer who intends to combine the modules. This is really no different from verifying that the types of the modules' interfaces are compatible (except that in the latter case there is of course more help from the compiler, but that is beside the point). In both cases, if the modules' interfaces are not compatible, some glue code may be needed.<BR/><BR/>If your criterion for languages that support composable modules is that /any/ two modules must be composable without any "if"s -- that is, without any concern for compatibility of interfaces -- then by that standard your Haskell cannot be considered to feature module composibility either.Anonymousnoreply@blogger.comtag:blogger.com,1999:blog-5975524006824862804.post-56694441428376258402007-09-02T13:58:00.000-07:002007-09-02T13:58:00.000-07:00If the two modules' assumptions and guarantees are...<I> If the two modules' assumptions and guarantees are compatible, they can be combined just fine.</I><BR/><BR/>That, of course, is the big "if".<BR/><BR/>Paul.Paul Johnsonhttps://www.blogger.com/profile/07353083601285449293noreply@blogger.comtag:blogger.com,1999:blog-5975524006824862804.post-74020217089842665632007-09-02T08:34:00.000-07:002007-09-02T08:34:00.000-07:00In your explanation of why two independently writt...In your explanation of why two independently written modules of code in a non-GC language cannot be combined, you seem to assume that the modules do not make explicit assumptions and guarantees about the validity duration of the references they receive and hand out. This assumption does not hold for properly designed C++ libraries (I'm only considering C++ in my response), for which validity duration and ownership guarantees for conveyed references and raw pointers (and similar things like iterators) are explicitly documented. For example, for all containers in the C++ standard library, it is explicitly documented which operations on the containers invalidate which iterators and references to the elements.<BR/><BR/>If the two modules' assumptions and guarantees are compatible, they can be combined just fine.Anonymousnoreply@blogger.com