{"id":15662658,"url":"https://github.com/zkat/proposal-collection-literals","last_synced_at":"2025-04-23T21:42:53.998Z","repository":{"id":65998202,"uuid":"127965644","full_name":"zkat/proposal-collection-literals","owner":"zkat","description":"[WITHDRAWN] tc39 proposal for custom collection literals","archived":false,"fork":false,"pushed_at":"2018-05-25T16:14:37.000Z","size":4,"stargazers_count":18,"open_issues_count":1,"forks_count":2,"subscribers_count":9,"default_branch":"latest","last_synced_at":"2025-03-30T03:43:40.807Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/zkat.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-04-03T20:34:27.000Z","updated_at":"2024-03-04T12:14:57.000Z","dependencies_parsed_at":"2023-03-13T20:31:24.025Z","dependency_job_id":null,"html_url":"https://github.com/zkat/proposal-collection-literals","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zkat%2Fproposal-collection-literals","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zkat%2Fproposal-collection-literals/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zkat%2Fproposal-collection-literals/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zkat%2Fproposal-collection-literals/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/zkat","download_url":"https://codeload.github.com/zkat/proposal-collection-literals/tar.gz/refs/heads/latest","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250522264,"owners_count":21444508,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-03T13:33:50.897Z","updated_at":"2025-04-23T21:42:53.978Z","avatar_url":"https://github.com/zkat.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"# ECMAScript Tagged Collection Literals\n\n## [Status](https://tc39.github.io/process-document/)\n\n**Stage**: **WITHDRAWN**\n\n**Author**: Kat Marchán (npm, [@maybekatz](https://twitter.com/maybekatz))\n\n**Champions**: Kat Marchán (npm, [@maybekatz](https://twitter.com/maybekatz))\n\n## WITHDRAWN\n\nThis proposal was presented to TC39 in May 2018 and voluntarily withdrawn during\ndiscussions. The author concluded this issue was best solved through an\nobject-destructuring protocol corresponding to sequence iterators, in\ncombination with `Map.from()` and company.\n\nJavaScript, unlike a lot of the static languages pattern matching concepts were\nbased on, does not include enough static typing information to make things like\ndestructuring or pattern matching efficient and cacheable enough to work well in\nthese cases and stay performant. Additionally, this additional syntax did not\nadd enough value to be worth the syntax budget expenditure.\n\nA different proposal will be submitted based on this one that talks about\ncreation/extraction protocols in a unified way, but without adding additional\nsyntax.\n\n## Introduction\n\nThis proposal extends both destructuring binding/assignment and the [`match`\nstatement](https://github.com/tc39/proposal-pattern-matching) with the ability\nto apply custom destructuring and matching operations to matched data. It also\nadds a new constructor syntax for building these custom data structures with\nconcise object and array style syntax while preserving their individual benefits\nand invariants.\n\nThe syntax itself is derived from similar syntax in multiple other languages\nused for this purpose, and is meant to be reminiscent of tagged template\nliterals in JavaScript -- except using other literal syntaxes available in the\nlanguage.\n\nThis proposal is derived from a previously-discussed [extensible collection\nliterals](https://github.com/alex-weej/es-extensible-collection-literal), but\nadds significant work as far as how this syntax interacts with destructuring and\nmatching.\n\n## Motivating Examples\n\nConvenient construction of object-like and array-like data structures:\n```js\nconst map = Map!{1: 2, three: 4, [[5]]: 6, 1: 'again'}\n// Map { 1 =\u003e 'again', 'three' =\u003e 4, [5] =\u003e 6 }\n\nconst set = Set![1,2,3,2]\n// Set [1, 2, 3]\n\nconst opt = Some!1\n// Some { value: 1 }\n```\n\nDestructuring assignment/binding:\n```js\nconst Map!{1: x, three: y} = map\nx // 2\ny // 4\n\nconst Set![x,y] = set\nx // 1\ny // 2\n\nconst Some!x = opt\nx // 1\n```\n\nMatch statement compatibility:\n```js\nmatch (input) {\n  when Map!{1: x, 2: y} ~\u003e ...\n  when /(?\u003cyear\u003e\\d{4})-(?\u003cmonth\u003e\\d{2})/u!{groups: {year, month}} ~\u003e {\n    console.log(`The year is ${year}, and the month is ${month}`)\n  },\n  when Some!1 ~\u003e `option succeeded with an internal value of 1`\n  when Some!x ~\u003e `option succeeded with a non-1 value of ${x}`,\n  when None!{} ~\u003e `option failed`\n}\n```\n\n## The Big Picture\n\n### Related Active Proposals\n\n* [Pattern matching](https://github.com/tc39/proposal-pattern-matching)\n* [Frozen/sealed object syntax](https://github.com/keithamus/object-freeze-seal-syntax)\n* [Richer Keys](https://docs.google.com/presentation/d/1q3CGeXqskL1gHTATH_VE9Dhj0VGTIAOzJ1cR0dYqDBk/edit#slide=id.p)\n* [`Object.fromEntries`](https://github.com/bakkot/object-from-entries)\n* [Smart Pipelines](https://github.com/js-choi/proposal-smart-pipelines/blob/master/readme.md)\n* [`of` and `from` constructors](https://github.com/tc39/proposal-setmap-offrom)\n\n## Construction Literals\n\nFor construction, literals are a thin layer of syntax sugar over\n`Constructor.from()` functions. When a literal construction expression is found,\nthe left hand side is evaluated for its value, and the right hand side is\nconverted to an iterator or an atomic value. The type of value passed to\n`.from()` depends on which of the three syntaxes is used:\n\n```js\n// Tagged Object Literals\nMap!{foo: 1, 'foo': 1, [Symbol('bar')]: 2, 3: 4, [{}]: 5}\n=== Map.from({[Symbol.iterator]: function* () {\n  // IdentifierName interpreted as string\n  yield ['foo', 1]\n  // StringLiteral PropertyNames\n  yield ['foo', 1]\n  // Symbols preserved\n  yield [Symbol('bar'), 2]\n  // Numeric literals do not get ToString\n  yield [3, 4]\n  // Other kinds of computer property also do not get ToString\n  yield [{}, 5]\n}}\n\n// Tagged Array Literals\nSet![1,2,3]\n=== Set.from({[Symbol.iterator]: function* () {\n  // Nothing special here, except the argument is not an Array\n  yield 1; yield 2; yield 3\n}})\n\n// Tagged Value Literals\nSome!1\n=== Some.from(1)\n```\n\n### Benefits\n\nFor Objects, the benefits are more obvious: No conversion to `ToString`,\nparse-time early errors for invalid key/value syntax, and more appropriate\nsyntax for key/value types, instead of having to write nested arrays.\n\nFor Arrays and Values, the benefit on this end of things is smaller, and largely\nbased on convenience, with the exception that it does help ease a common footgun\nwith `new`:\n\n```js\nclass Bar { constructor (iter) { this.val = [...iter] } }\nfunction foo () { return {Bar} }\nfoo.Bar = Bar\nnew foo().Bar()\n// TypeError: Class constructor Bar cannot be invoked without `new`\nnew foo.Bar()\n// =\u003e Bar {}\n```\n\nWhile this behavior is consistent, it is something that does occasionally bite\npeople. Literal syntax helps ease this a bit, specially in data structure-heavy\ncode:\n\n```js\nfoo().Bar![1,2,3]\n// Bar { val: [1,2,3] }\nfoo.Bar![1,2,3]\n// Bar { val: [1,2,3] }\n```\n\nBut, as implied before, the main benefit of extending tagged literal syntax to\narrays and individual values is the correspondence to destructuring...\n\n## Destructuring Literals\n\nWhen a user learns they can construct with one syntax, is becomes much easier to\nteach them how to destruct with it.\n\nWhile the common `.from()` method mechanism is what makes construction literals\nwork, destructuring uses the standard iterator protocol through a\n`Symbol.valueOf` constructor method. If `Symbol.valueOf` is not present,\n`.valueOf()` is tried instead. If array or object-destructurng syntax is used\nwithout RestProperty/RestElement, `.valueOf()` will receive an array of keys\nthat are being requested from the object. If an atomic destructure is requested,\nthe second argument to `valueOf()` will be `undefined`. Filtering entries based\non these keys is optional.\n\nThe `valueOf` method should return an iterator\n\n```js\nconst Map!{1: x, y} = Map!{1: 'x', y: 'y'}\n===\nlet x, y\nfor (let entry of Map.valueOf(Map!{1: 'x', y: 'y'}, [1, 'y'])) {\n  match (entry) {\n    when [1, _x] ~\u003e {\n      x = _x\n    }\n    when ['y', _y] ~\u003e {\n      y = _y\n    }\n  }\n}\n\nconst Set![a, b, c] = Set![1,2,3,4]\n===\nlet [a,b,c] = Array.from(Set.valueOf(Set![1,2,3,4], [0,1,2]))\n\nclass Some { constructor (val) { this._val = val } }\nSome.valueOf = (some) =\u003e some._val\n\nconst Some!x = Some!1\n===\nlet x = Some.valueOf(new Some(1))\n// x === 1\n```\n\nWhen a destructuring sequence is used, the iterator will be used as-is to match\nand fill entries in the destructured array or object.\n\nIf `valueOf` returns `undefined`, the match is considered to have failed, and no\nvalues will match. When used with `match`, this will cause the match clause to\nfail.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzkat%2Fproposal-collection-literals","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fzkat%2Fproposal-collection-literals","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzkat%2Fproposal-collection-literals/lists"}