1. Mutability vs Immutability
Python:
def mutate_list(l):
l.append(4)
my_list = [1, 2, 3]
mutate_list(my_list)
print(my_list) # [1, 2, 3, 4]
Mutable objects like lists or dictionaries change in-place.
JavaScript:
function mutateArray(arr) {
arr.push(4);
}
const myArray = [1, 2, 3];
mutateArray(myArray);
console.log(myArray); // [1, 2, 3, 4]
Rust:
fn mutate_vec(v: &mut Vec<i32>) {
v.push(4);
}
fn main() {
let mut v = vec![1, 2, 3];
mutate_vec(&mut v);
println!("{:?}", v); // [1, 2, 3, 4]
}
Mutability isn’t just about being able to change a value — it’s about ownership, borrowing, and responsibility.
2. Pass by Value vs Reference Confusion
Python passes references to objects by value. You’re not passing the object; you’re passing a reference.
def add_item(d):
d['new'] = 'yes'
data = {}
add_item(data)
print(data) # {'new': 'yes'}
JavaScript is the same. Object references are passed by value:
function modify(obj) {
obj.name = "changed";
}
const user = {};
modify(user);
console.log(user); // { name: "changed" }
Rust enforces clarity:
fn take_ownership(v: Vec<i32>) {
println!("{:?}", v);
}
fn main() {
let vec = vec![1, 2, 3];
take_ownership(vec);
// println!("{:?}", vec); // Error: vec moved
}
Rust forces you to be explicit with ownership. You won’t forget what’s happening.
3. Floating-Point Precision
print(0.1 + 0.2 == 0.3) # False
console.log(0.1 + 0.2 === 0.3); // false
fn main() {
println!("{}", 0.1 + 0.2 == 0.3); // false
}
Don’t use floats for precise decimal math. Use Decimal
in Python, BigInt
in JS (for integers), or crates like rust_decimal
in Rust.
4. Async != Efficient
JS:
async function getData() {
await fetch(url1);
await fetch(url2); // Waits for url1 to finish first
}
// Better:
await Promise.all([fetch(url1), fetch(url2)]);
Python:
async def main():
await asyncio.gather(
fetch(url1),
fetch(url2)
)
Rust (with Tokio):
let (a, b) = tokio::join!(task1(), task2());
Async needs parallelism. Not waiting like it’s synchronous.
5. Scope and Closures
JavaScript:
for (var i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 100);
} // Prints 3, 3, 3
for (let i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 100);
} // Prints 0, 1, 2
Python:
def funcs():
return [lambda i=i: i for i in range(3)]
for f in funcs():
print(f()) # 0 1 2
Rust:
let funcs: Vec<_> = (0..3).map(|i| move || println!("{}", i)).collect();
for f in funcs {
f();
} // 0 1 2
Closures capture variables, not their values — unless you’re deliberate.
6. Null vs Undefined vs None
JavaScript:
let x; // undefined
let y = null; // null
Python:
x = None
Rust:
let x: Option<i32> = None;
Different semantics. JS has undefined
and null
. Python has None
. Rust has Option
and it’s type-safe.
7. Big O Isn’t Optional
Bad complexity = bad performance.
Python:
# O(n^2)
for i in range(n):
for j in range(n):
pass
Rust:
for i in 0..n {
for j in 0..n {
// do stuff
}
}
Your language doesn’t save you. Your algorithm does.
8. Boolean Short-Circuiting
JS:
function expensive() { console.log("ran"); return true; }
false && expensive(); // nothing logs
Python:
False and expensive() # never runs expensive()
Rust:
fn expensive() -> bool {
println!("ran");
true
}
fn main() {
false && expensive(); // does not run
}
Short-circuiting matters in perf and in bugs.
9. Equality vs Identity
JS:
"5" == 5 // true
"5" === 5 // false
Always use ===
.
Python:
x = [1, 2]
y = [1, 2]
print(x == y) # True
print(x is y) # False
Rust:
let a = vec![1, 2];
let b = vec![1, 2];
println!("{}", a == b); // true
In Rust and Python, ==
compares content. Identity is a different thing.
10. Dependencies
JavaScript:
npm install left-pad
Do you really need that?
Python:
pip install requests
Useful. But don’t install everything you see on Stack Overflow.
Rust:
[dependencies]
serde = "1.0"
Even Rust has bloat if you let it. Crates aren’t free.
Every new dependency increases build time, audit size, and attack surface.
That’s all. No outro. Just get better at the basics. These aren’t obscure ideas. They’re just things you keep skipping.
See you next time I feel like writing one of these.