Peter (PEZ) Strömberg’s Post

Python is dynamic. Clojure is dynamicer? (defn g [x] (if (= 7 x) (do (defn g [y] (* y y)) (g x)) (+ 1 x))) [(g 1) (g 7) (g 2)] ;=> [2 49 4] Being able to do this with ease is what keeps me happy as a programmer.

**Dangerous Python** **Artifact #1 – a function that changes its own code** Most programmers assume one simple rule: if a function is called f, it always does the same thing. Python allows you to break that assumption. Not through eval. Not through dynamic imports. Directly inside the function object itself. In Python, every function has an attribute called __code__. This is the bytecode, the actual execution engine of the function. And it can be replaced while the program is running. Below the post you can see a minimal example. _________________________________________________________________ **What just happened?** At first the function f behaves normally. f(x) = x + 1 But when the condition x == 7 appears, a surgical operation happens: f.__code__ = ... From that moment on, the function behaves completely differently. The same object. The same name. A different engine. **Why is this dangerous?** This mechanism breaks several fundamental assumptions of programming. 1. Code stops being stable over time A function may do one thing at the beginning of the program and something entirely different five seconds later. 2. Debugging becomes harder Stack traces and code inspection may show one thing while the runtime is executing something else. 3. Tests may become unstable If tests run in a different order, the program may behave differently. **Why does Python allow this?** Because Python is not only a programming language. It is a runtime manipulation system. Functions, classes, and modules are just objects. And objects can be modified. This power is useful in: frameworks plugin systems instrumentation code analysis tools But in normal application code, this is closer to a museum artifact than a design pattern. PYTHON ALLOWS SOMETHING MOST LANGUAGES FORBID: A FUNCTION CAN REMAIN THE SAME FUNCTION… AND STILL CHANGE ITS CODE WHILE THE PROGRAM IS RUNNING.

  • No alternative text description for this image

Awful that LinkedIn strips indentation.

  • No alternative text description for this image

Wouldn't be more idiomatic using letfn? (defn g [x]     (if (= 7 x)       (letfn [(g [y]                  (* y y))]         (g x))       (+ 1 x)))

Like
Reply
See more comments

To view or add a comment, sign in

Explore content categories