IWETHEY v. 0.3.0 | TODO
1,095 registered users | 0 active users | 0 LpH | Statistics
Login | Create New User
IWETHEY Banner

Welcome to IWETHEY!

New Re: Reusable components?
What Paul Graham means is that a repeated pattern is something you should wrap up in an abstraction and reuse. A common practice when refactoring is to look for sequences of repeated code, and then wrap that up into a method or function, which you call henceforth. "Once and only once", as the XP people say.

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.
New Macros
Maybe I've had too much experience with m4 and C-style macros, but whenever I think a macro is the best way to do something, it usually comes back and bites me in the butt.
Famous last RPG quotes: "I'll just shoot this fireball down the dungeon passageway..."
New Not just macros!
If you've had experience with C and M4 macros, you've had too much experience with them. :) They just suck. The various branches of the Lisp family tree -- Common Lisp, Dylan, Scheme -- all have macro systems that don't cause crippling spinal trauma. But macros are really besides the point: they came up mostly because I wanted an example of a kind of abstraction that regular procedural abstraction doesn't work all that great at, and not surprisingly the obvious examples come from languages that have non-procedural ways of building abstractions. If I have the tools to capture an abstraction, I'll be more likely to keep an eye out for them.

For example, I really like Perl 6's built-in grammar support. Writing recursive descent parsers by hand isn't actually hard, per se. It's just that the code comes in a very stereotyped form and it's a great idea to sugar away the repetitious bits, so that when you are debugging you don't have to first figure out whether an error happened because you made a conceptual error or just because you mistyped some boilerplate.

Another example is Ocaml's module system. It is, honestly, the closest I have ever seen a language come to making software out of interchangeable parts. The basic idea is to make linking part of the module language: you can write code that is parameterized on the modules it uses. Parameterized modules (called functors) take some modules as arguments, and then build a module. For example, you can build a case-insensitive string map like this:


module CaseFoldCmp =
struct
type t = string
let compare a b =
compare (String.lowercase a) (String.lowercase b)
end
\t
module CaseFoldingMap = Map.Make(CaseFoldCmp)


And just like that, you have a case-folding map module that has all of the operations of the standard library's Map module. This is very cool.
New Re: Not just macros!
To me, that's not clear at all. Where did A and B come from? Vapor? Assumed arguments to functions? Some sort of object-oriented stuff that I haven't wrapped my mind around yet?
New Re: Not just macros!
That's a function definition -- a and b are the arguments. Caml has a funny syntax. Here's an annotated version, with comments (* like this *).

 
module StringCmp =
struct
type t = string (* This is like a C typedef *)

(* This is a function definition. 'let compare a b = <foo>'
declares a function that takes two arguments a and b. The <foo>
expression after the = is the function body. Function calls don't
use the 'f(x, y)' syntax. Instead, Caml uses simple
juxtaposition: 'f x y' instead. *)

let compare a b =
compare (String.lowercase a) (String.lowercase b)

(* This call to compare calls the generic comparison function, and
rebinds it locally in this module. (String.lowercase s) will return
a lowercase version. So what we are doing is lowercasing both args
and then calling the generic compare, to get a case-insensitive
comparison.
*)
end
     TPC slides are coming online - (ben_tilly) - (43)
         Problems with patterns - (JayMehaffey) - (42)
             Re: Problems with patterns - (Dominus) - (7)
                 Fixing existing languages... - (admin)
                 Re: Problems with patterns - (JayMehaffey)
                 Context shouldn't be C++ - (tuberculosis)
                 Re: Problems with patterns - (neelk) - (1)
                     That is what Perl 6 is about :-) - (ben_tilly)
                 Please don't remove the slides - (ben_tilly)
                 Patterns and languages. - (Arkadiy)
             The iterators complaint is truncated, not misguided - (ben_tilly) - (33)
                 Reusable components? - (wharris2) - (32)
                     Re: Reusable components? - (neelk) - (4)
                         Macros - (wharris2) - (3)
                             Not just macros! - (neelk) - (2)
                                 Re: Not just macros! - (wharris2) - (1)
                                     Re: Not just macros! - (neelk)
                     What "prevailing style of thought" are you talking about? - (ben_tilly) - (26)
                         Speaking for myself... - (tseliot) - (25)
                             Re: Speaking for myself... - (neelk) - (24)
                                 Paul Graham on OO - (tablizer) - (23)
                                     Note his first criticism - (ben_tilly) - (8)
                                         Elitist claim? - (tablizer) - (7)
                                             Don't guess, measure! - (neelk) - (4)
                                                 Simplify - (tablizer) - (3)
                                                     Re: Simplify - (neelk) - (2)
                                                         Depends on the language - (ben_tilly) - (1)
                                                             This is why I prefer PHP to C... :-) -NT - (static)
                                             You can judge that for yourself - (ben_tilly)
                                             You can judge that for yourself - (ben_tilly)
                                     HAS-A is orthogonal to OO - (admin) - (13)
                                         Guess you gotta... - (folkert) - (1)
                                             Muah. -NT - (admin)
                                         It is more common in OO - (tablizer) - (10)
                                             Don't go there. You will regret it. -NT - (static) - (1)
                                                 What is wrong with a little romp with a cute harmless troll? -NT - (tablizer)
                                             Been down this road before... - (admin) - (7)
                                                 Defining definition - (tablizer) - (6)
                                                     Mister... - (folkert) - (5)
                                                         Frameworks and votes - (tablizer) - (4)
                                                             Now... - (folkert) - (3)
                                                                 Erect Ape - (tablizer) - (2)
                                                                     Hey.. I feel the *same* way about the tyranny of - (Ashton) - (1)
                                                                         What we need are more DISorganized religions? Hmmm -NT - (tablizer)

Mmmmm... warm chunky cheese Danish... in a cup! How convenient is that??
71 ms