C'mon, why stop there? Implement Scheme in your toy lambda. Then implement another toy lambda in your Scheme, and a Scheme in that. Continue until it takes several minutes to do (fib 5). Then, write JIT compiler for that Scheme. See what it takes to get down to pre-Inception levels of performance.

Now, you've actually learned something: Abstractions are costly.

Too late, someone already did that and measured the overhead of up to five interpretations layers: "Scheme benchmarking with a meta-circular" interpreter http://yinwang0.wordpress.com/2013/11/04/scheme-benchmarking... Archive: http://web.archive.org/web/20140105145428/https://yinwang0.w... HN discussion: https://news.ycombinator.com/item?id=7045734 (25 points, 443 days ago, 9 comments) (The main critic is that it should compare more scheme implementations.)

Many modern schemes (and similar languages like Racket and Clojure) have many optimization, use bytecode and jit compiling, so the abstraction overhead is not as big as in the naive versions. And you get nice code and powerful macros in exchange.

IIRC Stalin is faster than C in some benchmarks, but the compiling time is very big. "Stalin: a global optimizing compiler for Scheme" https://github.com/barak/stalin HN discussion: https://news.ycombinator.com/item?id=8214343 (85 points, 220 days ago, 70 comments)