Assertions are a Good Thing. Sadly, most programming languages support a very limited set of assertions; the most common case is just specifying a boolean expression, based on current variable values, that must evaluate to true in order for the assertion to succeed. Some languages, such as Eiffel, offer a slightly more advanced language for expressing some assertions -- for example, the old keyword can be used in post-conditions to refer to the original value of variables that might have changed during evaluation.
In general, any assertion mechanism that allows programmers to use higher-level concepts, or measure properties that are not readily accessible otherwise, is good progress. Assertions for heap properties are not a new thing, but in GC Assertions: Using the Garbage Collector to Check Heap Properties (PLDI '09), E. A. Aftandilian and S. Z. Guyer suggest both a rich set of heap-related assertions, plus a novel mechanism for performing the tests with minimal runtime overhead (<3% when a significant set of assertion is used).
The authors claim their system to be more precise than static analysis, since it tests the actual, concrete heap, and work well in the presence of (commonly used) mechanisms like reflection and dynamic class loading; more efficient than runtime invariant checks; and more accurate than heuristics.
The set of assertions offered in this system include assert-dead(ref) (zero incoming references), assert-alldead() (for all objects allocated in a marked region), assert-instances(type), num), assert-unshared(ref) (one incoming pointer), and more. Assertion violations provide a dump that shows the path from a memory root (e.g., thread stack or static field) to the violating object.
The system's strength lies in the fact that assertions are tested not when encountered at runtime, but rather on the following GC cycle; but this imposes some limitations on the assertions that can be tested for. What I found missing is (a) a slightly richer set of assertions, with variants such as assert-min-references or assert-max-references; and (b) conditional asserts, as in, "test this assertion only if that condition holds". The conditions can be limited to very trivial ones, e.g., "if ref != null, assert-min-references(ref, 2)" can be used to verify that a given reference to an object is never the only one. (Yes, this specific example can be achieved by means of weak references, but that complicates the program's code, and unlike assertions, it cannot be turned off; I don't want the system to auto-release my reference if it's the last one, I want to assert that it never is.)
All in all, the paper presents a great new take on memory-related assertions. If Design-by-Contract is ever added to the Java language (as it should be), this paper provides a first glimpse into the possibilities of contracts that go beyond the trivial and easily-tested ones, by wisely taking advantage of the managed runtime environment.
Wednesday, December 23, 2009
Sunday, December 6, 2009
Eliminating the Call Stack to Save RAM
"How do I sort on disk?". This is the question that opens the first column in Jon Bentley's delectable Programming Pearls. The column was originally printed in 1983, and in book format in 1986. The asker thought that sorting on disk is required because the system he was programming for only had "about a thousand 16-bit words" (in other words, about 2KB) in free memory.
To please a new generation of readers, Bentley changed the question to deal with a "multi-megabyte" machine, with "only about a megabyte free", in the second edition of Programming Pearls, published in early 2000. I suppose Bentley's reasoning was, "anything smaller than that would sound unreasonable to a modern reader". How disappointing.
It was therefore very refreshing to read Eliminating the Call Stack to Save RAM, by Xuejun Yang, Nathan Cooprider, and John Regehr (LCTES '09). Over twenty-five years after Bentley's column first appeared, there still are people trying to save RAM on embedded systems, machines with "between hundreds of bytes and tens of kilybytes"! And, hey, what a neat memory-saving trick they present!
The idea presented in the paper is flattening: replacing function invocation and returns with simple jumps. This is different from inlining, since functions called from multiple sites are not duplicated; and in fact, flattening is performed only after single-callsite functions are inlined. With flattening, a function such as:
Is transformed into:
And a simple call like val = foo(actual1, actual2) is transformed into:
Clearly, the technique cannot be easily applied to programs with any sort of recursion. The presence of other "flattening hazards", such as calls through function pointers, also complicate things. But in the world of embedded software for micro-controller units (MCUs), these are rarities, exceptions rather than the norm. (Also clearly, the authors are being conservative, since the default clause in the returning switch statement could be replaced with the last valid value.)
Flattening is followed by lifting, where global variables are transformed into local variables (of main, the last remaining function). As the authors note, "In effect, flattening and lifting trick a legacy C compiler into performing whole-program optimizations. This works because modern compilers, running on modern desktop machines, are perfectly capable of whole-program compilation for MCU-sized codes."
Flattening and lifting increase program size (by 14% on average, ranging from about 2% to slightly less than 40% on a set of 15 test applications). How can this save memory? Well, as the title implies, the process, when applied aggressively, eliminates all usage of a call stack. And this, in turn, reduces RAM usage by 20% on average (ranging from 2% to over 40% for individual cases). CPU usage is decreased by 3% on average (while CPU usage for some programs is reduced by over 15%, it is actually increased for some other programs, by as much as 22%. I wonder how much would this be reduced by optimizing the order of the options in the "return switch"?).
In their lucidly written paper, the authors describe some of the interesting challenges they encountered in implementing this technique (for example, false execution paths that prevent some compiler optimizations) and the solutions found (in this case, passing callgraph data into the optimizer, even though the callgraph no longer exists as such by the time the optimizer runs, due to flattening). They also present some unexpected benefits, for example in terms of program security (no buffer overflow vulnerabilities!).
To please a new generation of readers, Bentley changed the question to deal with a "multi-megabyte" machine, with "only about a megabyte free", in the second edition of Programming Pearls, published in early 2000. I suppose Bentley's reasoning was, "anything smaller than that would sound unreasonable to a modern reader". How disappointing.
It was therefore very refreshing to read Eliminating the Call Stack to Save RAM, by Xuejun Yang, Nathan Cooprider, and John Regehr (LCTES '09). Over twenty-five years after Bentley's column first appeared, there still are people trying to save RAM on embedded systems, machines with "between hundreds of bytes and tens of kilybytes"! And, hey, what a neat memory-saving trick they present!
The idea presented in the paper is flattening: replacing function invocation and returns with simple jumps. This is different from inlining, since functions called from multiple sites are not duplicated; and in fact, flattening is performed only after single-callsite functions are inlined. With flattening, a function such as:
int foo (int formal1, int formal2) {
... body ...
return ret;
}Is transformed into:
_foo_body:
... body ...
_foo_ret_value = ret;
switch (_foo_ret_site) {
case 0: goto _foo_ret_site_0;
case 1: goto _foo_ret_site_1;
case 2: goto _foo_ret_site_2;
...
default: panic();
}
And a simple call like val = foo(actual1, actual2) is transformed into:
_foo_formal1 = actual1;
_foo_formal2 = actual2;
_foo_ret_site = 2;
goto _foo_body;
_foo_ret_site_2:
val = _foo_ret_value;
Clearly, the technique cannot be easily applied to programs with any sort of recursion. The presence of other "flattening hazards", such as calls through function pointers, also complicate things. But in the world of embedded software for micro-controller units (MCUs), these are rarities, exceptions rather than the norm. (Also clearly, the authors are being conservative, since the default clause in the returning switch statement could be replaced with the last valid value.)
Flattening is followed by lifting, where global variables are transformed into local variables (of main, the last remaining function). As the authors note, "In effect, flattening and lifting trick a legacy C compiler into performing whole-program optimizations. This works because modern compilers, running on modern desktop machines, are perfectly capable of whole-program compilation for MCU-sized codes."
Flattening and lifting increase program size (by 14% on average, ranging from about 2% to slightly less than 40% on a set of 15 test applications). How can this save memory? Well, as the title implies, the process, when applied aggressively, eliminates all usage of a call stack. And this, in turn, reduces RAM usage by 20% on average (ranging from 2% to over 40% for individual cases). CPU usage is decreased by 3% on average (while CPU usage for some programs is reduced by over 15%, it is actually increased for some other programs, by as much as 22%. I wonder how much would this be reduced by optimizing the order of the options in the "return switch"?).
In their lucidly written paper, the authors describe some of the interesting challenges they encountered in implementing this technique (for example, false execution paths that prevent some compiler optimizations) and the solutions found (in this case, passing callgraph data into the optimizer, even though the callgraph no longer exists as such by the time the optimizer runs, due to flattening). They also present some unexpected benefits, for example in terms of program security (no buffer overflow vulnerabilities!).
Saturday, November 14, 2009
The Netflix "Reference Guide on our Freedom & Responsibility Culture"
Well, this isn't an academic paper, and it's not even directly about software engineering, but I still find it a fascinating read, and related to the work of many software engineers in the industry. I'm talking about the Netflix "Reference Guide on our Freedom & Responsibility Culture". I recommend that you read it first: it's a fascinating read. Many of the ideas and principles presented there make perfect sense; some are a joy to read. Still, the document left me feeling troubled. Below is some criticism on two of the ideas and principles presented there.
The first painful point appears on page 26: "adequate performance gets a generous severance package". In other words, if you're just okay, you're outta here: we only want superstar performance. This is further hammered on page 29: managers are actively expected to let go of anyone they would not "fight hard to keep": the so-called "Keeper Test". The basic idea is to maintain an all-star team (which Netflix claims it does successfully). But I know that, as an employee, I'd have a very hard time looking at the eyes of my manager every day and wondering, "will she fire me today"? Oh, not because I'm not good -- I am good! -- but because I've had a rough week?
Sure, this is toned down a bit on page 32: "People who have been stars for us, and hit a bad patch, get a near term pass because we think they are likely to become stars for us again". But what's "near term"? If I hit a bad week, it's probably OK. A bad month? If I get pregnant (hypothetically speaking), how likely am I to retain my job if I hit a bad trimester? I can easily see how a short bad period can lead an employee to a downward spiral, caused in large part by his worries over retaining his job.I understand that job security in the US is not nearly as strong as it is in Europe, so while this is an extreme case, it's not drastically different than the case of most employees in most companies. But it still sounds unwise to me to have employees work in an explicit state of constant fear ("you should periodically ask your manager"..., p. 30). The annual comp review (pages 97-105) is just a different aspect of the same issue.
As an aside, I also think it's unwise for the company itself to release employees with proven capabilities, that are still good (remember, we're not talking about bad or lousey employees here: it's about good ones that are no longer stars), just to "open a slot to try to find a star" (p. 29). It's probably wiser to find the star first, and let go of the other employee later.
The second painful point the vacation policy -- or lack thereof (p. 68). Yes, the quip about "no clothing policy either" is amusing, but think about this for a moment: an employee who arrives sans clothing to the office is likely to lose the job; there's no policy, but everybody knows what's expected of them. With no vacation policy... what exactly is expected of employees? I have a strong feeling that if you'll measure the number of vacation days Netflix employees take annually, it will turn out to be significantly lower than that of employees in companies across the street. Because, when you constantly have to prove that you're a star, taking a week-long vacation sounds like a downright risk. When your pay is directly affected by your performance, you might work yourself to death. The advantage of a clear policy, N days per year, is that it's two-sided: while it limits the number of days off an employee can take, it also forces him to take some days off. And in most companies, a star performer that needs a few extra vacation days will find it easy to get approval for them.
I realize that my statement above, "when your pay is directly affected by your performance, you might work yourself to death", is true in many professions -- self-employed people, salespeople, shop owners, and so forth are exactly in this position. But as a salaried employee, I enjoy the benefit of knowing that the business will survive if I take a week off, and nobody will count it against me. In fact, I'm fully expected to use up those vacation days. This is one of the major advantages of being an employee in a large and stable company, and Netflix is robbing that advantage from their employees (while making it sound like a good thing).
These are the two key problems I've found with this document. There are many other nits to pick in there, but none is as important, I believe.
The first painful point appears on page 26: "adequate performance gets a generous severance package". In other words, if you're just okay, you're outta here: we only want superstar performance. This is further hammered on page 29: managers are actively expected to let go of anyone they would not "fight hard to keep": the so-called "Keeper Test". The basic idea is to maintain an all-star team (which Netflix claims it does successfully). But I know that, as an employee, I'd have a very hard time looking at the eyes of my manager every day and wondering, "will she fire me today"? Oh, not because I'm not good -- I am good! -- but because I've had a rough week?
Sure, this is toned down a bit on page 32: "People who have been stars for us, and hit a bad patch, get a near term pass because we think they are likely to become stars for us again". But what's "near term"? If I hit a bad week, it's probably OK. A bad month? If I get pregnant (hypothetically speaking), how likely am I to retain my job if I hit a bad trimester? I can easily see how a short bad period can lead an employee to a downward spiral, caused in large part by his worries over retaining his job.I understand that job security in the US is not nearly as strong as it is in Europe, so while this is an extreme case, it's not drastically different than the case of most employees in most companies. But it still sounds unwise to me to have employees work in an explicit state of constant fear ("you should periodically ask your manager"..., p. 30). The annual comp review (pages 97-105) is just a different aspect of the same issue.
As an aside, I also think it's unwise for the company itself to release employees with proven capabilities, that are still good (remember, we're not talking about bad or lousey employees here: it's about good ones that are no longer stars), just to "open a slot to try to find a star" (p. 29). It's probably wiser to find the star first, and let go of the other employee later.
The second painful point the vacation policy -- or lack thereof (p. 68). Yes, the quip about "no clothing policy either" is amusing, but think about this for a moment: an employee who arrives sans clothing to the office is likely to lose the job; there's no policy, but everybody knows what's expected of them. With no vacation policy... what exactly is expected of employees? I have a strong feeling that if you'll measure the number of vacation days Netflix employees take annually, it will turn out to be significantly lower than that of employees in companies across the street. Because, when you constantly have to prove that you're a star, taking a week-long vacation sounds like a downright risk. When your pay is directly affected by your performance, you might work yourself to death. The advantage of a clear policy, N days per year, is that it's two-sided: while it limits the number of days off an employee can take, it also forces him to take some days off. And in most companies, a star performer that needs a few extra vacation days will find it easy to get approval for them.
I realize that my statement above, "when your pay is directly affected by your performance, you might work yourself to death", is true in many professions -- self-employed people, salespeople, shop owners, and so forth are exactly in this position. But as a salaried employee, I enjoy the benefit of knowing that the business will survive if I take a week off, and nobody will count it against me. In fact, I'm fully expected to use up those vacation days. This is one of the major advantages of being an employee in a large and stable company, and Netflix is robbing that advantage from their employees (while making it sound like a good thing).
These are the two key problems I've found with this document. There are many other nits to pick in there, but none is as important, I believe.
Wednesday, October 28, 2009
Retrospective: An Axiomatic Basis for Computer Programming
C.A.R. Hoare is one of those people who laid the very foundations of software engineering. He is probably best-known for inventing the quicksort algorith. He's also the one who invented the null pointer; the concept of a synchronization monitor in operating systems; and much more.
Forty years ago, Hoare published "An Axiomatic Basis for Computer Programming", aiming to formalize programming, under the belief that "an elegant formalization [of the semantics of a programming language] might consist of a collection of axioms, similar to those introduced by Euclid to formalize the science of land measurement." His hope was "to find axioms that would be strong enough to enable programmers to discharge their responsibility to write correct and efficient programs".
The quotes are from a new retrospective article, titled simply "Retrospective: An Axiomatic Basis for Computer Programming" and published in the October 2009 issue of Communications of the ACM -- the same journal that published the original paper. In this new paper, Hoare surveys changes in the field of software engineering over four decades, and compares them to his expectations and vision. In particular, he believed that software verification and proof will take off after "some accident or series of accidents involving loss of life, perhaps followed by an expensive suit for damages". But instead, any accidents -- such as the Ariane V crash in 1996 -- led to more rigorous testing, rather than a take-off of verification. Verification of software and axiomatic programming remained mostly an academic practice.
Surprisingly (for Hoare), what caused verification to be introduced into software development practices, to the extent that it is used, is security considerations: "the attack of the hacker, leading to an occasional shutdown of worldwide commercial activity". He claims that "the only way to reach these vulnerabilities is by automatic analysis of the text of the program", i.e., verification techniques. And what about testing? Testing is important, says Hoare, but not for testing the program; rather, they are used for testing the programmer.
Forty years ago, Hoare published "An Axiomatic Basis for Computer Programming", aiming to formalize programming, under the belief that "an elegant formalization [of the semantics of a programming language] might consist of a collection of axioms, similar to those introduced by Euclid to formalize the science of land measurement." His hope was "to find axioms that would be strong enough to enable programmers to discharge their responsibility to write correct and efficient programs".
The quotes are from a new retrospective article, titled simply "Retrospective: An Axiomatic Basis for Computer Programming" and published in the October 2009 issue of Communications of the ACM -- the same journal that published the original paper. In this new paper, Hoare surveys changes in the field of software engineering over four decades, and compares them to his expectations and vision. In particular, he believed that software verification and proof will take off after "some accident or series of accidents involving loss of life, perhaps followed by an expensive suit for damages". But instead, any accidents -- such as the Ariane V crash in 1996 -- led to more rigorous testing, rather than a take-off of verification. Verification of software and axiomatic programming remained mostly an academic practice.
Surprisingly (for Hoare), what caused verification to be introduced into software development practices, to the extent that it is used, is security considerations: "the attack of the hacker, leading to an occasional shutdown of worldwide commercial activity". He claims that "the only way to reach these vulnerabilities is by automatic analysis of the text of the program", i.e., verification techniques. And what about testing? Testing is important, says Hoare, but not for testing the program; rather, they are used for testing the programmer.
Saturday, July 25, 2009
Debugging Method Names
What's in a name? More specifically, a program identifier? Proper identifiers make the program easier to understand and maintain; and it is no secret that maintenance costs often make the lion's share of software development costs. Thus, as every beginning programmer should know, carefully choosing method names is an important part of the software engineer's work.
In Debugging Method Names (appeared in ECOOP '09), the authors -- Einar W. Høst and Bjarte M. Østvold -- apply statistical analysis to method names, finding correlation between certain verbs that appear as prefixes in method names (find, is, get, set, add, remove, etc.) and programmatic attributes of methods (has loops, creates objects of the containing type, returns void, etc.). In a way, they apply Wittgenstein Sprachspiel ("language game") to the language of programs: a word means whatever it is used for, rather than having an intrinsic meaning. And thus, one can easily find that methods called setSomething are highly correlated with a void return type, accepting one or more parameters, and updating a field. While this is hardly surprising, deeper connections also appear when the authors analyze a very large codebase, consisting of over one million methods.
Once the statistical correlations are located, outliers can be detected. And indeed, the authors show how the method was used to detect actual "naming bugs" in the analyzed programs. For example, consider the following method, from AspectJ's source code:
The authors' software, after learning about method names and with no previous assumptions about names, claims that it expects this method to be findSomething, whereas it is actually named containsField. The analysis is right on spot -- a more proper name for this method would have been findField.
Other detected problems include an equals method that creates objects of the compared type (this is an actual bug, not just a naming problem), setters named isBooleanProperty (where Java programmers would expect setBooleanProperty), and more. The latter example is actually an indication of the system's strength: if the analyzed codebase had been Objective-C, this wouldn't have been detected as a problem, since in that language, boolean setters are indeed named with an initial is.
Are the outliers always bugs? Hardly. Manual inspection of a subset (an admittedly small one) shows that about 30% of the purported "bugs" aren't really bugs. The authors state that overly complex getter methods, as well as methods which include logging code, tend to confuse the system. Still, this seems to be like the first step towards applying statistical NLP to software engineering, with very promising results.
In Debugging Method Names (appeared in ECOOP '09), the authors -- Einar W. Høst and Bjarte M. Østvold -- apply statistical analysis to method names, finding correlation between certain verbs that appear as prefixes in method names (find, is, get, set, add, remove, etc.) and programmatic attributes of methods (has loops, creates objects of the containing type, returns void, etc.). In a way, they apply Wittgenstein Sprachspiel ("language game") to the language of programs: a word means whatever it is used for, rather than having an intrinsic meaning. And thus, one can easily find that methods called setSomething are highly correlated with a void return type, accepting one or more parameters, and updating a field. While this is hardly surprising, deeper connections also appear when the authors analyze a very large codebase, consisting of over one million methods.
Once the statistical correlations are located, outliers can be detected. And indeed, the authors show how the method was used to detect actual "naming bugs" in the analyzed programs. For example, consider the following method, from AspectJ's source code:
/**
* @return field object with given name, or null
*/
public Field name(String name) {
for (Iterator e = this.field_vec.iterator(); e.hasNext();) {
Field f = (Field) e.next();
if (f.getName().equals(name))
return f;
}
return null;
}
The authors' software, after learning about method names and with no previous assumptions about names, claims that it expects this method to be findSomething, whereas it is actually named containsField. The analysis is right on spot -- a more proper name for this method would have been findField.
Other detected problems include an equals method that creates objects of the compared type (this is an actual bug, not just a naming problem), setters named isBooleanProperty (where Java programmers would expect setBooleanProperty), and more. The latter example is actually an indication of the system's strength: if the analyzed codebase had been Objective-C, this wouldn't have been detected as a problem, since in that language, boolean setters are indeed named with an initial is.
Are the outliers always bugs? Hardly. Manual inspection of a subset (an admittedly small one) shows that about 30% of the purported "bugs" aren't really bugs. The authors state that overly complex getter methods, as well as methods which include logging code, tend to confuse the system. Still, this seems to be like the first step towards applying statistical NLP to software engineering, with very promising results.
Saturday, July 11, 2009
Producing Wrong Data Without Doing Anything Obviously Wrong
You'd expect code compiled with the gcc option -O3 to be faster than -O2 code, right? After all, the compiler spends more time on optimizing your code, and these are well-known optimizations that were deeply studied. So, would it surprise you if the code ended up being, say, 7% slower?
You test the code a day later, and suddenly, the very same code is 10% faster with -O3 as compared to -O2. What's going on here?
Let's see. Perhaps you've added or removed some totally unrelated environment variable?
Sounds odd, right? But this is exactly the behavior documented by the authors of Producing Wrong Data Without Doing Anything Obviously Wrong! (appeared in ASPLOS '09). They explain that a change in the size of the shell's environment can change the binary's alignment, causing noticeable differences in performance. They also show, although it is less surprising, that changes in the link order of the binary can have a measurable effect on performance.
The paper's claim is obviously not "play around with the environment size to find the performance sweet-spot". It is that measurement bias, a phenomenon well-known in experimental sciences, also exists in computer science experiments. They show that it exists regardless of the CPU, the benchmark used, or the compiler employed. Measurement bias in computer science is real, significant, commonplace, and unpredictable.
And thus, when developers try to measure the effect of an optimization, or the effectiveness of a new algorithm (when compared to an existing one), they should never be content with measurements -- even multiple measurements -- in a single settings. Change configurations; change platforms; play around with anything you can; randomize your setup; see if the performance difference that you suggest is real, or an artifact of the conincidental configuration you were using.
Will it work? Will the authors' "call for action" (section 8 in their paper) yield any results? I must admit I'm pessimistic. I think the only chance for this to have any effect is if conference reviewers will start demanding that experiment reports in papers include details about the measures taken to overcome measurement bias.
Until this happens, I cannot help but wonder how many times skillful craftsmen had devised great optimizations and applied them to their code, only to find out the code ends up being slower. The programmer shrug, not seeing what went wrong, and revert to the original, "more efficient", implementation. If only they had deleted one environment variable...
You test the code a day later, and suddenly, the very same code is 10% faster with -O3 as compared to -O2. What's going on here?
Let's see. Perhaps you've added or removed some totally unrelated environment variable?
Sounds odd, right? But this is exactly the behavior documented by the authors of Producing Wrong Data Without Doing Anything Obviously Wrong! (appeared in ASPLOS '09). They explain that a change in the size of the shell's environment can change the binary's alignment, causing noticeable differences in performance. They also show, although it is less surprising, that changes in the link order of the binary can have a measurable effect on performance.
The paper's claim is obviously not "play around with the environment size to find the performance sweet-spot". It is that measurement bias, a phenomenon well-known in experimental sciences, also exists in computer science experiments. They show that it exists regardless of the CPU, the benchmark used, or the compiler employed. Measurement bias in computer science is real, significant, commonplace, and unpredictable.
And thus, when developers try to measure the effect of an optimization, or the effectiveness of a new algorithm (when compared to an existing one), they should never be content with measurements -- even multiple measurements -- in a single settings. Change configurations; change platforms; play around with anything you can; randomize your setup; see if the performance difference that you suggest is real, or an artifact of the conincidental configuration you were using.
Will it work? Will the authors' "call for action" (section 8 in their paper) yield any results? I must admit I'm pessimistic. I think the only chance for this to have any effect is if conference reviewers will start demanding that experiment reports in papers include details about the measures taken to overcome measurement bias.
Until this happens, I cannot help but wonder how many times skillful craftsmen had devised great optimizations and applied them to their code, only to find out the code ends up being slower. The programmer shrug, not seeing what went wrong, and revert to the original, "more efficient", implementation. If only they had deleted one environment variable...
Monday, June 8, 2009
Confessions of a Used Programming Language Salesman
Erik Meijer is a language designer, and a big believer in functional programming in general and Haskell in particular. His essey Confessions of a Used Programming Language Salesman: Getting the Masses Hooked on Haskell is surprising and refreshing read. Not really a scientific paper, it appeared as an OOPSLA '07 Essey.
What is it really about? I think the following quote, from the Conclusions section, says it all: "Functional programming has nally reached the masses, except that it is called Visual Basic instead of Haskell."
We've all seen how functional programming concepts (like lambda functions and list comprehension) slowly appear in leading programming languages, often under different names. C#'s LINQ facility, for example, is list comprehension on steroids. Meijer explains that this tendency is no coincidence, and that in effect, some popular languages (led by Visual Basic 9, of all things!) are slowly but surely morphing into functional ones. They're a far cry from pure, lazy functional languages like Haskell, but these are baby steps in the right direction.
What is it really about? I think the following quote, from the Conclusions section, says it all: "Functional programming has nally reached the masses, except that it is called Visual Basic instead of Haskell."
We've all seen how functional programming concepts (like lambda functions and list comprehension) slowly appear in leading programming languages, often under different names. C#'s LINQ facility, for example, is list comprehension on steroids. Meijer explains that this tendency is no coincidence, and that in effect, some popular languages (led by Visual Basic 9, of all things!) are slowly but surely morphing into functional ones. They're a far cry from pure, lazy functional languages like Haskell, but these are baby steps in the right direction.
Subscribe to:
Posts (Atom)