{"id":13961803,"url":"https://github.com/tkgalk/denofun","last_synced_at":"2025-12-11T21:15:41.691Z","repository":{"id":62420947,"uuid":"195798569","full_name":"tkgalk/denofun","owner":"tkgalk","description":"Small utility library containing functions, monads and other fun stuff.","archived":true,"fork":false,"pushed_at":"2020-09-26T13:29:53.000Z","size":171,"stargazers_count":69,"open_issues_count":3,"forks_count":7,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-07-03T05:11:22.804Z","etag":null,"topics":["deno","functional-programming","typescript"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","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/tkgalk.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE.md","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-07-08T11:28:36.000Z","updated_at":"2023-07-25T14:27:16.000Z","dependencies_parsed_at":"2022-11-01T17:31:06.615Z","dependency_job_id":null,"html_url":"https://github.com/tkgalk/denofun","commit_stats":null,"previous_names":["galkowskit/denofun","tkgalk/denofun","tkg-codes/denofun"],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/tkgalk/denofun","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tkgalk%2Fdenofun","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tkgalk%2Fdenofun/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tkgalk%2Fdenofun/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tkgalk%2Fdenofun/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tkgalk","download_url":"https://codeload.github.com/tkgalk/denofun/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tkgalk%2Fdenofun/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":264562222,"owners_count":23628317,"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":["deno","functional-programming","typescript"],"created_at":"2024-08-08T17:01:27.779Z","updated_at":"2025-12-11T21:15:36.356Z","avatar_url":"https://github.com/tkgalk.png","language":"TypeScript","funding_links":[],"categories":["TypeScript"],"sub_categories":[],"readme":"# denofun\n\n\u003cp align=\"center\"\u003e\n    \u003cimg src=\"logo.svg\" width=\"256\" height=\"256\"\u003e\u003c/img\u003e\n    \u003cp align=\"center\"\u003e\n        Small utility library for \u003ca href=\"https://deno.land\"\u003eDeno\u003c/a\u003e containing functions, monads and other fun stuff.\n    \u003c/p\u003e\n\u003c/p\u003e\n\u003c/br\u003e\u003c/br\u003e\n\n## Roadmap\n\n⚠️ WATCH OUT!\n\nDenofun, like Deno itself, is still under heavy development. Semver will likely NOT be strictly enforced until v1.0.0.\nDenofun v1.0.0 will NOT be released until Deno v1.0.0 is released. In the meantime Denofun will try to stabilize, crush bugs and become as mature as possible. Until v1.0.0 treat this library as a curiosity. While early adopters and contributors are welcome, be wary if you want to use it somewhere you care about. For now.\n\n### Goals\n\n- provide a good replacement for libraries like Ramda or Lodash with \"native\" Deno feel\n- provide basic monads (Either, Maybe/Option)\n- good, out-of-the-box typings\n\n## Documentation\n\nThanks to how Deno works, it's easy to start using this library.\n\n```typescript\nimport compose from \"https://raw.githubusercontent.com/galkowskit/denofun/master/compose.ts\";\n```\n\nDenofun is also present in [deno.land](https://deno.land/) so you can use it for easier links.\n\n```typescript\nimport compose from \"https://deno.land/x/denofun/compose.ts\";\n```\n\nYou can AND SHOULD target specific versions or branches.\n\n```typescript\nimport compose from \"https://deno.land/x/denofun@0.3.0/compose.ts\";\n```\n\nOr if you find yourself needing the transpiled JavaScript version:\n\n```typescript\nimport compose from \"https://deno.land/x/denofun/compose.ts?js\";\n```\n\n### compose\n\n**compose** takes a list of functions and does right-to-left function composition.\n\n```typescript\nimport compose from \"https://deno.land/x/denofun/compose.ts\";\n\nfunction greet(name: string) {\n  return `hello, ${name}!`;\n}\n\nfunction makeLoud(x) {\n  return x.toUpperCase();\n}\n\nconst greetLoudly = compose(makeLoud, greet);\n\ngreetLoudly(\"world\"); // =\u003e HELLO, WORLD!\n```\n\n### concat\n\n**concat** adds two arrays or strings together.\n\n```typescript\nimport concat from \"https://deno.land/x/denofun/concat.ts\";\n\nconcat(\"hello\", \"world\"); // =\u003e \"helloworld\"\nconcat([1, 2, 3], [3, 4, 5]); // =\u003e [1, 2, 3, 3, 4, 5]\n```\n\n### curry\n\n**curry** returns a curried version of the provided n-arity function, it will return new 1-arity functions until all arguments are supplied.\n\n```typescript\nimport curry from \"https://deno.land/x/denofun/curry.ts\";\n\nconst greet = (name: string, age: number) =\u003e\n  `hello, I'm ${name} and I'm ${age} years old`;\ngreet(\"Tomasz\", 26); // =\u003e hello, I'm Tomasz and I'm 26 years old\n\nconst curriedGreet = curry(greet);\ncurriedGreet(\"Tomasz\")(26); // =\u003e hello, I'm Tomasz and I'm 26 years old\n\n// ===\n\nconst cars = [\n  { make: \"Alfa Romeo\", model: \"Giulia\" },\n  { make: \"Alfa Romeo\", model: \"Stelvio\" },\n  { make: \"Ford\", model: \"Mustang\" },\n  { make: \"Ford\", model: \"Focus\" },\n  { make: \"Toyota\", model: \"Mirai\" },\n  { make: \"Toyota\", model: \"Yaris\" },\n  { make: \"Toyota\", model: \"Supra\" },\n];\n\nconst filterCarsByMake = curry((make: string, car) =\u003e car.make === make);\nconst filterAlfas = filterCarsByMake(\"Alfa Romeo\");\ncars.filter(filterAlfas); // =\u003e [ { make: \"Alfa Romeo\", model: \"Giulia\" }, { make: \"Alfa Romeo\", model: \"Stelvio\" } ]\n```\n\n### Either\n\n**Either** is an interface that wraps values or Errors and can be used to:\n\n- handle error cases without throwing and catching errors\n- provide an alternative to Union types with runtime type safety and no need for typeguards\n\n```typescript\nimport { Either } from \"https://deno.land/x/denofun/either.ts\";\n\nfunction handleUnion(stringOrNumber: Either\u003cstring, number\u003e): number {\n    const value = stringOrNumber\n        .map((s: string) =\u003e s.toUpperCase()) // .map() applies the function to the left value, Either is a Functor\n        .left.map((s: string) =\u003e s.toLowerCase()) // but you can also use the .left shorthand for more clarity\n        .right.map((n: number) =\u003e n + 1) // .right will provide a way to apply functions to the right value\n        .flatMap((s) =\u003e { // Either is also a Monad, .flatMap() is also available on .left and .right\n            const n = parseFloat(s);\n            if (n) {\n                return right(n);\n            } else {\n                return left(s);\n            }\n        });\n    value.get() // =\u003e string | number\n    value.coerce(parseFloat) // =\u003e number (possibly NaN), also available on .left and .right\n\n    return value.mapEither(parseFloat, (n) =\u003e 1 / n) // =\u003e number (possibly NaN)\n}\n\nfunction handleError(stringOrError: Either\u003cstring, Error\u003e): string {\n    const safeString: string = stringOrError.catch((err) =\u003e err.message);\n    const value: string = stringOrError.try(); // will either throw the error or return the left value\n    const errorValue: stringOrError.right.try(); // will either throw a string or return an error as a value\n\n    return safeString;\n}\n```\n\n### either.error\n\n**either.error** wraps a value in the Either interface as a right value.\n`JSON.stringify()` will throw the value (ideally an Error)\n\n```typescript\nimport either from \"https://deno.land/x/denofun/either.ts\";\n// import error from \"https://deno.land/x/denofun/either/error.ts\"; // is also available\n\nconst numberOrError = either.error\u003cnumber, Error\u003e(new Error(\"message\"));\nnumberOrError.get(); // returns the error without throwing it\nnumberOrError.try(); // throws the error\nnumberOrError.right.try(); // returns the error with strict static typing\nJSON.stringify(rightString); // throws the Error\n```\n\n### either.jsonError\n\n**either.jsonError** wraps a value in the Either interface as a right value.\n`JSON.stringify()` will serialize it with its name, message, _and stack trace_, if available.\n\n```typescript\nimport either from \"https://deno.land/x/denofun/either.ts\";\n// import jsonError from \"https://deno.land/x/denofun/either/jsonError.ts\"; // is also available\n\nconst numberOrError = either.jsonError\u003cnumber, Error\u003e(new Error(\"message\"));\nnumberOrError.get(); // returns the error without throwing it\nnumberOrError.try(); // throws the error\nnumberOrError.right.try(); // returns the error with strict static typing\nJSON.stringify(rightString); // =\u003e {\"name\": \"Error\", \"message\": \"message\", \"stack\": \"...\"};\n```\n\n### either.left\n\n**either.left** wraps a value in the Either interface as a left value;\n\n```typescript\nimport either from \"https://deno.land/x/denofun/either.ts\";\n// import left from \"https://deno.land/x/denofun/either/left.ts\"; // is also available\n\nconst left12 = either.left\u003cnumber, string\u003e(12);\nleft12.get(); // =\u003e 12 with string | number union type, but no runtime error\nleft12.try(); // =\u003e 12 with strict static typing but potentially a runtime error (not in this case)\nleft12.right.try(); // throws 12\n```\n\n### either.partition\n\n**either.partition** partitions an array of `Either\u003cLeft, Right\u003e` in a tuple or `Left[]` and `Right[]`.\n\n```typescript\nimport { Either } from \"https://deno.land/x/denofun/either.ts\";\nimport partition from \"https://deno.land/x/denofun/either/partition.ts\";\n\nconst eitherValues: Array\u003cEither\u003cnumber, string\u003e\u003e = [\n  left(1),\n  left(3),\n  right(\"hello\"),\n  left(0.5),\n  right(\"0.5\"),\n  right(\"one\"),\n  left(NaN),\n];\nconst [leftValues, rightValues]: [number[], string[]] = partition(eitherValues);\n\nleftValues; // =\u003e [1, 3, 0.5, NaN]\nrightValues; // =\u003e [\"hello\", \"0.5\", \"one\"]\n\nleftValues.length + rightValues.length === 7; // =\u003e true\n```\n\n### either.right\n\n**either.right** wraps a value in the Either interface as a right value.\n\n```typescript\nimport either from \"https://deno.land/x/denofun/either.ts\";\n// import right from \"https://deno.land/x/denofun/either/right.ts\"; // is also available\n\nconst rightString = either.right\u003cnumber, string\u003e(\"hello\");\nrightString.get(); // \"hello\" with string | number union type, but no runtime error\nrightString.try(); // throws \"hello\"\nrightString.right.try(); // returns \"hello\" with strict static typing\n```\n\n### either.tryCatch\n\n**either.tryCatch** calls its callback argument immediately and handles any synchronous errors by returning an `Either\u003cType, Error\u003e`.\n\n```typescript\nimport { Either } from \"https://deno.land/x/denofun/either.ts\";\nimport tryCatch from \"https://deno.land/x/denofun/either/tryCatch.ts\";\n\nconst numberOrError: Either\u003cnumber, Error\u003e = tryCatch(() =\u003e {\n  throw new Error(\"message\");\n});\n\nnumberOrError.get(); // returns the error as a value\nnumberOrError\n  .map((n) =\u003e n + 1) // no-op\n  .try(); // throws the error\n```\n\n### either.tryCatchAsync\n\n**either.tryCatchAsync** calls its callback argument immediately and handles all synchronous **and** asynchronous errors by returning a `Promise\u003cEither\u003cType, Error\u003e\u003e`.\n\n```typescript\nimport { Either } from \"https://deno.land/x/denofun/either.ts\";\nimport { tryCatchAsync } from \"https://deno.land/x/denofun/either/try_catch.ts\";\n\nsetTimeout(async () =\u003e {\n  const numberOrError: Either\u003cnumber, Error\u003e = await tryCatchAsync(() =\u003e\n    Promise.reject(new Error(\"message\"))\n  );\n\n  numberOrError.get(); // returns the error as a value\n  numberOrError\n    .map((n) =\u003e n + 1) // no-op\n    .try(); // throws the error\n}, 1);\n```\n\n### equals\n\n**equals** checks if two values are equal, **warning:** for non-primitives uses JSON parsing (for now).\n\n```typescript\nimport equals from \"https://deno.land/x/denofun/equals.ts\";\n\nequals(1, 1); // =\u003e true\nequals(1, 2); // =\u003e false\nequals([1, 2, 3], [1, 2, 3]); // =\u003e true\nequals([1, 2, 3], [2, 1, 3]); // =\u003e false\nequals(\n  { make: \"Alfa Romeo\", model: \"Giulia\" },\n  { make: \"Alfa Romeo\", model: \"Giulia\" }\n); // =\u003e true\n```\n\n### filter\n\n**filter** runs filter function on every element of array and returns a new array with only those elements for which filter function returned true.\n\n```typescript\nimport filter from \"https://deno.land/x/denofun/filter.ts\";\n\nconst cars = [\n  { make: \"Alfa Romeo\", model: \"Giulia\" },\n  { make: \"Alfa Romeo\", model: \"Stelvio\" },\n  { make: \"Ford\", model: \"Mustang\" },\n  { make: \"Ford\", model: \"Focus\" },\n  { make: \"Toyota\", model: \"Mirai\" },\n  { make: \"Toyota\", model: \"Yaris\" },\n  { make: \"Toyota\", model: \"Supra\" },\n];\n\nfilter((car) =\u003e car.make === \"Ford\", cars); // =\u003e [ { make: \"Ford\", model: \"Mustang\" }, { make: \"Ford\", model: \"Focus\" } ]\n```\n\n### find\n\n**find** looks up first element of an array that matches the function passed.\n\n```typescript\nimport find from \"https://deno.land/x/denofun/find.ts\";\n\nconst cars = [\n  { make: \"Alfa Romeo\", model: \"Giulia\" },\n  { make: \"Alfa Romeo\", model: \"Stelvio\" },\n  { make: \"Ford\", model: \"Mustang\" },\n  { make: \"Ford\", model: \"Focus\" },\n  { make: \"Toyota\", model: \"Mirai\" },\n  { make: \"Toyota\", model: \"Yaris\" },\n  { make: \"Toyota\", model: \"Supra\" },\n];\n\nfunction findToyota(car) {\n  return car.make === \"Toyota\";\n}\n\nfind(findToyota, cars); // =\u003e { make: \"Toyota\", model: \"Mirai\" }\n```\n\n### flatten\n\n**flatten** takes an array of elements and flattens it by one level.\n\n```typescript\nimport flatten from \"https://deno.land/x/denofun/find.ts\";\n\nflatten([\n  [1, 2, 3],\n  [4, 5, 6],\n]); // =\u003e [1, 2, 3, 4, 5, 6]\nflatten([[1, [2, 3], [4, [5, [6]]]]]); // =\u003e [1, 2, 3, 4, [5, [6]]]\nflatten([]); // =\u003e []\n```\n\n### groupBy\n\n**groupBy** accepts a selector function and a list of elements, the elements will be grouped by the return value of the selector function.\n\n```typescript\nimport groupBy from \"https://deno.land/x/denofun/group_by.ts\";\n\nconst cars = [\n  { make: \"Alfa Romeo\", model: \"Giulia\" },\n  { make: \"Alfa Romeo\", model: \"Stelvio\" },\n  { make: \"Ford\", model: \"Mustang\" },\n  { make: \"Ford\", model: \"Focus\" },\n  { make: \"Toyota\", model: \"Mirai\" },\n  { make: \"Toyota\", model: \"Yaris\" },\n  { make: \"Toyota\", model: \"Supra\" },\n];\n\ngroupBy((car) =\u003e car.name, cars); // =\u003e { \"Alfa Romeo\": [ { make: \"Alfa Romeo\", model: \"Giulia\" }, { make: \"Alfa Romeo\", model: \"Stelvio\" } ], \"Ford\": [ { make: \"Ford\", model: \"Mustang\" }, { make: \"Ford\", model: \"Focus\" }, ], \"Toyota\": [ { make: \"Toyota\", model: \"Mirai\" }, { make: \"Toyota\", model: \"Yaris\" }, { make: \"Toyota\", model: \"Supra\" } ] }\ngroupBy((x) =\u003e x.length, [\"a\", \"bb\", \"bb\", \"ccc\"]); // =\u003e { 1: [\"a\"], 2: [\"bb\", \"bb\"], 3: [\"ccc\"] }\n```\n\n### has\n\n**has** checks if a key exists inside an object (does NOT check the prototype's keys!).\n\n```typescript\nimport has from \"https://deno.land/x/denofun/has.ts\";\n\nconst car = { make: \"Alfa Romeo\", model: \"Giulia\" };\nhas(\"make\", car); // =\u003e true\n```\n\n### head\n\n**head** returns the first element of an array or a string.\n\n```typescript\nimport head from \"https://deno.land/x/denofun/head.ts\";\n\nconst numbers = [1, 2, 3, 4, 5];\nhead(numbers); // =\u003e 1\n\n// ===\n\nhead(\"hello world!\"); // =\u003e \"h\"\n```\n\n### identity\n\n**identity** returns the provided element, otherwise does nothing.\n\n```typescript\nimport identity from \"https://deno.land/x/denofun/identity.ts\";\n\nconst x = 5;\nidentity(x); // =\u003e 5\n```\n\n### includes\n\n**includes** checks if an element exists in a string or array (including objects).\n\n```typescript\nimport includes from \"https://deno.land/x/denofun/includes.ts\";\n\nincludes(1, [1, 2, 3]); // =\u003e true\nincludes(\"hel\", \"hello world\"); // =\u003e true\nincludes({ make: \"Alfa Romeo\", model: \"Giulia\" }, [\n  { make: \"Alfa Romeo\", model: \"Giulia\" },\n  { make: \"Ford\", model: \"Mustang\" },\n]); // =\u003e true\n```\n\n### keys\n\n**keys** returns key names from a provided object.\n\n```typescript\nimport keys from \"https://deno.land/x/denofun/keys.ts\";\n\nconst car = { make: \"Alfa Romeo\", model: \"Giulia\" };\nkeys(car); // =\u003e [\"make\", \"model\"]\n```\n\n### last\n\n**last** accepts a list of items (or a string) and returns the last element (or character).\n\n```typescript\nimport last from \"https://deno.land/x/denofun/last.ts\";\n\nlast([1, \"test\", 3]); // =\u003e 3\nlast(\"hello world!\"); // =\u003e \"!\"\n```\n\n### lens\n\n**lens** lens returns a special lens object that can be used as a function setter/getter.\n\n```typescript\nimport lens from \"https://deno.land/x/denofun/lens.ts\";\n\nconst car = Object.freeze({\n  make: \"Toyota\",\n  model: \"GT86\",\n});\n\nconst getCarModel = (data: { make: string, model: string }) =\u003e data.model;\nconst setCarModel = (data: { make: string, model: string }, value: string) =\u003e ({ ...data, model: value });\n\nconst carModelLens = lens(getCarModel, setCarModel); // =\u003e Lens\u003cCar, string\u003e\n```\n\n### map\n\n**map** applies a function to each element of the array, returns the array of results.\n\n```typescript\nimport map from \"https://deno.land/x/denofun/map.ts\";\n\nconst numbers = [1, 2, 3, 4, 5];\nmap((n) =\u003e n * 2, numbers); // =\u003e [2, 4, 6, 8, 10]\n```\n\n### maybe\n\n**maybe** wraps a potentially `null` or `undefined` value in a `Maybe` type which provides\nthe map, flatMap, filter, and mapMaybe methods\n\n```typescript\nimport maybe from \"https://deno.land/x/denofun/maybe.ts\";\n\nconst numbers = [1, 2, 3, 4, 5];\nconst maybeNumber = maybe(numbers.find((n) =\u003e n \u003e 2));\nmaybeNumber.get(); // =\u003e 3\nmaybeNumber.map((n) =\u003e n + 1).get(); // =\u003e 4\nmaybeNumber.flatMap((n) =\u003e (n !== 3 ? maybe(1 / (n - 3)) : maybe())).get(); // =\u003e undefined\n```\n\n### memoize\n\n**memoize** returns a function that remembers the result of a function with a given parameters so it can cache the previous results.\n\n```typescript\nimport memoize from \"https://deno.land/x/denofun/memoize.ts\";\n\nconst double = (n) =\u003e n * 2;\nconst memoizedDouble = memoize(double);\n\nmemoizedDouble(2); // =\u003e 4 (calculated)\nmemoizedDouble(2); // =\u003e 4 (cached)\n```\n\n### nth\n\n**nth** returns element under given index, if negative index is provided element at (length + index) is returned.\n\n```typescript\nimport nth from \"https://deno.land/x/denofun/nth.ts\";\n\nnth(2, [1, 2, 3, 4, 5]); // =\u003e 3\nnth(4, \"hello world!\"); // =\u003e \"o\"\n```\n\n### omit\n\n**omit** returns a copy of an object but without specified keys.\n\n```typescript\nimport omit from \"https://deno.land/x/denofun/omit.ts\";\n\nconst car = { make: \"Alfa Romeo\", model: \"Giulia\" };\nomit([\"make\"], car); // =\u003e { model: \"Giulia\" }\n```\n\n### partition\n\n**partition** runs predicate on every element of input array and returns a tuple of two arrays: one where predicate returns `true`, one where predicate returns `false`.\n\n```typescript\nimport partition from \"https://deno.land/x/partition/partition.ts\";\npartition((x) =\u003e x % 3 === 0, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]); // =\u003e [[0, 3, 6, 9], [1, 2, 4, 5, 7, 8]]\n```\n\n### pick\n\n**pick** returns a copy of an object with only the keys selected\n\n```typescript\nimport pick from \"https://deno.land/x/denofun/pick.ts\";\n\nconst car = { make: \"Alfa Romeo\", model: \"Giulia\", doors: 5 };\npick([\"make\", \"model\"], car); // =\u003e { make: \"Alfa Romeo\", model: \"Giulia\" }\n```\n\n### pipe\n\n**pipe** takes a list of functions and does left-to-right function composition.\n\n```typescript\nimport pipe from \"https://deno.land/x/denofun/pipe.ts\";\n\nfunction greet(name: string) {\n  return `hello, ${name}!`;\n}\n\nfunction makeLoud(x) {\n  return x.toUpperCase();\n}\n\nconst greetLoudly = pipe(greet, makeLoud);\n\ngreetLoudly(\"world\"); // =\u003e \"HELLO, WORLD!\"\n```\n\n### pluck\n\n**pluck** takes an array of objects and a property name and returns an array containing the named property of each object.\n\n```typescript\nimport pluck from \"https://deno.land/x/denofun/pluck.ts\";\n\nconst cars = [\n  { make: \"Alfa Romeo\", model: \"Giulia\" },\n  { make: \"Alfa Romeo\", model: \"Stelvio\" },\n  { make: \"Ford\", model: \"Mustang\" },\n  { make: \"Ford\", model: \"Focus\" },\n  { make: \"Toyota\", model: \"Mirai\" },\n  { make: \"Toyota\", model: \"Yaris\" },\n  { make: \"Toyota\", model: \"Supra\" },\n];\n\npluck(\"make\", cars); // =\u003e [ \"Alfa Romeo\", \"Alfa Romeo\", \"Ford\", \"Ford\", \"Toyota\", \"Toyota\", \"Toyota\" ]\n```\n\n### prop\n\n**prop** returns a value from object under a specific key.\n\n```typescript\nimport prop from \"https://deno.land/x/denofun/prop.ts\";\n\nconst car = { make: \"Alfa Romeo\", model: \"Giulia\" };\nprop(\"make\", car); // =\u003e \"Alfa Romeo\"\n```\n\n### reduce\n\n**reduce** applies a reductor function to all elements of the array while\nkeeping the aggragete of previous iterations. Returns a single value.\n\n```typescript\nimport reduce from \"https://deno.land/x/denofun/reduce.ts\";\n\nconst numbers = [1, 2, 3, 4, 5];\n\nconst add = (a, b) =\u003e a + b;\nreduce(add, 0, numbers); // =\u003e 15\n```\n\n### reverse\n\n**reverse** reverses the order of the elements in array or string.\n\n```typescript\nimport reverse from \"https://deno.land/x/denofun/reverse.ts\";\n\nreverse([1, 2, 3, 4, 5]); // =\u003e [5, 4, 3, 2, 1]\n\n// ===\n\nreverse(\"hello world!\"); // =\u003e [\"!dlrow olleh\"]\n```\n\n### set\n\n**set** uses a provided lens, copies the provided object with a changed value.\n\n```typescript\nimport lens from \"https://deno.land/x/denofun/lens.ts\";\nimport set from \"https://deno.land/x/denofun/set.ts\";\n\nconst car = Object.freeze({\n  make: \"Toyota\",\n  model: \"GT86\",\n});\n\nconst getCarModel = (data: { make: string, model: string }) =\u003e data.model;\nconst setCarModel = (data: { make: string, model: string }, value: string) =\u003e ({ ...data, model: value });\n\nconst carModelLens = lens(getCarModel, setCarModel);\nset(carModelLens, car, \"Mirai\"); // =\u003e { make: \"Toyota\", model: \"Mirai\" }\n```\n\n### slice\n\n**slice** return a given slice of an array or string (wrapper over Array.prototype.slice).\n\n```typescript\nimport slice from \"https://deno.land/x/denofun/slice.ts\";\n\nslice(1, 3, [\"a\", \"b\", \"c\", \"d\", \"e\"]); // =\u003e ['b', 'c']\nslice(1, Infinity, [\"b\", \"c\", \"d\", \"e\"]); // =\u003e ['b', 'c', 'd', 'e']\n```\n\n### sort\n\n**sort** performs a sorting of array or string via provided sorting function.\n\nSorting function has to accept two arguments and retrun positive number if first argument\nis bigger than second, 0 if equal and negative if lesser.\n\n```typescript\nimport sort from \"https://deno.land/x/denofun/sort.ts\";\n\nfunction sortNumbers(a, b) {\n  if (a \u003e b) {\n    return 1;\n  }\n\n  if (a == b) {\n    return 0;\n  }\n\n  if (a \u003c b) {\n    return -1;\n  }\n}\n\nsort(sortNumbers, [5, 4, 2, 3, 1]); // =\u003e [1, 2, 3, 4, 5];\n\n// or shorter\nsort((a, b) =\u003e a - b, [5, 4, 2, 3, 1]); // =\u003e [1, 2, 3, 4, 5];\n```\n\n### split\n\n**split** splits a string by a given deliminator/separator.\n\n```typescript\nimport split from \"https://deno.land/x/denofun/split.ts\";\n\nsplit(\"/\", \"/usr/local/bin/deno\"); // =\u003e [\"\", \"usr\", \"local\", \"bin\", \"deno\"]\n```\n\n### tail\n\n**tail** returns all elements of the given array or string except the first.\n\n```typescript\nimport tail from \"https://deno.land/x/denofun/tail.ts\";\n\ntail([1, 2, 3, 4, 5]); // =\u003e [2, 3, 4, 5]\n\n// ===\n\ntail(\"hello world!\"); // =\u003e \"ello world!\"\n```\n\n### values\n\n**values** returns values from a provided object\n\n```typescript\nimport values from \"https://deno.land/x/denofun/values.ts\";\n\nconst car = { make: \"Alfa Romeo\", model: \"Giulia\" };\nvalues(car); // =\u003e [\"make\", \"model\"]\n```\n\n### view\n\n**view** uses a lens to get value from an object.\n\n```typescript\nimport lens from \"https://deno.land/x/denofun/lens.ts\";\nimport view from \"https://deno.land/x/denofun/view.ts\";\n\nconst car = Object.freeze({\n  make: \"Toyota\",\n  model: \"GT86\",\n});\n\nconst getCarModel = (data: { make: string, model: string }) =\u003e data.model;\nconst setCarModel = (data: { make: string, model: string }, value: string) =\u003e ({ ...data, model: value });\n\nconst carModelLens = lens(getCarModel, setCarModel);\nview(carModelLens, car); // =\u003e \"GT86\"\n```\n\n## For Developers\n\nIf you want to contribute to Denofun:\n\n1. Clone this repository.\n2. Make sure you have Deno installed.\n3. You can run tests with `deno test`.\n\nThanks!\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftkgalk%2Fdenofun","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftkgalk%2Fdenofun","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftkgalk%2Fdenofun/lists"}