This is fine as far as it goes, but common tools for abstraction aren't powerful enough to capture all possible abstractions. For example, suppose that you want to write some Python code that opens a file, processes it, and then closes the file before returning the result, with the caveat that the file must get closed, even if the code that does a computation raises an exception. The code to do this looks like this:
file = open('/usr/dict/words')
try:
process(file)
finally:
file.close()
This little try/finally block is just so much boilerplate -- it has to be written every single time you open a file. This isn't so bad in this particular case, but it gets less and less maintainable the more complex your cleanup protocol is, because you have to repeat the pattern everywhere you use it. The probability of getting it right everywhere rises exponentially with the number of uses.
You could theoretically code it up as a higher-order function, but a) that doesn't work in languages without HOFs, and b) it's generally pretty yucky looking.
The solution, in languages with macros, is to try and wrap these patterns syntactically. For example, Dylan has a macro called with-open-file that is used like this:
with-open-file(file = "/usr/dict/words")
process(file);
end with-open-file;
This is defined with a macro:
define macro with-open-file
{
with-open-file (?stream:variable = ?namestring:expression,
#rest ?parameters:expression)
?:body
end
}
=> {
let stream = #f;
block ()
stream := make(<file-stream>, locator: ?namestring, ?parameters);
let ?stream = stream;
?body;
cleanup
if (stream)
close(stream);
end if;
end block
}
end macro with-open-file;
The reason this is nice is partly because it's marginally more terse, but mostly because the cleanup sequence is defined in only one place. The probability of making an error is constant in the number of uses, and once made it can be easily localized and fixed. But even if your language doesn't have macros, it's WELL worth looking for common patterns and adding them as library functions/new syntax. Eliminating redundancy eliminates errors.