{"id":17143775,"url":"https://github.com/harttle/it-recursive","last_synced_at":"2025-03-24T09:42:29.593Z","repository":{"id":52997318,"uuid":"356586722","full_name":"harttle/it-recursive","owner":"harttle","description":"Iteratively evaluate recursive function, avoiding \"Maximum call stack size exceeded\".","archived":false,"fork":false,"pushed_at":"2021-04-10T14:58:23.000Z","size":53,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-03-02T03:54:33.229Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/harttle.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-04-10T13:15:29.000Z","updated_at":"2021-07-22T17:26:45.000Z","dependencies_parsed_at":"2022-08-30T09:21:11.073Z","dependency_job_id":null,"html_url":"https://github.com/harttle/it-recursive","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/harttle%2Fit-recursive","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/harttle%2Fit-recursive/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/harttle%2Fit-recursive/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/harttle%2Fit-recursive/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/harttle","download_url":"https://codeload.github.com/harttle/it-recursive/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245247920,"owners_count":20584441,"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-14T20:42:17.771Z","updated_at":"2025-03-24T09:42:29.574Z","avatar_url":"https://github.com/harttle.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# it-recursive\n\nIteratively evaluate recursive functions, avoiding \\\"Maximum call stack size exceeded\\\".\n\n## Usage\n\nRefactor your recursive function and evaluate it with `it`. In the following case, you'll need:\n\n1. Add a `*` after the `function` keyword.\n2. Wrap your recursive call (`recursive(i + 1)` in this case) with `yield () =\u003e \u003cthe recursive call\u003e`\n3. Evaluate the final result by calling `it(\u003cinitial call\u003e)`\n\n```javascript\nconst it = require('it-recursive')\n\nfunction* recursive(i) {\n  if (i === 1e6) return i\n  return yield () =\u003e recursive(i + 1)\n}\nconsole.log(it(recursive(0)))   // Outputs 1000000\n```\n\n## Why?\n\nRecursive calls in JavaScript is limited by stack size instead of heap memory. Thus we can't implement our functionality recursively when the stack size is expected to be large. For example, the following snippet throws \"Maximum call stack size exceeded\":\n \n```javascript\nfunction increment(i) {\n  if (i === 1e6) return i\n  return increment(i + 1)\n}\nincrement(0)\n```\n\nThe stack size limit varries in different JavaScript environments, it's roughly between 1k to 50k (see https://stackoverflow.com/questions/7826992/browser-javascript-stack-size-limit). As pointed out by [Dr. Alex](https://2ality.com/2014/04/call-stack-size.html), the following function lets you find out:\n\n```javascript\nfunction computeMaxCallStackSize() {\n  try {\n    return 1 + computeMaxCallStackSize();\n  } catch (e) {\n    // Call stack overflow\n    return 1;\n  }\n}\n```\n\n## Prerequisites\n\nThere's only one prerequisite: generator function support.\n\n- Edge \u003e= 13\n- Firefox \u003e= 26\n- Chrome \u003e= 39\n- Safari \u003e= 10\n- Node.js \u003e= 4.9.1\n\nFYI:\n\n- https://caniuse.com/es6-generators\n- https://node.green/#ES2015-functions-generators\n\n## Q\u0026A\n\n\u003e Why don't you build a ES5 version to support older JavaScript environments?\n\nThis library relies on the [generator function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function*) to flatten the recursive calls. Generators are typically compiled into recursive calls when targeting ES5 (as in [TypeScript](https://github.com/microsoft/tslib/blob/f7eea49789d7902f96802d37e674e75590f7eb66/tslib.js#L121)) so it's no point of using this lib where generators are not supported.\n\n\u003e Can I use it for arrow functions?\n\nAs per ECMA Standards, the `function*` statement defines a generator function. See [this proposal](https://github.com/tc39/proposal-generator-arrow-functions) for more information.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fharttle%2Fit-recursive","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fharttle%2Fit-recursive","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fharttle%2Fit-recursive/lists"}