Build `c0 + c1·v + c2·v² + …` with canonical construction (no simplify). * Terms with an exactly-zero coefficient are skipped so the fitted expression * reads `x² + 1`, not `x² + 0x + 1`.
( ce: ComputeEngine, coeffs: Expression[], variable: string )
| 1194 | // passes. |
| 1195 | // The LEADING arm is the string-preservation rule: a sample drawn from a |
| 1196 | // string's own characters is a string (`docs/STRING_ROADMAP.md`, "String |
| 1197 | // preservation rule"; promoted in Phase 2 as an ELEMENT-PRESERVING |
| 1198 | // list-out operator). `RandomSample` is eager and has no lazy collection |
| 1199 | // handlers, so the join happens in the `evaluate` handler below. |
| 1200 | // Re-segmentation caveat: rejoining the sampled characters can merge or |
| 1201 | // split grapheme clusters, so the result may hold a different number of |
| 1202 | // characters than `k` — a sampled combining mark attaches to whichever |
| 1203 | // character now precedes it. |
| 1204 | // Spelled as a BOUNDED type variable (`T where T: string`), never the |
| 1205 | // ground type `string`: an `unknown`- or `any`-typed operand refutes no |
| 1206 | // arm, so a ground `string` parameter would win most-specific-wins on |
| 1207 | // every untyped operand and claim `string` for a call that usually |
| 1208 | // returns a list. A bounded variable with no call-site binding does not. |
| 1209 | signature: |
| 1210 | '((T, number) random -> T where T: string) & ((indexed_collection, number) random -> list)', |
| 1211 | // IMPURE producer: decline-only from the source facet — zero draws, |
| 1212 | // never `true` (see `RandomShuffle`/`RandomChoice`). |
| 1213 | canEnumerate: (expr) => { |
| 1214 | if (!isFunction(expr)) return undefined; |
| 1215 | return expr.op1.isEnumerableCollection === false ? false : undefined; |
| 1216 | }, |
| 1217 | evaluate: ([xs, kOp], { engine: ce }) => { |
| 1218 | if (!xs.isIndexedCollection) return undefined; |