Skip to content

Commit b911150

Browse files
committed
full example back to front
1 parent 72f42ba commit b911150

1 file changed

Lines changed: 58 additions & 62 deletions

File tree

docs/blog/posts/jac_vs_sota_todo_app.md

Lines changed: 58 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,64 @@ And yet, building with the best-in-class version of every tool still produces ~5
2020

2121
<!-- more -->
2222

23-
Let's walk through the app section by section - Jac first to show the intent, then the SOTA equivalent to show the cost.
23+
## The Complete Jac App
24+
25+
Here's the Jac version. One file, 46 lines:
26+
27+
```jac
28+
node Todo {
29+
has title: str,
30+
category: str = "other",
31+
done: bool = False;
32+
}
33+
34+
enum Category { WORK, PERSONAL, SHOPPING, HEALTH, OTHER }
35+
36+
def categorize(title: str) -> Category by llm();
37+
38+
def:pub add_todo(title: str) -> Todo {
39+
try {
40+
category = str(categorize(title)).split(".")[-1].lower();
41+
} except Exception { }
42+
root() ++> (todo := Todo(title=title, category=category));
43+
return todo;
44+
}
45+
46+
def:pub get_todos -> list[Todo] {
47+
return [root()-->][?:Todo];
48+
}
49+
50+
cl def:pub app -> JsxElement {
51+
has todos: list[Todo] = [],
52+
text: str = "";
53+
54+
async can with entry {
55+
todos = await get_todos();
56+
}
57+
58+
async def add {
59+
if text.strip() {
60+
todo = await add_todo(text.strip());
61+
todos = todos + [todo];
62+
text = "";
63+
}
64+
}
65+
66+
return
67+
<div>
68+
<input
69+
value={text}
70+
onChange={lambda e: ChangeEvent { text = e.target.value;}}
71+
onKeyPress={lambda e: KeyboardEvent { if e.key == "Enter" { add(); }}}
72+
placeholder="Add a todo..."
73+
/>
74+
<button onClick={add}>Add</button>
75+
{[<p key={jid(t)}>{t.title} ({t.category})</p> for t in todos]}
76+
</div>;
77+
}
78+
```
79+
80+
Now let's walk through each section and see what the same intent costs in the SOTA stack.
2481

2582
---
2683

@@ -620,67 +677,6 @@ The 187 extra lines aren't wrong. They're just not doing what you hired them to
620677

621678
---
622679

623-
## The Complete Jac App
624-
625-
You've now seen each piece in context. Here's the whole thing - one file, 46 lines:
626-
627-
```jac
628-
node Todo {
629-
has title: str,
630-
category: str = "other",
631-
done: bool = False;
632-
}
633-
634-
enum Category { WORK, PERSONAL, SHOPPING, HEALTH, OTHER }
635-
636-
def categorize(title: str) -> Category by llm();
637-
638-
def:pub add_todo(title: str) -> Todo {
639-
try {
640-
category = str(categorize(title)).split(".")[-1].lower();
641-
} except Exception { }
642-
root() ++> (todo := Todo(title=title, category=category));
643-
return todo;
644-
}
645-
646-
def:pub get_todos -> list[Todo] {
647-
return [root()-->][?:Todo];
648-
}
649-
650-
cl def:pub app -> JsxElement {
651-
has todos: list[Todo] = [],
652-
text: str = "";
653-
654-
async can with entry {
655-
todos = await get_todos();
656-
}
657-
658-
async def add {
659-
if text.strip() {
660-
todo = await add_todo(text.strip());
661-
todos = todos + [todo];
662-
text = "";
663-
}
664-
}
665-
666-
return
667-
<div>
668-
<input
669-
value={text}
670-
onChange={lambda e: ChangeEvent { text = e.target.value;}}
671-
onKeyPress={lambda e: KeyboardEvent { if e.key == "Enter" { add(); }}}
672-
placeholder="Add a todo..."
673-
/>
674-
<button onClick={add}>Add</button>
675-
{[<p key={jid(t)}>{t.title} ({t.category})</p> for t in todos]}
676-
</div>;
677-
}
678-
```
679-
680-
Data model, AI categorization, API, and full-stack reactive UI. No ORM, no prompt template, no fetch ceremony, no type mirroring. One type system from database to browser to LLM.
681-
682-
---
683-
684680
## Bonus: The Configuration Tax
685681

686682
The scorecard above covers application code only. But the polyglot tax extends to project configuration too - and the ratio there tells its own story.

0 commit comments

Comments
 (0)