Prefer methods over free functions in std and public APIs #146
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
What
Move the standard library and compiler-facing APIs from free functions towards methods where a method is the natural shape (the function operates on one receiver type, e.g.
foo(x: Digest, ...)becomesx.foo(...)).Why
Many free functions exist only because TorbScript syntax grew step by step; method syntax is available now and is the preferred API style (owner direction, 2026-10-06; first applied in #96).
Scope for refine
std/(and anything the compiler looks up by name) and classify: convert to method, keep as free function (no natural receiver, constructors, multi-receiver), or keep as thin wrapper for compatibility.Not in scope
A big-bang rename in one PR.
[loop:torbscript] claim refine by session:loop-torbscript-20261008 until 2026-10-08T09:15:00Z
Bytes(slice of #146) #175MarkdownDocument(slice of #146) #178[loop:torbscript] owner decision: deprecation path for the free functions that get a method (breaking-change policy, not settled in a design record).
Context: #96 already settled that the method is primary and the free function stays as a thin wrapper. Open is what happens to the wrapper afterwards. RELEASE.md section 3 says
stdonly grows within 1.x (removal waits for 2.0; a member is markeddeprecatedwith a replacement andtorb lint --fixmigrates callers); before 1.0 any breaking change needs a migration. DEPRECATION.md builds the mark and the lint fix.Options:
deprecated(replacement: ..., since: ...)in the release after its method ships,torb lint --fixmigrates callers, removal not before 2.0. Warnings, no break within 0.x/1.x.stdwith the lint migration).Also open: ~170
publicfree functions are undocumented helpers (scanner, wire, derive plumbing). Are they API (then they follow the chosen option) or internals to be made non-public in a separate, breaking round?Recommendation: option 2, and treat undocumented helpers as internals handled in their own later issue. It keeps the 1.x promise, uses the machinery that already exists, and needs no break.
Until answered, no slice marks a wrapper
deprecatedor removes anything; slices that only add methods and keep the wrappers are not blocked.[loop:torbscript] refine: inventory at
129f1574: 301publicfree functions instd/(excluding tests), ~85 documented indocs/standard-library/, ~215 undocumented helpers. Classification of the documented ones:std/compression(inflated, deflated, gzipped, gunzipped, crc32 onBytes),std/encoding(hexEncoded onBytes, hexDecoded, base64Decoded onString),std/archive(tarred, extract onList<TarEntry>, untarred onBytes),std/markdown(markdownOf, htmlOf onMarkdownDocument, plainText on inlines),std/uri(formDecoded, formEncoded, percentDecoded), later round:std/streamtextOf,std/dnspresentation/query/readResponse,std/httpsend/get-style helpers takingUri/Headers,std/corecombineHashes.constantTimeEqualis done (#96).std/console(print, printError, isTerminal, ...),std/task(spawn, both, pause, offload),std/timesleep,std/test(test, group),std/io(readLine, standardInput, ...),std/core(panic, do, unless, retry, isSame),std/expression(assert, nameOf),std/iterationfactories (mapping, filtering, taking, ..., all collectors),std/osplatform functions (version, hostName, uptime, directories),std/networkresolve/lookup/systemNameServers,std/encodingstructureOf and the derive plumbing,std/markdownparsedDocument.compiler/src/backend/c/natives.trb,compiler/src/ir/lower/*andcompiler/src/semantics/checker/wellknown.trb:print,printError,isTerminal,sleep,pause,spawn,assert, plus everynative fnofstd/task,std/fs,std/console. The converted slices below touch none of them.publichelpers (uri/characters,yaml/*,markdown/text,dns/wire,http/parse,regex/*,signature/*,os/<platform>): treated as internals, not converted; whether they are API is part of the owner question above.First slices (std only, wrapper kept, no seed touch, no deprecation, one PR each): #175 compression, #176 encoding, #177 archive, #178 markdown (all
ready), #179 uri (queued, notreadybecause the ready buffer is full). Later rounds: stream/dns/http/core after these land.Worker usage: about 95k tokens (sonnet, medium).
next: waiting (owner decision above on the wrapper deprecation path; the epic stays open as tracker, slices #175-#178 do not depend on it)
Question q1 for torben (decision, blocking): What happens to a free-function wrapper after its method ships?
[loop:torbscript] owner decision recorded (torben, 2026-10-08): "Noch niemand nutzt TorbScript, die sollen raus einfach, komplett" (nobody uses TorbScript yet, they should simply go, completely).
Resolution:
deprecatedphase, no kept wrapper, notorb lint --fixmigration rule. Callers inside the repo (std, tests, examples, docs) are migrated in the same PR.publichelpers (~170, scanner, wire, derive plumbing): treated as internals (Orion's call under the same reasoning). They become non-public in their own follow-up slices per module, also without deprecation.Status: decided, no longer waiting. Slices #175 to #179 get the updated scope.
Bytes(slice of #146) #175MarkdownDocument(slice of #146) #178std/cipherwith ChaCha20-Poly1305 (RFC 8439) #264std/http#30std/json-schema(step 1 of #80) #434JsonPointer(RFC 6901) instd/json(step 1 of #81) #435Into<Path>signatures (PATH slice 2) #68std/json-schema:$id,$ref,$defs,$anchorand a registry of supplied documents (step 2a of #80) #553Into<Path>signatures (PATH slice 2) #68std/json-patchwith RFC 6902 JSON Patch and the json-patch-tests suite (step 2 of #81) #581[owner-answer] q=q1 option=remove-before-1 „Deprecate and remove before 1.0“ 2026-10-29T22:53:18Z