This difference is stark when you look at what it's doing, but allows for some interesting uses when combined with lazy vals. We use it pretty extensively in our configuration loader (using twitter-eval) that allows us to do per-value overrides of configuration files by using lazy vals assigned to defs and then using the defs in the application (of all the performance bottlenecks we have, the possibly optimized out function call generated for the defs is negligible). The end result is that you can derive values from configuration settings prior to the configuration finishing being loaded. This means we don't have to care what order the configuration files are loaded in (they're separated by what they're configuring, with many shared between applications).