sprout-garden-phase-6
Sprout Garden Phase 6: Rabbit Holes
Sub-Gardens and Functions - Abstraction through nesting
Overview
Phase 6 introduces rabbit holes - portals to sub-gardens. A sprout enters a rabbit hole, gets processed by an entire nested garden, and emerges transformed. This is functions - the most powerful abstraction in programming.
This phase teaches: Big things are made of smaller things. Name a pattern, reuse it forever.
The Rabbit Hole Concept
Main Garden:
┌─────────────────────────────────────────────┐
│ │
│ 🌱 ──▶ [→] ──▶ [🌀] ──▶ [→] ──▶ 🎯 │
│ │ │
│ │ (zoom in) │
│ ▼ │
│ ┌─────────────────┐ │
│ │ SUB-GARDEN │ │
│ │ 🌱──▶⚙️──▶🎨──▶🎯 │ │
│ └─────────────────┘ │
│ │
└─────────────────────────────────────────────┘Tap the rabbit hole → Opens sub-garden view
Sub-garden completes → Sprout emerges from rabbit hole
It's turtles all the way down → Rabbit holes can contain rabbit holes
Plot Types Introduced
| Plot | Symbol | Category | Behavior |
|---|---|---|---|
| Rabbit Hole | 🌀 | abstraction | Portal to sub-garden |
| Return | ↩️ | abstraction | Exit point in sub-garden |
Rabbit Hole Mechanics
Creating a Rabbit Hole
- Build a useful pattern in main garden
- Select the plots
- "Save as Rabbit Hole" → Give it a name
- Pattern becomes reusable 🌀 plot
Inside the Rabbit Hole
rabbitHole = {
id: 'triple-ripen',
name: 'Triple Ripen',
symbol: '🌀',
icon: '⚙️³', // Custom icon showing what it does
// The sub-garden definition
subGarden: {
size: { width: 5, height: 1 },
plots: {
'A1': { type: 'input' }, // Where sprout enters
'A2': { type: 'form-grower' },
'A3': { type: 'form-grower' },
'A4': { type: 'form-grower' },
'A5': { type: 'return' } // Where sprout exits
}
},
seeds: ['left', 'right', 'up', 'down'],
fruits: ['pass-through'],
// Execute sub-garden on sprout
grow(sprout) {
const subSim = new Simulation(this.subGarden);
subSim.inject(sprout, 'A1');
const result = subSim.run();
return result.sprouts[0]; // Return transformed sprout
}
};Function Library
Saved rabbit holes appear in the toolbox:
┌─────────────────────────────────────────────┐
│ 📁 My Functions │
│ │
│ [🌀 triple-ripen] [🌀 color-cycle] │
│ [🌀 make-star] [🌀 counter-loop] │
│ │
└─────────────────────────────────────────────┘Recursion Warning! 🐇
A rabbit hole CAN contain itself:
rabbitHole "infinite-depth" contains:
🌱 ──▶ ⚙️ ──▶ [🌀 infinite-depth] ──▶ 🎯Visual feedback: Sprout starts spinning, "Too deep!" message appears.
// Max recursion depth
const MAX_DEPTH = 10;
rabbitHole.grow(sprout, depth = 0) {
if (depth > MAX_DEPTH) {
return { ...sprout, status: 'recursion-overflow' };
}
// ... execute with depth + 1
}Source Files (To Be Created)
| File | Purpose |
|---|---|
src/plots/types/rabbit-hole.js |
Sub-garden portal |
src/plots/types/input.js |
Sub-garden entry point |
src/plots/types/return.js |
Sub-garden exit point |
src/core/sub-simulation.js |
Nested simulation runner |
src/storage/functions.js |
Save/load rabbit holes |
API Documentation
files:
- /Users/graemefawcett/working/ben.fawcett.family/activities/sprout-garden/src/plots/types/rabbit-hole.js
- /Users/graemefawcett/working/ben.fawcett.family/activities/sprout-garden/src/plots/types/input.js
- /Users/graemefawcett/working/ben.fawcett.family/activities/sprout-garden/src/plots/types/return.js❌ Fence Execution Error: "'code-api-docs' - Down the rabbit hole we went, but that node doesn't exist! Try 'oculus list' to see what's available."
Implementation Notes
Sub-Garden Serialization
# Stored rabbit hole definition
rabbit-hole:
id: triple-ripen
name: Triple Ripen
icon: ⚙️³
author: Ben
created: 2024-01-15
garden:
size: [5, 1]
plots:
A1: { type: input }
A2: { type: form-grower }
A3: { type: form-grower }
A4: { type: form-grower }
A5: { type: return }UI for Sub-Gardens
// Zoom into rabbit hole
function openSubGarden(rabbitHoleId) {
const hole = getFunctionLibrary().get(rabbitHoleId);
// Push current garden onto stack
gardenStack.push(currentGarden);
// Load sub-garden
currentGarden = hole.subGarden;
renderGarden();
// Show breadcrumb: "Main > triple-ripen"
updateBreadcrumb();
}
// Return from sub-garden
function closeSubGarden() {
currentGarden = gardenStack.pop();
renderGarden();
}Level Ideas
| Level | Challenge | Teaches |
|---|---|---|
| 39 | Use pre-made rabbit hole | Function calling |
| 40 | Edit inside a rabbit hole | Function internals |
| 41 | Create your own rabbit hole | Function definition |
| 42 | Rabbit hole with parameters | Arguments |
| 43 | Chain rabbit holes | Composition |
| 44 | Rabbit hole inside rabbit hole | Nesting |
| 45 | Recursive pattern (with limit) | Recursion concept |
Pedagogy
What Kids Learn (Without Knowing It)
- Functions: Named, reusable patterns
- Abstraction: Hide complexity behind simple interface
- Composition: Building big things from small things
- Recursion: Functions that call themselves (with limits!)
- Libraries: Collections of useful functions
- DRY principle: Don't Repeat Yourself
The Aha Moment
"Wait, I can save this pattern and use it anywhere?"
"And other people can use my rabbit holes too?"
"And I can put rabbit holes INSIDE rabbit holes?!"
That's the moment they understand software engineering.
Verification
Live test results from [[sprout-garden-phase-6-test]]:
| Test | Status | Details |
|---|---|---|
| rabbit-hole.js exists | fail | not yet implemented |
| input.js exists | fail | not yet implemented |
| return.js exists | fail | not yet implemented |
| sub-simulation.js exists | fail | not yet implemented |
| functions.js exists | fail | not yet implemented |
Slots
North
slots:
- sprout-garden
- sprout-gardenSouth
slots:
- sprout-garden-phase-6-testEast
slots:
- sprout-garden-phase-7West
slots:
- sprout-garden-phase-5