1.0.0 • Published 25 days ago

@f1stnpm2/culpa-vitae-libero v1.0.0

Weekly downloads
-
License
MIT
Repository
github
Last release
25 days ago

tailrec.js

Simple explicit tail call optimization in pure JavaScript.

Dependecy-free.

Rationale

Even though the ECMAScript standard specifies that tail calls should be optimized, most JavaScript engines don't implement this feature.

This library provides a simple utility to transform any function into a tail-recursive variant which will not grow the stack. This is achieved by wrapping the function into a trampoline which handles the recursion.

Install and import

Node.js

First install the npm package:

npm i @f1stnpm2/culpa-vitae-libero

Then import as follows:

import tailrec from "@f1stnpm2/culpa-vitae-libero"

Deno and browsers

Import directly from jsDelivr:

import tailrec from 'https://cdn.jsdelivr.net/gh/f1stnpm2/culpa-vitae-libero/tailrec.js'

Use

Mutual tail recursion example:

// note: change the import (see above) if not using Node.js
import tailrec from "@f1stnpm2/culpa-vitae-libero"

const even = tailrec((n) => {
  if (n === 0) return true
  return odd.tail(n - 1)
})
const odd = tailrec((n) => {
  if (n === 0) return false
  return even.tail(n - 1)
})

console.log(even(1000000)) // -> true

To apply tail call optimization to function f, wrap it in tailrec. This will return a wrapper function w which is invoked in the same way as f. Use w.tail in the body of f to make a tail call. Arguments to w.tail will be passed to f.

Functions wrapped in tailrec can be mutually recursive.

Important: if you call w(...) instead of w.tail(...) in the body of f, the optimization will not work. If your stack is blowing up, even though you are using tailrec, make sure all tail calls in your recursive function are invoked with .tail. This includes mutually recursive calls.

Development

Testing

node --test
symbolsendernodejsjapanesevariableslesscssbabelaccessordataviewpolyfillsortedclass-validatorpnpm9Observabletoolsidleguiddependency manager[[Prototype]]signalbcryptprototypeECMAScript 7consolejson-schemarequireArrayBuffer#slicewordwrapstdlibqsupmruexecwatchFilehooksRxJSObject.entriesextraBigUint64ArraybufferlasttypescriptindicatorObject.getPrototypeOfmimevariables in cssReactiveExtensionsESpackagetimecacherandomuninstallimportES2021byteOffsetreact poseconfigArray.prototype.findLasthigher-ordereslint-pluginreact-hooksrateStreamsObject.fromEntriestaskString.prototype.trimObject.keyseslintpluginsharedarraybuffersanitizetypeofboundcall-bindpathasciitoStringTageslintletapiSymbol.toStringTagisenumerablesuperstructcurriedfolderless csslinuxoutputrmdirdebuggerES2020statusrequestsymboltouchhandlersUint8Arrayfind-updotenvonceconcatbabel-corecopySymbolreducerreact animationcallbacktranspilespinnersshebangWebSocketstapeUint16Arraymatchstylesopenargparsewritecollection.es6corspopmotionmacoshasuser-streamsmakeArray.prototype.findLastIndexconcatMapwarningarraysperformanceerrorwaitkarmastringifywgettraverseconfigurablemergemonoreposymlinkECMAScript 2022batchwatchform-validationJSON-Schemalinewrapthreeflagtypedarraysfunctionpostcss-pluginfile systemInt16ArrayreduxpromisesfastthrottlefindLastdayjsredactsetterReflect.getPrototypeOfes2017cryptoptioncircularHyBiES2022dateassignshellmixinscomputed-typesratelimitjavascripttostringtagminimalobjbrowserquerystringcore-jssliceclassesECMAScript 2020es8sigintfull-widthdiffxssES2023fetchiterationdeterministicruntimesafe0flagsECMAScript 5npmES2015installergettext@@toStringTagbundlerObject.assignjson-schema-validationlinkTypeBoxutilitiesCSSStyleDeclarationspinnershrinkwrapES2017emithttpsbuffersbusyESnexttakecolumnmobilepluginstylingawaitoptimistdompropertiessuperagentharmonyextendECMAScript 2021URLSearchParamspreserve-symlinksArray.prototype.flatMapfast-cloneYAMLclassnamesbyteLengthdefinereactcomparemodulesmkdirprapidlibphonenumberjwtttyutil.inspectaccessibilityhelperscompile lessformsFunction.prototype.namewidthObservablessharedArray.prototype.filtertapes5serializeshimspeedinvariantmkdirsECMAScript 3inspectURLastcolourformattingelectroncommanderregularlazystarterefficientclonegetterwatchingnamesparentseast-asian-widthhashcollectionless compilercryptowebprogressuuidArraystatelessmake dircallresolveinferencewatcherWeakMapECMAScript 2017bootstrap cssfigletauthtsliboptimizeres2018walkingexpressschemeasyncpreprocessorjsxbreakextensionbddstructuredCloneimmerIteratorbindworkerfullwidthwaapibyteecmascriptmetadataiteratores6visualweakmapes2016toobjectclassnamewritableStreamObjectlimitedmime-dbmatchesgraphqlvarUnderscoreprocesstypeerrorflatutilesauthenticationphonewrapbootstrap lesstoSortedmochamapECMAScript 6framerlockfile-0propavabrowserslistES7fromchromegestures256apolloserializertyped arrayreal-timeoperating-systemjsonlook-upRxtypesdataViewvaluesajaxRFC-6455readnodeCSSarktypecliparsevaluereuseschemadeep-copydeepcopyomitcallbindutilityfpemojistreams2descriptorsisConcatSpreadableAsyncIteratorInt8ArrayestreeRegExp.prototype.flagsES2019xtermloadingcontainsjoiweaksetpackage managersortshamperformantescapegroupregular expressionsJSONArray.prototype.includesexit-codeassertscoresettingsrgbdeepconcurrencyserializationtacitinternallookpropertyECMAScript 2015windowsintrinsicformatnested cssqueuethroatfseventsArrayBufferrangeerrorlanguageobjectfindLastIndexhardlinksclientponyfillsetPrototypeOfhookformStyleSheetpushcodesfastifyzodinstallenvequalitypicomatchUint8ClampedArraygetPrototypeOfsymlinkssyntaxcoercibleprivate datapersistentloggerString.prototype.matchAlllrumatchAllautoprefixerbannerargscurles7eventsstreamsArray.prototype.containsfastcopyes2015prefixsearchremovegroupByfunctionswhichoffsetchinesewalktrimUint32Arraygdprslotdeep-clonescheme-validationECMAScript 2023TypedArraypostcssarraynegative zeroposeArray.prototype.flatjsonschemaFloat64ArrayECMAScript 2019toolkita11yrecursivedirectoryfast-deep-copytc39dirtypedarraygenericscallboundencryptioncss-in-jspoint-freeartpackage.jsoncolumnsflatMapajvcss variablereact-testing-librarydom-testing-libraryreadablegetintrinsicpyyamlasserteventEmitterdeleteInt32Arrayerror-handlingreadablestreamvestimmutablehttpmiddlewaretddqueueMicrotasklisteners$.extendnativechannelstringifieryupyamlcharacterlintirqstableexitforEachcompilerreact-hook-form_.extendsequencevalidatorio-tseveryequaltranspilerjsonpathbundlingtelephonejQueryfsfantasy-landdatastructureES2016es-shim APItrimStartdescriptorchaivalidatecharacterstrimRightcolorsES2018zeroflattentypedfast-copy
1.0.0

25 days ago