Slugify — turn a title into a URL-safe slug
Lowercases, keeps alphanumerics, turns every run of other characters into a single hyphen, and trims leading/trailing hyphens. Demonstrates a per-char accumulator with a "last was separator" flag to collapse runs. Run: soma run slugify.cell --signal slugify "Hello, World! Foo--Bar"
A Soma program from the text part of the verified corpus: 45 lines, cells Slugify, SlugifyTest. It passes soma check with soma 3.2.4.
How it is built
The cell Slugify declares 1 signal in its face: slugify(title: String) -> String. Handlers: slugify (line 16).
The file also holds 1 test cell (SlugifyTest) with 5 assertions, run by soma test.
The source
slugify.cell
// ============================================================================
// Slugify — turn a title into a URL-safe slug
// ============================================================================
//
// Lowercases, keeps alphanumerics, turns every run of other characters into a
// single hyphen, and trims leading/trailing hyphens. Demonstrates a per-char
// accumulator with a "last was separator" flag to collapse runs.
//
// Run: soma run slugify.cell --signal slugify "Hello, World! Foo--Bar"
cell Slugify {
face {
signal slugify(title: String) -> String
}
on slugify(title: String) {
let low = lowercase(title)
let out = ""
let pending_dash = false
for i in range(0, len(low)) {
let c = low[i]
if (c >= "a" && c <= "z") || (c >= "0" && c <= "9") {
if pending_dash && len(out) > 0 {
out = out + "-"
}
pending_dash = false
out = out + c
} else {
pending_dash = true
}
}
return out
}
}
cell test SlugifyTest {
rules {
assert slugify("Hello World") == "hello-world"
assert slugify("Hello, World!") == "hello-world"
assert slugify(" Foo -- Bar ") == "foo-bar"
assert slugify("Already-Slug-99") == "already-slug-99"
assert slugify("!!!") == ""
}
}What the toolchain says
$ soma check slugify.cell
warning: `out` grows by concatenation inside a loop — each step copies the whole value, so the loop is quadratic (8 MB took 32 s, a list + join() 30 ms): push the pieces to a List and `join(parts, "")` once
--> slugify.cell:24:21
|
24 | out = out + "-"
| ^
✓ 1 warning(s), no errors.$ soma test slugify.cell
test SlugifyTest ...
✓ assert slugify("Hello World") == "hello-world"
✓ assert slugify("Hello, World!") == "hello-world"
✓ assert slugify(" Foo -- Bar ") == "foo-bar"
✓ assert slugify("Already-Slug-99") == "already-slug-99"
✓ assert slugify("!!!") == ""
5 tests: 5 passed, 0 failed$ soma verify slugify.cell
Verifying slugify.cell...
No state machine in this program: nothing to prove beyond `soma check` (invariants and lifecycles are what verify proves).
VERIFY OK (vacuous — no state machine)