42 lines
20 KiB
JSON
42 lines
20 KiB
JSON
[
|
||
{
|
||
"id": "js-map-vs-foreach",
|
||
"output": "# `Array.prototype.map` vs `Array.prototype.forEach`\n\n## The Key Difference\n\n**`map` returns a new array** with the results of calling a function on every element, while **`forEach` returns `undefined`** and simply executes a function for each element (side effects only).\n\n---\n\n## `forEach` — Used for **side effects**\n\n```javascript\nconst numbers = [1, 2, 3];\n\nconst result = numbers.forEach(num => {\n console.log(num * 2); // prints 2, 4, 6\n});\n\nconsole.log(result); // undefined\n```\n\n## `map` — Used for **transformations**\n\n```javascript\nconst numbers = [1, 2, 3];\n\nconst result = numbers.map(num => num * 2);\n\nconsole.log(result); // [2, 4, 6]\n```\n\n---\n\n## Summary Table\n\n| Feature | `map()` | `forEach()` |\n|--------------------|--------------------------------|------------------------------|\n| **Return value** | New array | `undefined` |\n| **Purpose** | Transform data | Perform side effects |\n| **Chainable?** | ✅ Yes (returns an array) | ❌ No (returns `undefined`) |\n| **Mutates original?** | No (unless you explicitly do) | No (unless you explicitly do) |\n\n---\n\n## When to Use Which?\n\n- **Use `map`** when you need a **new array** based on transforming each element:\n ```javascript\n const names = users.map(user => user.name); // extract names\n ```\n\n- **Use `forEach`** when you just want to **do something** with each element (e.g., logging, updating the DOM, pushing to an external array):\n ```javascript\n users.forEach(user => sendEmail(user)); // side effect\n ```\n\n> **Rule of thumb:** If you're not using the returned array from `map`, you should probably be using `forEach` instead. Conversely, if you're building a new array inside `forEach`, you should probably be using `map`."
|
||
},
|
||
{
|
||
"id": "py-list-tuple",
|
||
"output": "# Tuples vs Lists in Python\n\n## Use a **Tuple** When:\n\n### 1. **Data is immutable (shouldn't change)**\nTuples signal that the data is fixed and read-only.\n```python\n# Coordinates, RGB colors, database records\npoint = (3, 5)\ncolor = (255, 128, 0)\n```\n\n### 2. **Heterogeneous, structured data (like a record)**\nWhen each position has a specific meaning:\n```python\n# (name, age, city) — like a lightweight struct\nperson = (\"Alice\", 30, \"New York\")\n```\n\n### 3. **Dictionary keys or set elements**\nTuples are **hashable** (if their contents are); lists are not:\n```python\n# ✅ Works\nlocations = {(40.7, -74.0): \"New York\", (34.0, -118.2): \"LA\"}\n\n# ❌ TypeError: unhashable type: 'list'\nlocations = {[40.7, -74.0]: \"New York\"}\n```\n\n### 4. **Performance matters**\nTuples are slightly faster and use less memory:\n```python\nimport sys\nprint(sys.getsizeof((1, 2, 3))) # 64 bytes (typical)\nprint(sys.getsizeof([1, 2, 3])) # 88 bytes (typical)\n```\n\n### 5. **Returning multiple values from a function**\n```python\ndef get_dimensions():\n return (1920, 1080) # parentheses optional\n\nwidth, height = get_dimensions()\n```\n\n---\n\n## Use a **List** When:\n\n### 1. **Data needs to be modified**\n```python\nshopping = [\"milk\", \"eggs\"]\nshopping.append(\"bread\") # Lists support mutation\nshopping.remove(\"milk\")\n```\n\n### 2. **Homogeneous collection (same type of items)**\nWhen you have a sequence of similar things:\n```python\nscores = [95, 87, 92, 78]\nnames = [\"Alice\", \"Bob\", \"Charlie\"]\n```\n\n### 3. **You need to sort, filter, or iterate and modify**\n```python\nnumbers = [3, 1, 4, 1, 5]\nnumbers.sort()\n```\n\n---\n\n## Quick Reference\n\n| Criteria | Tuple | List |\n|---|---|---|\n| **Mutable?** | ❌ No | ✅ Yes |\n| **Hashable?** | "
|
||
},
|
||
{
|
||
"id": "sql-inner-vs-left",
|
||
"output": "# INNER JOIN vs LEFT JOIN in SQL\n\n## INNER JOIN\n\nAn **INNER JOIN** returns only the rows where there is a **match in both tables**.\n\n```sql\nSELECT employees.name, departments.dept_name\nFROM employees\nINNER JOIN departments ON employees.dept_id = departments.id;\n```\n\n### Visualization:\n```\nTable A Table B\n┌─────┐ ┌─────┐\n│ │ │ │\n│ ┌──┼───────┼──┐ │\n│ │ │ RESULT│ │ │ ← Only the overlap\n│ └──┼───────┼──┘ │\n│ │ │ │\n└─────┘ └─────┘\n```\n\n---\n\n## LEFT JOIN (LEFT OUTER JOIN)\n\nA **LEFT JOIN** returns **all rows from the left table**, and the matched rows from the right table. If there's **no match**, the right side will contain `NULL`.\n\n```sql\nSELECT employees.name, departments.dept_name\nFROM employees\nLEFT JOIN departments ON employees.dept_id = departments.id;\n```\n\n### Visualization:\n```\nTable A Table B\n┌─────┐ ┌─────┐\n│█████│ │ │\n│█████│───────┼──┐ │ ← All of Table A + matching from B\n│█████│ RESULT│ │ │\n│█████│───────┼──┘ │\n│█████│ │ │\n└─────┘ └─────┘\n```\n\n---\n\n## Practical Example\n\nGiven these tables:\n\n| **employees** | | **departments** | |\n|---|---|---|---|\n| name | dept_id | id | dept_name |\n| Alice | 1 | 1 | Engineering |\n| Bob | 2 | 2 | Marketing |\n| Carol | **NULL** | 3 | Sales |\n\n### INNER JOIN Result:\n| name | dept_name |\n|-------|-------------|\n| Alice | Engineering |\n| Bob | Marketing |\n\n> ❌ Carol is **excluded** (no matching dept_id)\n> ❌ Sales is **excluded** (no employee references it)\n\n### LEFT JOIN Result:\n| name | dept_name |\n|-------|-------------|\n| Alice | Engineering |\n| Bob | Marketing |\n| Carol | **NULL** |\n\n> ✅ Carol is **included** with NULL for dept_name\n> ❌ Sales is still excluded"
|
||
},
|
||
{
|
||
"id": "ts-type-vs-interface",
|
||
"output": "# TypeScript: Type Alias vs Interface\n\nBoth `type` and `interface` can describe object shapes, but they have key differences that guide when to use each.\n\n## Interface\n\nBest for **defining object shapes and contracts**, especially when you expect them to be extended or implemented.\n\n```typescript\ninterface User {\n name: string;\n age: number;\n}\n\n// ✅ Declaration merging (auto-extends across files)\ninterface User {\n email: string;\n}\n\n// ✅ Extends other interfaces\ninterface Admin extends User {\n role: string;\n}\n\n// ✅ Classes can implement them\nclass AppUser implements User {\n name = \"John\";\n age = 30;\n email = \"john@example.com\";\n}\n```\n\n## Type Alias\n\nBest for **unions, intersections, tuples, primitives, and complex type expressions**.\n\n```typescript\n// ✅ Union types (interfaces CAN'T do this)\ntype Status = \"active\" | \"inactive\" | \"banned\";\ntype Result = Success | Error;\n\n// ✅ Intersection types\ntype Admin = User & { role: string };\n\n// ✅ Tuples\ntype Coordinate = [number, number];\n\n// ✅ Mapped / conditional types\ntype Readonly<T> = { readonly [K in keyof T]: T[K] };\ntype Nullable<T> = T | null;\n\n// ✅ Primitives & utility aliases\ntype ID = string | number;\n```\n\n## Quick Decision Guide\n\n| Scenario | Use |\n|---|---|\n| Object shape / API contract | `interface` |\n| Union or intersection types | `type` |\n| Declaration merging needed (e.g., library augmentation) | `interface` |\n| Tuples | `type` |\n| Primitives / literal types | `type` |\n| Mapped / conditional types | `type` |\n| Class implementation contract | `interface` |\n| Function signatures (standalone) | Either (both work) |\n\n## Key Differences Summary\n\n```typescript\n// 1. Declaration merging — only interface\ninterface Window {\n myCustomProp: string; // merges with global Window\n}\n\n// 2. Union — only type\ntype Input = string | number; // interface can't do this\n\n// 3. Computed properties — only type\ntype Keys = \"x\" | \"y\";\ntype Point = { [K in Keys]: number }; // { x: number; y: number }\n```\n\n## Rule of Thumb\n\n> - Use **`interface`** for public APIs,"
|
||
},
|
||
{
|
||
"id": "regex-bug",
|
||
"output": "# The Problem with `/^[a-z]+$/` and Non-ASCII Lowercase Letters\n\n## The Issue\n\nThe regex `/^[a-z]+$/` **only matches ASCII lowercase letters** (a through z). It will **fail** to match non-ASCII lowercase letters like `é`, `ñ`, `ü`, `ø`, etc.\n\n```javascript\nconst regex = /^[a-z]+$/;\n\nconsole.log(regex.test('hello')); // ✅ true\nconsole.log(regex.test('café')); // ❌ false (because of 'é')\nconsole.log(regex.test('naïve')); // ❌ false (because of 'ï')\n```\n\n## Why?\n\nThe character class `[a-z]` is a **range based on character codes** (97–122 in Unicode/ASCII). It only covers the 26 basic Latin lowercase letters. Characters like `é` (U+00E9) fall outside this range.\n\n## Solutions\n\n### 1. Use Unicode Property Escapes (Recommended, Modern JS)\n\n```javascript\nconst regex = /^\\p{Lowercase_Letter}+$/u;\n\nconsole.log(regex.test('hello')); // ✅ true\nconsole.log(regex.test('café')); // ✅ true\nconsole.log(regex.test('naïve')); // ✅ true\nconsole.log(regex.test('Hello')); // ❌ false\n```\n\n> The `u` flag enables Unicode mode, and `\\p{Lowercase_Letter}` matches **any** Unicode lowercase letter.\n\n### 2. Alternative Unicode Property Shorthand\n\n```javascript\nconst regex = /^\\p{Ll}+$/u; // 'Ll' = \"Letter, lowercase\"\n\nconsole.log(regex.test('café')); // ✅ true\nconsole.log(regex.test('über')); // ✅ true\n```\n\n### 3. Case-Insensitive Workaround (Less Precise)\n\n```javascript\nconst regex = /^\\p{Letter}+$/u;\n\n// Then check if the string equals its lowercase form\nfunction isAllLowercase(str) {\n return /^\\p{Letter}+$/u.test(str) && str === str.toLowerCase();\n}\n```\n\n## Key Takeaway\n\n| Regex | Matches `é`? | Matches `ñ`? | Unicode-aware? |\n|-------|:-----------:|:-----------:|:--------------:|\n| `/^[a-z]+$/"
|
||
},
|
||
{
|
||
"id": "async-race",
|
||
"output": "# Sequential `await` vs `Promise.all`\n\nThe key difference is **concurrency** — how the promises execute in relation to each other.\n\n## Sequential `await`\n\n```javascript\nasync function sequential() {\n const a = await fetchUser(); // Starts and waits (e.g., 2s)\n const b = await fetchOrders(); // Starts AFTER a finishes (e.g., 2s)\n // Total time: ~4s\n}\n```\n\n- The second promise **doesn't start until the first resolves**\n- Total time = sum of both durations\n\n## `Promise.all`\n\n```javascript\nasync function parallel() {\n const [a, b] = await Promise.all([\n fetchUser(), // Starts immediately (e.g., 2s)\n fetchOrders() // Starts immediately (e.g., 2s)\n ]);\n // Total time: ~2s\n}\n```\n\n- Both promises start **at the same time**\n- Total time = duration of the **slowest** one\n\n## Visual Timeline\n\n```\nSequential:\n fetchUser: |████████|\n fetchOrders: |████████|\n Total: |================| ~4s\n\nPromise.all:\n fetchUser: |████████|\n fetchOrders: |████████|\n Total: |========| ~2s\n```\n\n## Error Handling Differences\n\n| Behavior | Sequential `await` | `Promise.all` |\n|---|---|---|\n| **First fails** | Stops immediately, second never runs | Both were started; rejects with first error |\n| **Second fails** | Only happens if first succeeded | Rejects as soon as *any* promise rejects |\n| **Both fail** | Only first error is thrown | First rejection is thrown; second is potentially an unhandled rejection |\n\n```javascript\n// Promise.all — fails fast\ntry {\n const [a, b] = await Promise.all([slow(), fast()]);\n} catch (e) {\n // If fast() rejects first, you get that error immediately\n // slow() is still running but its result is ignored\n}\n```\n\n## When to Use Which\n\n- **`Promise.all`** — when the promises are **independent** (e.g., fetching unrelated data)\n- **Sequential** — when the second depends on the first's result:\n\n```javascript\nconst user = await fetchUser(id);\nconst orders = await fetchOrders(user.accountId); // needs user first\n```\n\n## Bonus: `Promise.allSettled`"
|
||
},
|
||
{
|
||
"id": "go-slice-append",
|
||
"output": "# Why `append` Can Unexpectedly Modify Other Slices in Go\n\nThis is one of Go's most common gotchas, and it stems from how slices work internally.\n\n## Slice Internals\n\nA slice is a **three-field struct** (a \"slice header\"):\n\n```go\ntype slice struct {\n array unsafe.Pointer // pointer to underlying array\n len int\n cap int\n}\n```\n\nWhen you create a sub-slice, the new slice **shares the same underlying array**:\n\n```go\noriginal := make([]int, 5, 10) // len=5, cap=10\nsub := original[1:3] // len=2, cap=9 — same backing array!\n```\n\n## The Problem\n\n`append` has two behaviors depending on capacity:\n\n1. **If `len < cap`**: writes into the existing array (no allocation)\n2. **If `len == cap`**: allocates a new, larger array (safe)\n\n**Case 1 is where the bug hides:**\n\n```go\na := make([]int, 3, 5) // [0, 0, 0], cap=5\na[0], a[1], a[2] = 1, 2, 3\n\nb := a[:2] // [1, 2], cap=5 — shares same array\n\n// b has len=2, cap=5, so there's room — no new allocation!\nb = append(b, 99)\n\nfmt.Println(b) // [1 2 99]\nfmt.Println(a) // [1 2 99] ← a[2] was silently overwritten!\n```\n\n### What happened:\n\n```\nUnderlying array: [1, 2, 3, 0, 0]\n ^\n append wrote 99 here (index 2)\n \nBoth 'a' and 'b' point to this same array,\nso a[2] changed from 3 to 99.\n```\n\n## A More Realistic Example\n\nThis commonly occurs when building results from a shared prefix:\n\n```go\npath := []string{\"home\", \"user\"}\n\n// Two different paths branching from the same prefix\npathA := append(path, \"documents\")\npathB := append(path, \"pictures\") // Overwrites \"documents\"!\n\nfmt.Println(pathA) // [home user pictures] ← WRONG!\nfmt.Println(pathB) // [home user pictures]\n```\n\nBoth `append` calls wrote to `path["
|
||
},
|
||
{
|
||
"id": "rust-lifetime",
|
||
"output": "# Why Rust Requires Explicit Lifetimes on Returned References\n\nWhen a function returns a reference, the compiler needs to know **how long that reference is valid**. Without a lifetime annotation, the compiler can't determine which input the returned reference is tied to, making it impossible to guarantee memory safety.\n\n## The Problem\n\n```rust\n// ❌ This won't compile\nfn longest(x: &str, y: &str) -> &str {\n if x.len() > y.len() { x } else { y }\n}\n```\n\nThe compiler asks: *\"Does the returned reference live as long as `x`, as long as `y`, or something else?\"* It can't figure this out on its own because the choice depends on **runtime logic**.\n\n## The Fix\n\n```rust\n// ✅ Explicit lifetime tells the compiler the relationship\nfn longest<'a>(x: &'a str, y: &'a str) -> &'a str {\n if x.len() > y.len() { x } else { y }\n}\n```\n\nThis says: \"The returned reference will be valid for at least as long as **both** `x` and `y` are valid\" (i.e., `'a` is the shorter of the two lifetimes).\n\n## Why the Compiler Can't Just Guess\n\nThe compiler analyzes functions **independently** — it doesn't look at how a function is called to determine lifetimes. It needs the signature alone to enforce safety at every call site:\n\n```rust\nfn main() {\n let string1 = String::from(\"hello\");\n let result;\n {\n let string2 = String::from(\"world\");\n result = longest(&string1, &string2);\n }\n // ❌ Compiler catches this: string2 is dropped, but result might point to it\n println!(\"{}\", result);\n}\n```\n\nWithout the lifetime annotation, the compiler couldn't reject this code.\n\n## When You *Don't* Need Explicit Lifetimes\n\nRust has **lifetime elision rules** that let you omit lifetimes in unambiguous cases:\n\n```rust\n// ✅ Only one input reference, so the output obviously borrows from it\nfn first_word(s: &str) -> &str {\n // compiler infers: fn first_word<'a>(s: &'a str) -> &'a str\n &s[..s.find(' ').unwrap_or(s.len())]\n}\n\n// ✅ &self methods — output lifetime is assumed to match &self\nimpl MyStruct {"
|
||
},
|
||
{
|
||
"id": "python-gil",
|
||
"output": "# The Python GIL and Concurrency\n\n**No, the GIL does not prevent all concurrency.** It's a common misconception. Here's the nuanced picture:\n\n## What the GIL Does\n\nThe **Global Interpreter Lock** (in CPython) ensures that only **one thread executes Python bytecode at a time**. This limits **CPU-bound parallelism** with threads.\n\n```python\n# CPU-bound work — GIL limits this to ~1 core with threads\nimport threading\n\ndef count():\n total = 0\n for _ in range(10_000_000):\n total += 1\n\n# These run essentially sequentially due to the GIL\nt1 = threading.Thread(target=count)\nt2 = threading.Thread(target=count)\n```\n\n## What the GIL Does NOT Prevent\n\n### 1. **I/O-bound concurrency with threads** ✅\nThe GIL is **released during I/O operations** (network, disk, sleep):\n\n```python\nimport threading, requests\n\n# These actually run concurrently — GIL is released during I/O\nurls = [\"https://example.com\"] * 10\nthreads = [threading.Thread(target=requests.get, args=(url,)) for url in urls]\n```\n\n### 2. **Multiprocessing** ✅\nEach process has its **own GIL**, so true parallelism is possible:\n\n```python\nfrom multiprocessing import Pool\n\ndef cpu_heavy(n):\n return sum(range(n))\n\nwith Pool(4) as p:\n results = p.map(cpu_heavy, [10**7] * 4) # Uses 4 cores\n```\n\n### 3. **Async I/O** ✅\nCooperative concurrency within a single thread:\n\n```python\nimport asyncio, aiohttp\n\nasync def fetch(session, url):\n async with session.get(url) as resp:\n return await resp.text()\n\nasync def main():\n async with aiohttp.ClientSession() as session:\n tasks = [fetch(session, \"https://example.com\") for _ in range(10)]\n await asyncio.gather(*tasks) # Concurrent I/O\n```\n\n### 4. **C extensions that release the GIL** ✅\nLibraries like **NumPy**, **pandas**, and **scikit-learn** release the GIL during heavy computation:\n\n```python\nimport numpy as np\nfrom threading import Thread\n\n# NumPy releases the GIL — true parallel execution"
|
||
},
|
||
{
|
||
"id": "react-key",
|
||
"output": "# Why React Requires Unique `key` Props in Lists\n\n## The Short Answer\n\nReact uses `key` props to **identify which items in a list have changed, been added, or been removed**. Keys help React's **reconciliation algorithm** (diffing) efficiently update the DOM.\n\n## The Problem Without Keys\n\nWhen React re-renders a list, it needs to match elements between the old and new virtual DOM trees. Without keys, React compares elements **by index position**:\n\n```jsx\n// ❌ Without keys — React uses index by default\n// Before:\n<ul>\n <li>Apple</li>\n <li>Banana</li>\n</ul>\n\n// After (inserting \"Cherry\" at the top):\n<ul>\n <li>Cherry</li> // React thinks \"Apple\" mutated into \"Cherry\"\n <li>Apple</li> // React thinks \"Banana\" mutated into \"Apple\"\n <li>Banana</li> // React sees a new element — creates it\n</ul>\n```\n\nReact ends up **re-rendering every item** instead of just inserting one — this is inefficient and can cause **bugs with component state**.\n\n## How Keys Fix This\n\n```jsx\n// ✅ With keys — React tracks each item by identity\n// Before:\n<ul>\n <li key=\"apple\">Apple</li>\n <li key=\"banana\">Banana</li>\n</ul>\n\n// After:\n<ul>\n <li key=\"cherry\">Cherry</li> // React knows this is NEW\n <li key=\"apple\">Apple</li> // React knows this MOVED\n <li key=\"banana\">Banana</li> // React knows this MOVED\n</ul>\n```\n\nReact now correctly **inserts** one element and **moves** the others — no unnecessary re-renders.\n\n## Key Rules\n\n| ✅ Do | ❌ Don't |\n|-------|----------|\n| Use stable, unique IDs (`item.id`) | Use array index as key (if list reorders) |\n| Keep keys consistent across renders | Use `Math.random()` or `Date.now()` |\n| Keys must be unique among **siblings** | Keys don't need to be globally unique |\n\n## Common Example\n\n```jsx\nconst TodoList = ({ todos }) => (\n <ul>\n {todos.map((todo) => (\n // ✅ Use a stable unique identifier\n <li key={todo.id}>{todo.text}</li>\n ))}\n </ul>\n);\n```\n\n## When Index"
|
||
}
|
||
] |