Jens G. writes in with a useful programming mechanism usually found in functional languages. Say you have a semipredicate - a block of code that returns a logical false if the code fails, but an actual return value if it succeeds. Opening a file is a good example. You'd like to return the file handle if you got it, but do something else if you didn't, like raise an exception.
Naively, you could do:
if (semipredicate()) {return semipredicate();}
else {....}
but that requires two calls to semipredicate(), which could be expensive. Of course, you could bind the result to a local variable:
foo = semipredicate();
if (foo) {return foo;}
else {...}
Local variables are messy and inelegant, though, and what's a functional language if not elegant? In C-style code, you could use
return (semipredicate() || somethingelse() );
but then you aren't able to change the return value, which would be a very handy thing indeed. Enter anaphoric macros. An anaphor, as Jens explains, is a linguistic term used to refer to something said previously. Pronouns in English are anaphors.
Enter LISP and all its parenthetical goodness. Basically, we define a macro that captures the result of the semipredicate, and that result can be manipulated in the source code. Here's the definition for anaphoric-if:
(defmacro aif (condition consequence &optional (alternative nil))
`(let ((it ,condition))
(if it ,consequence ,alternative)))
The backquote (`) character lets the LISP interpreter know to only evaluate the bits of code inside the macro that are marked with a comma. So in this macro, "it" is bound to the result of condition, and then we evaluate consequence if condition returned something other than NIL, and alternative otherwise. You can use this macro in the source like so:
(aif (predicate ...) it (something_else ...))
Notice how you can refer to "it" like it's a free variable, but when the macro is expanded it will actually refer to the result of predicate! This allows for neat things like being able to return a modified value of it:
(aif (predicate ...) (* it 2) (something_else ...))
There are also anaphoric versions of while, do, etc. Visit the On Lisp page to learn more.
Tuesday, December 11, 2007
Thursday, December 6, 2007
Cool Hack Of The Day Grand Opening!
Based off of this reddit thread, Cool Hack Of The Day is now live! The site won't be able to stay alive without your help, so please email your best examples of coding prowess to chotd.feedback@gmail.com.
We'll start the site with one of the more legendary hacks ever seen - Carmack's Inverse Square Root.
We'll start the site with one of the more legendary hacks ever seen - Carmack's Inverse Square Root.
float Q_rsqrt( float number )A more thorough history of this code can be found here.
{
long i;
float x2, y;
const float threehalfs = 1.5F;
x2 = number * 0.5F;
y = number;
i = * ( long * ) &y; // evil floating point bit level hacking
i = 0x5f3759df - ( i >> 1 ); // what the fuck?
y = * ( float * ) &i;
y = y * ( threehalfs - ( x2 * y * y ) ); // 1st iteration
// y = y * ( threehalfs - ( x2 * y * y ) ); // 2nd iteration, this can be removed
#ifndef Q3_VM
#ifdef __linux__
assert( !isnan(y) ); // bk010122 - FPE?
#endif
#endif
return y;
}
Subscribe to:
Posts (Atom)