Self-Modifying Code: The Programming Magic You Didn’t Know You Needed | Web Theory: Part 14
Mohammadreza Emamyari
Posted on November 15, 2024
Programming can feel like magic sometimes. You write some text, and voilà, your computer does incredible things! But what if I told you that code can rewrite itself while it’s running? That’s the magic of self-modifying code, a fascinating concept that has both practical applications and a hint of mystery.
In this article, we’ll dive into what self-modifying code is, explore its real-life uses, and have some fun with JavaScript examples. Don't worry—we’ll keep things simple and exciting!
What Is Self-Modifying Code?
Self-modifying code is code that changes itself as it executes. Imagine a program editing its own instructions and then continuing to run with its newly altered logic. It’s like a chef changing the recipe halfway through cooking based on the flavor so far.
For instance, a simple piece of code might add numbers in one run but decide to subtract them in the next, all based on what it “learns” during execution.
While it might sound like science fiction, self-modifying code has been around for a long time. In the early days of computing, when memory was limited, programmers used it to optimize code. Today, it’s mostly used in niche areas like artificial intelligence, virus design (yikes!), or creating code that adapts to new inputs.
Why Would You Use Self-Modifying Code?
- Optimization: Sometimes, it’s faster to rewrite parts of the code than to create multiple versions of the same logic.
- Adaptability: Programs can change behavior without restarting or loading new code.
- Dynamic Features: Some creative applications like obfuscating code or generating unique behaviors in games use this concept.
The Risks of Self-Modifying Code
Self-modifying code is like a double-edged sword. While it’s powerful, it’s also risky:
- Debugging becomes hard because the code you see isn’t the code running anymore.
- Security risks arise since malicious actors can exploit it.
- Unpredictable behavior can creep in if changes aren’t handled carefully.
So, use it wisely and sparingly.
A Fun Example with JavaScript
JavaScript doesn’t natively support self-modifying code in the way assembly language or C might, but we can get creative. Let’s explore a simple example to see how a program can "change itself."
Example 1: Code that rewrites its function
Here’s a JavaScript function that rewrites itself based on a condition:
let action = function() {
console.log("Hello, I'm the original code!");
// Modify the function itself
action = function() {
console.log("I've been modified!");
};
};
// Call the function twice to see the effect
action(); // Logs: "Hello, I'm the original code!"
action(); // Logs: "I've been modified!"
What’s happening here?
- The
action
function initially logs a message. - After its first execution, it redefines itself to log something else.
- When called again, the new definition takes over.
This might seem like a gimmick, but it’s a simplified example of how self-modifying code can work in practice.
Example 2: Dynamic Code Generation
JavaScript has a powerful eval()
function that lets you execute strings as code. While eval()
is risky and generally frowned upon, it’s perfect for understanding self-modifying concepts.
let multiplier = 2;
let modifyCode = function() {
// Generate new code dynamically
let newCode = `
console.log('New multiplier: ${multiplier}');
multiplier *= 2;
`;
// Execute the new code
eval(newCode);
};
modifyCode(); // Logs: "New multiplier: 2"
modifyCode(); // Logs: "New multiplier: 4"
modifyCode(); // Logs: "New multiplier: 8"
In this example:
- The function creates and executes new code at runtime.
- The multiplier changes dynamically, and the behavior evolves with each call.
Example 3: Self-Updating Logic
Here’s another scenario: a quiz program that modifies itself based on user input.
let askQuestion = function() {
let question = "What is 2 + 2?";
let answer = 4;
console.log(question);
// Update behavior based on the answer
askQuestion = function(userAnswer) {
if (userAnswer == answer) {
console.log("Correct! Changing the question...");
question = "What is 3 + 5?";
answer = 8;
} else {
console.log("Incorrect. Try again!");
}
};
};
// First question
askQuestion(); // Logs: "What is 2 + 2?"
// User answers
askQuestion(4); // Logs: "Correct! Changing the question..."
askQuestion(7); // Logs: "Incorrect. Try again!"
askQuestion(8); // Logs: "Correct! Changing the question..."
This program changes its question and answer dynamically, creating a new user experience each time.
When Should You Avoid It?
Despite its cool factor, self-modifying code is rarely the best solution in modern programming. Consider using more readable and maintainable techniques like configuration files, polymorphism, or state machines unless you have a specific reason to modify code dynamically.
Wrapping It Up
Self-modifying code is a powerful tool that offers incredible flexibility—but with great power comes great responsibility. It’s not something you’ll use every day, but it’s worth understanding for the occasional situation where adaptability or optimization is critical.
Whether you’re experimenting with JavaScript or diving deeper into programming, self-modifying code is a reminder of how dynamic and creative coding can be. So go ahead—tinker, play, and marvel at the magic of code that can write itself!
🔗 Link to my article pertaining to Code Smell and Design Smell
Posted on November 15, 2024
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.
Related
November 15, 2024