You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
docs: expand convert-to-marimo skill with function extraction guidance
Add detailed guidance on:
- Naming functions to document intent (replacing comments)
- Decomposing monolithic functions by stage
- Splitting large cells so intermediate results are visible
- Extracting reusable helpers into their own cells
- Parameterizing functions to avoid globals
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Copy file name to clipboardExpand all lines: .claude/skills/convert-to-marimo/SKILL.md
+126-8Lines changed: 126 additions & 8 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -231,6 +231,131 @@ Results update when the user changes either input.
231
231
232
232
## Phase 6: Code Quality
233
233
234
+
### Name things to document intent
235
+
236
+
Well-named functions and variables replace comments. If you find yourself writing a comment to explain what a block of code does, that is a signal to extract it into a named function instead.
237
+
238
+
**Before:**
239
+
```python
240
+
# Filter sentences containing our keyword and build records for Pinecone
241
+
results = []
242
+
for i, row inenumerate(dataset.filter(lambdax: any(k in x["text"] for k in keywords))):
The second version reads like a description of what is happening. The function names are the documentation.
262
+
263
+
### Decompose monolithic functions by stage
264
+
265
+
Jupyter notebooks often have one large function that loads, filters, transforms, and formats data all at once. Split it along its natural stages — each stage becomes a function with a clear name and a clear input/output contract.
266
+
267
+
**Identify stages by asking:** at what points does the data change shape or purpose?
268
+
269
+
Example decomposition:
270
+
```
271
+
prepare_sentences(dataset, keywords) → one big function doing everything
to_records(sentences, column) → returns list of Pinecone record dicts
278
+
```
279
+
280
+
Each stage can be shown, inspected, and explained independently. Each can be reused or replaced without touching the others.
281
+
282
+
### Split large cells to make intermediate results visible
283
+
284
+
Marimo cells produce output. A single cell that does five things produces one output — or none. Splitting at stage boundaries lets each step show its result, which helps readers understand what changed and why.
285
+
286
+
**Rule of thumb:** if a cell produces a value worth seeing (a filtered dataset, a record list, a search result), that value should be the last expression in its own cell.
287
+
288
+
```python
289
+
# Too much in one cell — intermediate state invisible
If a function is called more than once, or could reasonably be called with different arguments, give it its own cell. Readers can read the definition once, then see it used cleanly at each call site.
317
+
318
+
The search notebook pattern is a good model:
319
+
320
+
```python
321
+
# One cell defines the helper
322
+
defsearch(query, top_k=10, lang=None):
323
+
results = index.search(
324
+
namespace=namespace,
325
+
top_k=top_k,
326
+
inputs={"text": query},
327
+
filter={"lang": {"$eq": lang}} if lang elseNone,
328
+
)
329
+
return print_results(query, results)
330
+
331
+
# Subsequent cells are just clean call sites
332
+
search("I want to go to the park and relax")
333
+
search("Quiero ir al parque a relajarme")
334
+
search("The park is crowded today", lang="en")
335
+
```
336
+
337
+
### Parameterize functions — avoid globals
338
+
339
+
Converted notebooks often have functions that silently close over global variables (`keywords`, `index`, `namespace`). This makes the function hard to reuse and hides dependencies.
340
+
341
+
**Before (globals):**
342
+
```python
343
+
keywords = ["park"]
344
+
345
+
defprepare_sentences(dataset):
346
+
return dataset.filter(lambdax: any(k in x["translation"]["en"] for k in keywords))
347
+
```
348
+
349
+
**After (explicit parameter):**
350
+
```python
351
+
defprepare_sentences(dataset, keywords=None):
352
+
if keywords:
353
+
return dataset.filter(lambdax: any(k in x["translation"]["en"] for k in keywords))
354
+
return dataset
355
+
```
356
+
357
+
The exception: functions that close over `index` and `namespace` in a "search" helper are reasonable — they're scoped to the notebook, and the closure reads naturally.
358
+
234
359
### Remove over-explaining comments
235
360
236
361
Only comment on the non-obvious WHY — not on what the code does. Delete comments like:
@@ -239,14 +364,7 @@ Only comment on the non-obvious WHY — not on what the code does. Delete commen
239
364
-`# flatten and shuffle for ease of use`
240
365
-`# Here, we create a record for each sentence in the dataset`
241
366
242
-
Keep comments that explain constraints, workarounds, or non-obvious choices.
243
-
244
-
### Decompose monolithic functions
245
-
246
-
If the converted notebook has a large function doing multiple things, split it:
247
-
- Separate filtering from reshaping from formatting
248
-
- Name each function after its single responsibility
249
-
- Parameterize functions properly — avoid globals captured by closures
367
+
Keep comments that explain constraints, workarounds, or non-obvious choices — especially when a behaviour might surprise a reader (e.g. why a version is pinned, why a parameter is omitted).
0 commit comments