From 0cd5973ddf7baf0a69b902d056d0b2562b1ead3a Mon Sep 17 00:00:00 2001 From: Sean-Lan Date: Fri, 14 Apr 2017 18:43:39 +0800 Subject: [PATCH 01/43] fix: fix the lift example error --- readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.md b/readme.md index 34faf12..a3e7507 100644 --- a/readme.md +++ b/readme.md @@ -456,7 +456,7 @@ const mult = a => b => a * b const liftedMult = liftA2(mult) // this function now works on functors like array liftedMult([1, 2], [3]) // [3, 6] -liftA2((a, b) => a + b)([1, 2], [3, 4]) // [4, 5, 5, 6] +liftA2(a => b => a + b)([1, 2], [3, 4]) // [4, 5, 5, 6] ``` Lifting a one-argument function and applying it does the same thing as `map`. From 9045867897550bee7a2fbac360cc959911114bcc Mon Sep 17 00:00:00 2001 From: Sunny Patel Date: Wed, 10 May 2017 09:45:10 +0530 Subject: [PATCH 02/43] Fix Typo in Closure Replaced Scopped with Scoped --- readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.md b/readme.md index 36ff36e..0d67777 100644 --- a/readme.md +++ b/readme.md @@ -149,7 +149,7 @@ add2(10) // 12 ## Closure A closure is a way of accessing a variable outside its scope. -Formally, a closure is a technique for implementing lexically scopped named binding. It is a way of storing a function with an environment. +Formally, a closure is a technique for implementing lexically scoped named binding. It is a way of storing a function with an environment. A closure is a scope which captures local variables of a function for access even after the execution has moved out of the block in which it is defined. ie. they allow referencing a scope after the block in which the variables were declared has finished executing. From 916d87505cce2f80679f9c316820e4599a90f9a3 Mon Sep 17 00:00:00 2001 From: Vladimir Gorej Date: Wed, 17 May 2017 00:32:37 +0200 Subject: [PATCH 03/43] docs(readme.md): add ramda-adjunct as FL ramda-adjunct is rapidly growing adjunct or core ramda library. --- readme.md | 1 + 1 file changed, 1 insertion(+) diff --git a/readme.md b/readme.md index 03d1d07..50af36b 100644 --- a/readme.md +++ b/readme.md @@ -859,6 +859,7 @@ getNestedPrice({item: {price: 9.99}}) // Some(9.99) * [mori](https://github.com/swannodette/mori) * [Immutable](https://github.com/facebook/immutable-js/) * [Ramda](https://github.com/ramda/ramda) +* [ramda-adjunct](https://github.com/char0n/ramda-adjunct) * [Folktale](http://folktalejs.org) * [monet.js](https://cwmyers.github.io/monet.js/) * [lodash](https://github.com/lodash/lodash) From 4f869c86d9071349cae9863f941369c833116dd3 Mon Sep 17 00:00:00 2001 From: jethro larson Date: Tue, 6 Jun 2017 13:20:33 -0700 Subject: [PATCH 04/43] Remove TODO entries. TODO stuff can be managed by issues --- readme.md | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/readme.md b/readme.md index cd3450f..a56b822 100644 --- a/readme.md +++ b/readme.md @@ -256,14 +256,6 @@ const predicate = (a) => a > 2; [1, 2, 3, 4].filter(predicate); // [3, 4] ``` -## Contracts - -TODO - -## Guarded Functions - -TODO - ## Categories Objects with associated functions that adhere to certain rules. E.g. [Monoid](#monoid) @@ -626,10 +618,6 @@ const sum = (list) => list.reduce((acc, val) => acc + val, 0); sum([1, 2, 3]) // 6 ``` -## Traversable - -TODO - ## Type Signatures Often functions in JavaScript will include comments that indicate the types of their arguments and return values. From a30176c55c51b6d4c37cee49fe3afa1f5efac931 Mon Sep 17 00:00:00 2001 From: jethro larson Date: Tue, 6 Jun 2017 13:51:07 -0700 Subject: [PATCH 05/43] Rename union type to sum type to complement with product type and change description and example to better match the concept --- readme.md | 102 ++++++++++++++++++++++++++++-------------------------- 1 file changed, 53 insertions(+), 49 deletions(-) diff --git a/readme.md b/readme.md index 50af36b..03061a8 100644 --- a/readme.md +++ b/readme.md @@ -56,8 +56,9 @@ __Table of Contents__ * [Foldable](#foldable) * [Traversable](#traversable) * [Type Signatures](#type-signatures) -* [Union type](#union-type) -* [Product type](#product-type) +* [Algebraic data type](#algebraic-data-type) + * [Sum type](#sum-type) + * [Product type](#product-type) * [Option](#option) * [Functional Programming Libraries in JavaScript](#functional-programming-libraries-in-javascript) @@ -102,9 +103,9 @@ Partially applying a function means creating a new function by pre-filling some // Helper to create partially applied functions // Takes a function and some arguments const partial = (f, ...args) => - // returns a function that takes the rest of the arguments - (...moreArgs) => - // and calls the original function with all of them + // returns a function that takes the rest of the arguments + (...moreArgs) => + // and calls the original function with all of them f(...args, ...moreArgs) // Something to apply @@ -146,10 +147,10 @@ add2(10) // 12 ## Closure A closure is a way of accessing a variable outside its scope. -Formally, a closure is a technique for implementing lexically scoped named binding. It is a way of storing a function with an environment. +Formally, a closure is a technique for implementing lexically scoped named binding. It is a way of storing a function with an environment. A closure is a scope which captures local variables of a function for access even after the execution has moved out of the block in which it is defined. -ie. they allow referencing a scope after the block in which the variables were declared has finished executing. +ie. they allow referencing a scope after the block in which the variables were declared has finished executing. ```js @@ -159,7 +160,7 @@ addToFive(3); //returns 8 ``` The function ```addTo()``` returns a function(internally called ```add()```), lets store it in a variable called ```addToFive``` with a curried call having parameter 5. -Ideally, when the function ```addTo``` finishes execution, its scope, with local variables add, x, y should not be accessible. But, it returns 8 on calling ```addToFive()```. This means that the state of the function ```addTo``` is saved even after the block of code has finished executing, otherwise there is no way of knowing that ```addTo``` was called as ```addTo(5)``` and the value of x was set to 5. +Ideally, when the function ```addTo``` finishes execution, its scope, with local variables add, x, y should not be accessible. But, it returns 8 on calling ```addToFive()```. This means that the state of the function ```addTo``` is saved even after the block of code has finished executing, otherwise there is no way of knowing that ```addTo``` was called as ```addTo(5)``` and the value of x was set to 5. Lexical scoping is the reason why it is able to find the values of x and add - the private variables of the parent which has finished executing. This value is called a Closure. @@ -167,7 +168,7 @@ The stack along with the lexical scope of the function is stored in form of refe Lambda Vs Closure: A lambda is essentially a function that is defined inline rather than the standard method of declaring functions. Lambdas can frequently be passed around as objects. -A closure is a function that encloses its surrounding state by referencing fields external to its body. The enclosed state remains across invocations of the closure. +A closure is a function that encloses its surrounding state by referencing fields external to its body. The enclosed state remains across invocations of the closure. __Further reading/Sources__ @@ -294,7 +295,7 @@ Math.abs(Math.abs(10)) ``` ```js -sort(sort(sort([2, 1]))) +sort(sort(sort([2,1]))) ``` ## Point-Free Style @@ -352,7 +353,7 @@ TODO ## Category A category in category theory is a collection of objects and morphisms between them. In programming, typically types -act as the objects and functions as morphisms. +act as the objects and functions as morphisms. To be a valid category 3 rules must be met: @@ -368,7 +369,8 @@ To be a valid category 3 rules must be met: Since these rules govern composition at very abstract level, category theory is great at uncovering new ways of composing things. -### Further reading +__Further reading__ + * [Category Theory for Programmers](https://bartoszmilewski.com/2014/10/28/category-theory-for-programmers-the-preface/) ## Value @@ -519,9 +521,9 @@ Lazy evaluation is a call-by-need evaluation mechanism that delays the evaluatio ```js const rand = function*() { - while (1 < 2) { + while (1 < 2) { yield Math.random() - } + } } ``` @@ -583,7 +585,7 @@ A monad is an object with [`of`](#pointed-functor) and `chain` functions. `chain ```js // Implementation -Array.prototype.chain = function (f) { +Array.prototype.chain = function(f){ return this.reduce((acc, it) => acc.concat(f(it)), []) } @@ -603,7 +605,7 @@ An object that has `extract` and `extend` functions. ```js const CoIdentity = (v) => ({ - val: v, + val: v, extract () { return this.val }, @@ -631,7 +633,7 @@ An applicative functor is an object with an `ap` function. `ap` applies a functi ```js // Implementation -Array.prototype.ap = function (xs) { +Array.prototype.ap = function(xs){ return this.reduce((acc, f) => acc.concat(xs.map(f)), []) } @@ -701,16 +703,16 @@ Make array a setoid: ```js Array.prototype.equals = function (arr) { - const len = this.length - if (len !== arr.length) { - return false - } - for (let i = 0; i < len; i++) { - if (this[i] !== arr[i]) { - return false + const len = this.length + if (len !== arr.length) { + return false } - } - return true + for (let i = 0; i < len; i++) { + if (this[i] !== arr[i]) { + return false + } + } + return true } ;[1, 2].equals([1, 2]) // true @@ -773,27 +775,29 @@ __Further reading__ * [Mostly Adequate Guide](https://drboolean.gitbooks.io/mostly-adequate-guide/content/ch7.html#whats-your-type) * [What is Hindley-Milner?](http://stackoverflow.com/a/399392/22425) on Stack Overflow -## Union type -A union type is the combination of two types together into another one. +## Algebraic data type +A composite type made from putting other types together. Two common classes of algebraic types are [sum](#sum-type) and [product](#product-type). -JS doesn't have static types but let's say we invent a type `NumOrString` which is a sum of `String` and `Number`. - -The `+` operator in JS works on strings and numbers so we can use this new type to describe its inputs and outputs: +### Sum type +A Sum type is the combination of two types together into another one. It is called sum because the number of possible values in the result type is the sum of the input types. +JavaScript doesn't have types like this but we can use `Set`s to pretend: ```js -// add :: (NumOrString, NumOrString) -> NumOrString -const add = (a, b) => a + b +// imagine that rather than sets here we have types that can only have these values +const bools = new Set([true, false]); +const halfTrue = new Set(['half-true']); -add(1, 2) // Returns number 3 -add('Foo', 2) // Returns string "Foo2" -add('Foo', 'Bar') // Returns string "FooBar" +// The weakLogic type contains the sum of the values from bools and halfTrue +const weakLogicValues = new Set([...bools, ...halfTrue]) ``` -Union types are also known as algebraic types, tagged unions, or sum types. +Sum types are sometimes called union types, discriminated unions, or tagged unions. There's a [couple](https://github.com/paldepind/union-type) [libraries](https://github.com/puffnfresh/daggy) in JS which help with defining and using union types. -## Product type +Flow includes [union types](https://flow.org/en/docs/types/unions/) and TypeScript has [Enums](https://www.typescriptlang.org/docs/handbook/enums.html) to serve the same role. + +### Product type A **product** type combines types together in a way you're probably more familiar with: @@ -801,12 +805,12 @@ A **product** type combines types together in a way you're probably more familia // point :: (Number, Number) -> {x: Number, y: Number} const point = (x, y) => ({x: x, y: y}) ``` -It's called a product because the total possible values of the data structure is the product of the different values. +It's called a product because the total possible values of the data structure is the product of the different values. Many languages have a tuple type which is the simplest formulation of a product type. See also [Set theory](https://en.wikipedia.org/wiki/Set_theory). ## Option -Option is a [union type](#union-type) with two cases often called `Some` and `None`. +Option is a [sum type](#sum-type) with two cases often called `Some` and `None`. Option is useful for composing functions that might not return a value. @@ -814,22 +818,22 @@ Option is useful for composing functions that might not return a value. // Naive definition const Some = (v) => ({ - val: v, - map (f) { + val: v, + map(f) { return Some(f(this.val)) - }, - chain (f) { + }, + chain(f) { return f(this.val) - } + } }) const None = () => ({ - map (f) { + map(f){ return this - }, - chain (f) { + }, + chain(f){ return this - } + } }) // maybeProp :: (String, {a}) -> Option a From 1601ecd8594f78b2689a574dffd91335ba2632b3 Mon Sep 17 00:00:00 2001 From: jethro larson Date: Wed, 7 Jun 2017 10:45:26 -0700 Subject: [PATCH 06/43] Delint, fix TOC, minor tweaks --- readme.md | 74 +++++++++++++++++++++++++++---------------------------- 1 file changed, 36 insertions(+), 38 deletions(-) diff --git a/readme.md b/readme.md index 03061a8..1340381 100644 --- a/readme.md +++ b/readme.md @@ -35,8 +35,6 @@ __Table of Contents__ * [Value](#value) * [Constant](#constant) * [Functor](#functor) - * [Preserves identity](#preserves-identity) - * [Composable](#composable) * [Pointed Functor](#pointed-functor) * [Lift](#lift) * [Referential Transparency](#referential-transparency) @@ -103,9 +101,9 @@ Partially applying a function means creating a new function by pre-filling some // Helper to create partially applied functions // Takes a function and some arguments const partial = (f, ...args) => - // returns a function that takes the rest of the arguments - (...moreArgs) => - // and calls the original function with all of them + // returns a function that takes the rest of the arguments + (...moreArgs) => + // and calls the original function with all of them f(...args, ...moreArgs) // Something to apply @@ -154,9 +152,9 @@ ie. they allow referencing a scope after the block in which the variables were d ```js -const addTo = x => y => x + y; -var addToFive = addTo(5); -addToFive(3); //returns 8 +const addTo = x => y => x + y +var addToFive = addTo(5) +addToFive(3) // returns 8 ``` The function ```addTo()``` returns a function(internally called ```add()```), lets store it in a variable called ```addToFive``` with a curried call having parameter 5. @@ -173,12 +171,12 @@ A closure is a function that encloses its surrounding state by referencing field __Further reading/Sources__ * [Lambda Vs Closure](http://stackoverflow.com/questions/220658/what-is-the-difference-between-a-closure-and-a-lambda) -* [JavaScript Closures highly voted disucussion](http://stackoverflow.com/questions/111102/how-do-javascript-closures-work) +* [How do JavaScript Closures Work?](http://stackoverflow.com/questions/111102/how-do-javascript-closures-work) ## Auto Currying Transforming a function that takes multiple arguments into one that if given less than its correct number of arguments returns a function that takes the rest. When the function gets the correct number of arguments it is then evaluated. -lodash & ramda have a `curry` function that works this way. +lodash & Ramda have a `curry` function that works this way. ```js const add = (x, y) => x + y @@ -295,7 +293,7 @@ Math.abs(Math.abs(10)) ``` ```js -sort(sort(sort([2,1]))) +sort(sort(sort([2, 1]))) ``` ## Point-Free Style @@ -406,12 +404,12 @@ john.age + five === ({name: 'John', age: 30}).age + (5) An object that implements a `map` function which, while running over each value in the object to produce a new object, adheres to two rules: -### Preserves identity +__Preserves identity__ ``` object.map(x => x) ≍ object ``` -### Composable +__Composable__ ``` object.map(compose(f, g)) ≍ object.map(g).map(f) @@ -521,9 +519,9 @@ Lazy evaluation is a call-by-need evaluation mechanism that delays the evaluatio ```js const rand = function*() { - while (1 < 2) { + while (1 < 2) { yield Math.random() - } + } } ``` @@ -585,7 +583,7 @@ A monad is an object with [`of`](#pointed-functor) and `chain` functions. `chain ```js // Implementation -Array.prototype.chain = function(f){ +Array.prototype.chain = function (f) { return this.reduce((acc, it) => acc.concat(f(it)), []) } @@ -605,7 +603,7 @@ An object that has `extract` and `extend` functions. ```js const CoIdentity = (v) => ({ - val: v, + val: v, extract () { return this.val }, @@ -633,7 +631,7 @@ An applicative functor is an object with an `ap` function. `ap` applies a functi ```js // Implementation -Array.prototype.ap = function(xs){ +Array.prototype.ap = function (xs) { return this.reduce((acc, f) => acc.concat(xs.map(f)), []) } @@ -703,16 +701,16 @@ Make array a setoid: ```js Array.prototype.equals = function (arr) { - const len = this.length - if (len !== arr.length) { - return false + const len = this.length + if (len !== arr.length) { + return false + } + for (let i = 0; i < len; i++) { + if (this[i] !== arr[i]) { + return false } - for (let i = 0; i < len; i++) { - if (this[i] !== arr[i]) { - return false - } - } - return true + } + return true } ;[1, 2].equals([1, 2]) // true @@ -784,8 +782,8 @@ A Sum type is the combination of two types together into another one. It is call JavaScript doesn't have types like this but we can use `Set`s to pretend: ```js // imagine that rather than sets here we have types that can only have these values -const bools = new Set([true, false]); -const halfTrue = new Set(['half-true']); +const bools = new Set([true, false]) +const halfTrue = new Set(['half-true']) // The weakLogic type contains the sum of the values from bools and halfTrue const weakLogicValues = new Set([...bools, ...halfTrue]) @@ -818,22 +816,22 @@ Option is useful for composing functions that might not return a value. // Naive definition const Some = (v) => ({ - val: v, - map(f) { + val: v, + map (f) { return Some(f(this.val)) - }, - chain(f) { + }, + chain (f) { return f(this.val) - } + } }) const None = () => ({ - map(f){ + map (f) { return this - }, - chain(f){ + }, + chain (f) { return this - } + } }) // maybeProp :: (String, {a}) -> Option a From aab4db75dd9895b128a6456bd340cd481ea6706c Mon Sep 17 00:00:00 2001 From: chocolateboy Date: Sat, 10 Jun 2017 23:00:44 +0000 Subject: [PATCH 07/43] rm obsolete links Remove links to [removed](https://github.com/hemanth/functional-programming-jargon/commit/4f869c86d9071349cae9863f941369c833116dd3) TODO sections: * Guarded Functions * Traversable --- readme.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/readme.md b/readme.md index 7d90d84..364ba2e 100644 --- a/readme.md +++ b/readme.md @@ -30,7 +30,6 @@ __Table of Contents__ * [Point-Free Style](#point-free-style) * [Predicate](#predicate) * [Contracts](#contracts) -* [Guarded Functions](#guarded-functions) * [Category](#category) * [Value](#value) * [Constant](#constant) @@ -52,7 +51,6 @@ __Table of Contents__ * [Setoid](#setoid) * [Semigroup](#semigroup) * [Foldable](#foldable) -* [Traversable](#traversable) * [Type Signatures](#type-signatures) * [Algebraic data type](#algebraic-data-type) * [Sum type](#sum-type) From 9dd0916753b42b7b10d135a7d471657b43198bf6 Mon Sep 17 00:00:00 2001 From: Tommy Kelly Date: Mon, 12 Jun 2017 10:16:41 -0700 Subject: [PATCH 08/43] add link to sanctuary --- readme.md | 1 + 1 file changed, 1 insertion(+) diff --git a/readme.md b/readme.md index 364ba2e..76665f9 100644 --- a/readme.md +++ b/readme.md @@ -859,6 +859,7 @@ getNestedPrice({item: {price: 9.99}}) // Some(9.99) * [Lazy.js](https://github.com/dtao/lazy.js) * [maryamyriameliamurphies.js](https://github.com/sjsyrek/maryamyriameliamurphies.js) * [Haskell in ES6](https://github.com/casualjavascript/haskell-in-es6) +* [Sanctuary](https://github.com/sanctuary-js/sanctuary) --- From 3e94a1a690b12006c7002e895ad3df2bdf60fa96 Mon Sep 17 00:00:00 2001 From: Wisnu Adi Nurcahyo Date: Thu, 15 Jun 2017 16:50:44 +0700 Subject: [PATCH 09/43] Add translation for Bahasa Indonesia --- contributing.md | 34 +-- package.json | 12 +- readme.md | 547 +++++++++++++++++++++++++++++++++--------------- 3 files changed, 385 insertions(+), 208 deletions(-) diff --git a/contributing.md b/contributing.md index 138a49a..a04a54a 100644 --- a/contributing.md +++ b/contributing.md @@ -1,29 +1,7 @@ -# Contributing +# Berkontribusi -This project is a work in progress. Contributions are very welcome. - -## Hard rules -* Run `npm test` to lint the code examples. Your changes must pass. -* If you add a new definition or reorder them run `npm run toc` to regenerate the table of contents. - -That said, we'd like to maintain some consistency across the document. - -## Style guide -1. Every definition should include at least one JavaScript code example. -1. Definitions should be written using the simplest language possible. Every word should tell. -1. Target programmers that have no functional programming experience. -1. We value understandability more than accuracy. e.g. It's okay to describe a functor as a container. -1. Don't overuse jargon even if defined elsewhere in the document. -1. Link to terms defined in the document when you use them in a definition. -1. Avoid big walls of text - -## Code conventions -[![JavaScript Style Guide](https://cdn.rawgit.com/feross/standard/master/badge.svg)](https://github.com/feross/standard) - -* Be consistent with other examples -* Prefer arrow functions -* Parenthesis around function arguments -* Put output values in comments -* Keep it short and simple - -This styleguide is a WIP too! Send PRs :) +Proyek ini berkembang seiring dengan berkembangnya konten dari +[_Functional Programming Jargon_](https://github.com/hemanth/functional-programming-jargon/) +milik [hemanth](https://github.com/hemanth/). Maka dari itu sebaiknya Anda +berkontribusi langsung ke _repository_ tersebut. Akan tetapi, kontribusi dalam +bentuk apapun ke _repository_ ini sangat dipersilakan. diff --git a/package.json b/package.json index e7cfe68..0379bbc 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { - "name": "functional-programming-jargons", + "name": "jargon-pemrograman-fungsional", "version": "1.0.0", - "description": "Jargon from the functional programming world in simple terms!", + "description": "Jargon dari dunia pemrograman fungsional secara sederhana!", "main": "index.js", "scripts": { "test": "eslint readme.md", @@ -9,14 +9,14 @@ }, "repository": { "type": "git", - "url": "git+https://github.com/hemanth/functional-programming-jargon.git" + "url": "git+https://github.com/wisn/jargon-pemrograman-fungsional.git" }, - "author": "hemanth", + "author": "wisn", "license": "MIT", "bugs": { - "url": "https://github.com/hemanth/functional-programming-jargon/issues" + "url": "https://github.com/wisn/jargon-pemrograman-fungsional/issues" }, - "homepage": "https://github.com/hemanth/functional-programming-jargon#readme", + "homepage": "https://github.com/wisn/jargon-pemrograman-fungsional#readme", "devDependencies": { "eslint": "^3.4.0", "eslint-config-standard": "^6.0.0", diff --git a/readme.md b/readme.md index 364ba2e..126080e 100644 --- a/readme.md +++ b/readme.md @@ -1,19 +1,24 @@ -# Functional Programming Jargon +# Jargon Pemrograman Fungsional -Functional programming (FP) provides many advantages, and its popularity has been increasing as a result. However, each programming paradigm comes with its own unique jargon and FP is no exception. By providing a glossary, we hope to make learning FP easier. +_Functional programming_ (FP) atau pemrograman fungsional memberikan banyak +keuntungan, dan kini popularitasnya telah meningkat sebagai hasilnya. Namun, +setiap paradigma pemrograman datang dengan jargon uniknya masing-masing +dan FP tidak terkecuali. Dengan memberikan glosarium, +kami berharap dapat mempermudah belajar FP. -Examples are presented in JavaScript (ES2015). [Why JavaScript?](https://github.com/hemanth/functional-programming-jargon/wiki/Why-JavaScript%3F) +Contoh yang ada disajikan dalam JavaScript (ES2015). +[Kenapa JavaScript?](https://github.com/hemanth/functional-programming-jargon/wiki/Why-JavaScript%3F) -*This is a [WIP](https://github.com/hemanth/functional-programming-jargon/issues/20); please feel free to send a PR ;)* +*Ini adalah sebuah +[WIP](https://github.com/hemanth/functional-programming-jargon/issues/20) +dari +[Functional Programming Jargon](https://github.com/hemanth/functional-programming-jargon/) +milik [hemanth](https://github.com/hemanth/); Jangan ragu untuk mengirim PR ;)* -Where applicable, this document uses terms defined in the [Fantasy Land spec](https://github.com/fantasyland/fantasy-land) +Jika ada, dokumen ini menggunakan istilah yang didefinisikan dalam spesifikasi +[Fantasy Land](https://github.com/fantasyland/fantasy-land). -__Translations__ -* [Portuguese](https://github.com/alexmoreno/jargoes-programacao-funcional) -* [Spanish](https://github.com/idcmardelplata/functional-programming-jargon/tree/master) -* [Chinese](https://github.com/shfshanyue/fp-jargon-zh) - -__Table of Contents__ +__Daftar Isi__ * [Arity](#arity) @@ -25,11 +30,11 @@ __Table of Contents__ * [Function Composition](#function-composition) * [Continuation](#continuation) * [Purity](#purity) -* [Side effects](#side-effects) +* [Side Effect](#side-effects) * [Idempotent](#idempotent) * [Point-Free Style](#point-free-style) * [Predicate](#predicate) -* [Contracts](#contracts) +* [Contract](#contract) * [Category](#category) * [Value](#value) * [Constant](#constant) @@ -51,19 +56,29 @@ __Table of Contents__ * [Setoid](#setoid) * [Semigroup](#semigroup) * [Foldable](#foldable) -* [Type Signatures](#type-signatures) +* [Type Signature](#type-signature) * [Algebraic data type](#algebraic-data-type) * [Sum type](#sum-type) * [Product type](#product-type) * [Option](#option) -* [Functional Programming Libraries in JavaScript](#functional-programming-libraries-in-javascript) +* [Pustaka Pemrograman Fungsional dalam JavaScript](#pustaka-pemrograman-fungsional-dalam-javascript) ## Arity -The number of arguments a function takes. From words like unary, binary, ternary, etc. This word has the distinction of being composed of two suffixes, "-ary" and "-ity." Addition, for example, takes two arguments, and so it is defined as a binary function or a function with an arity of two. Such a function may sometimes be called "dyadic" by people who prefer Greek roots to Latin. Likewise, a function that takes a variable number of arguments is called "variadic," whereas a binary function must be given two and only two arguments, currying and partial application notwithstanding (see below). +_Arity_ merupakan banyaknya argumen yang diambil oleh fungsi. +Berasal dari kata-kata seperti _unary_, _binary_, _ternary_, dan lain-lain. +Kata ini memiliki perbedaan yang terdiri dari dua sufiks, "-ary" dan "-ity." +Penjumlahan, misalnya, mengambil dua argumen, dan jadi didefinisikan sebagai +fungsi biner (_binary function_) atau fungsi dengan dua _arity_. +Fungsi semacam itu terkadang disebut "_dyadic_" oleh orang-orang yang lebih +menyukai bahasa Yunani dari bahasa Latin. +Demikian juga, fungsi yang mengambil sejumlah variabel argumen disebut +"_variadic_", sedangkan fungsi biner harus diberikan dua dan hanya dua +argumen, meskipun _currying_ dan _partial application_ (lihat di bawah). + ```js const sum = (a, b) => a + b @@ -71,12 +86,14 @@ const sum = (a, b) => a + b const arity = sum.length console.log(arity) // 2 -// The arity of sum is 2 +// Arity dari fungsi `sum` adalah dua ``` ## Higher-Order Functions (HOF) -A function which takes a function as an argument and/or returns a function. +_Higher-Order Function_ adalah sebuah fungsi yang mengambil fungsi sebagai +argumen dan/atau mengembalikan sebuah fungsi. + ```js const filter = (predicate, xs) => xs.filter(predicate) @@ -92,40 +109,50 @@ filter(is(Number), [0, '1', 2, null]) // [0, 2] ## Partial Application -Partially applying a function means creating a new function by pre-filling some of the arguments to the original function. +Menerapkan fungsi secara parsial (_Partial Application_ atau Fungsi Parsial) +artinya membuat fungsi baru dengan mengisi beberapa argumen ke fungsi semula. ```js -// Helper to create partially applied functions -// Takes a function and some arguments +// Helper membuat sebagian fungsi yang diaplikasikan +// Mengambil sebuah fungsi dan beberapa argumen const partial = (f, ...args) => - // returns a function that takes the rest of the arguments + // mengembalikan sebuah fungsi yang mengambil sisa argumen (...moreArgs) => - // and calls the original function with all of them + // dan memanggil fungsi asilnya dengan semuanya f(...args, ...moreArgs) -// Something to apply +// Sesuatu untuk diaplikasikan const add3 = (a, b, c) => a + b + c -// Partially applying `2` and `3` to `add3` gives you a one-argument function +// Menerapkan `2` dan `3` secara parsial ke `add3` +// Sehingga, memberikan Anda sebuah fungsi dengan satu argumen const fivePlus = partial(add3, 2, 3) // (c) => 2 + 3 + c fivePlus(4) // 9 ``` -You can also use `Function.prototype.bind` to partially apply a function in JS: +Anda juga dapat menggunakan `Function.prototype.bind` untuk menerapkan +fungsi parsial di JavaScript: + ```js const add1More = add3.bind(null, 2, 3) // (c) => 2 + 3 + c ``` -Partial application helps create simpler functions from more complex ones by baking in data when you have it. [Curried](#currying) functions are automatically partially applied. +_Partial application_ atau fungsi parsial membantu menciptakan fungsi yang +lebih sederhana dari yang lebih kompleks dengan memadukan data saat Anda +memilikinya. [_Curried_](#currying) _function_ sudah secara otomatis diterapkan +secara parsial. ## Currying -The process of converting a function that takes multiple arguments into a function that takes them one at a time. +_Currying_ merupakan sebuah proses mengubah fungsi yang membutuhkan banyak +argumen menjadi fungsi yang membawa mereka satu-persatu. + +Setiap kali fungsi dipanggil hanya menerima satu argumen dan mengembalikan +sebuah fungsi yang membutuhkan satu argumen sampai semua argumen dilewatkan. -Each time the function is called it only accepts one argument and returns a function that takes one argument until all arguments are passed. ```js const sum = (a, b) => a + b @@ -142,39 +169,66 @@ add2(10) // 12 ## Closure -A closure is a way of accessing a variable outside its scope. -Formally, a closure is a technique for implementing lexically scoped named binding. It is a way of storing a function with an environment. +_Closure_ merupakan sebuah cara untuk mengakses sebuah variabel yang berada +di luar cakupannya. +Secara formal, _closure_ merupakan sebuah teknik untuk menerapkan _lexically +scoped_ bernama _binding_. Ini adalah cara untuk menyimpan sebuah fungsi +dengan sebuah _environment_. -A closure is a scope which captures local variables of a function for access even after the execution has moved out of the block in which it is defined. -ie. they allow referencing a scope after the block in which the variables were declared has finished executing. +_Closure_ adalah lingkup yang menangkap variabel lokal dari suatu fungsi untuk +askes bahkan setelah eksekusi telah berpindah dari blok yang didefinisikan. +Yaitu, mereka membiarkan referensi lingkup setelah blok dimana variabel +dinyatakan telah selesai mengeksekusi. ```js const addTo = x => y => x + y var addToFive = addTo(5) -addToFive(3) // returns 8 +addToFive(3) // mengembalikan 8 ``` -The function ```addTo()``` returns a function(internally called ```add()```), lets store it in a variable called ```addToFive``` with a curried call having parameter 5. -Ideally, when the function ```addTo``` finishes execution, its scope, with local variables add, x, y should not be accessible. But, it returns 8 on calling ```addToFive()```. This means that the state of the function ```addTo``` is saved even after the block of code has finished executing, otherwise there is no way of knowing that ```addTo``` was called as ```addTo(5)``` and the value of x was set to 5. +Fungsi `addTo()` mengembalikan sebuah fungsi (secara internal disebut `add()`), +lalu disimpan di variabel yang disebut `addToFive` dengan _curried call_ yang +memiliki parameter `5`. -Lexical scoping is the reason why it is able to find the values of x and add - the private variables of the parent which has finished executing. This value is called a Closure. +Idealnya, ketika fungsi `addTo` selesai dieksekusi, cakupannya, +dengan variabel lokal `add`, `x`, `y` seharusnya tidak dapat diakses. Tapi, +itu mengembalikan `8` ketika memanggil `addToFive()`. Ini artinya kondisi +dari fungsi `addTo` disimpan bahkan setelah blok kode selesai dieksekusi. +Jika tidak, tidak mungkin dapat mengetahui bahwa `addTo` telah dipanggil +sebagai `addTo(5)` dan nilai dari `x` telah ditentukan menjadi `5`. -The stack along with the lexical scope of the function is stored in form of reference to the parent. This prevents the closure and the underlying variables from being garbage collected(since there is at least one live reference to it). +_Lexical scoping_ adalah alasan mengapa ia dapat menemukan nilai dari `x` dan +`add` - sebuah variabel _private_ induk yang telah selesai dieksekusi. +Nilai ini disebut _Closure_. -Lambda Vs Closure: A lambda is essentially a function that is defined inline rather than the standard method of declaring functions. Lambdas can frequently be passed around as objects. +`Stack` beserta `lexical scope` fungsinya disimpan dalam bentuk referensi +ke induknya. Hal ini mencegah _closure_ dan variabel-variabel mendasar agar +tidak dikumpulkan sebagai sampah (karena setidaknya ada satu refernsi +langsung untuk itu). -A closure is a function that encloses its surrounding state by referencing fields external to its body. The enclosed state remains across invocations of the closure. +__Lambda Vs. Closure__ +_Lambda_ pada dasarnya adalah fungsi yang didefinisikan secara _inline_ +daripada metode standar untuk mendeklarasikan fungsi. Lambda sering dapat +dilewatkan sebagai objek. + +_Closure_ adalah fungsi yang membungkus keadaan sekitarnya dengan +mereferensikan bidang yang ada di luar tubuhnya. _State_ tertutup tetap +berada di seberang seruan _closure_. -__Further reading/Sources__ +__Bacaan lebih lanjut/Sumber__ * [Lambda Vs Closure](http://stackoverflow.com/questions/220658/what-is-the-difference-between-a-closure-and-a-lambda) * [How do JavaScript Closures Work?](http://stackoverflow.com/questions/111102/how-do-javascript-closures-work) ## Auto Currying -Transforming a function that takes multiple arguments into one that if given less than its correct number of arguments returns a function that takes the rest. When the function gets the correct number of arguments it is then evaluated. -lodash & Ramda have a `curry` function that works this way. +_Auto currying_ mengubah fungsi yang membutuhkan banyak argumen menjadi +argumen yang jika diberikan kurang dari jumlah argumen yang benar mengembalikan +sebuah fungsi yang mengambil sisanya. Bila fungsi mendapatkan jumlah argumen +yang benar, maka akan dievaluasi. + +lodash dan Ramda memiliki fungsi `curry` yang bekerja seperti di bawah. ```js const add = (x, y) => x + y @@ -185,23 +239,28 @@ curriedAdd(1) // (y) => 1 + y curriedAdd(1)(2) // 3 ``` -__Further reading__ +__Bacaan lebih lanjut__ * [Favoring Curry](http://fr.umio.us/favoring-curry/) * [Hey Underscore, You're Doing It Wrong!](https://www.youtube.com/watch?v=m3svKOdZijA) ## Function Composition -The act of putting two functions together to form a third function where the output of one function is the input of the other. +_Function composition_ atau komposisi fungsi adalah tindakan yang menempatkan +dua fungsi bersama untuk membentuk fungsi ketiga dimana keluaran dari satu +fungsi adalah masukan dari yang lain. + ```js -const compose = (f, g) => (a) => f(g(a)) // Definition -const floorAndToString = compose((val) => val.toString(), Math.floor) // Usage +const compose = (f, g) => (a) => f(g(a)) // Definisi +const floorAndToString = compose((val) => val.toString(), Math.floor) // Penggunaan floorAndToString(121.212121) // '121' ``` ## Continuation -At any given point in a program, the part of the code that's yet to be executed is known as a continuation. +Pada suatu titik dalam sebuah program, bagian dari kode yang belum dieksekusi +dikenal sebagai kelanjutan/kontinuitas atau _continuation_. + ```js const printAsString = (num) => console.log(`Given ${num}`) @@ -214,16 +273,20 @@ const addOneAndContinue = (num, cc) => { addOneAndContinue(2, printAsString) // 'Given 3' ``` -Continuations are often seen in asynchronous programming when the program needs to wait to receive data before it can continue. The response is often passed off to the rest of the program, which is the continuation, once it's been received. +Kontinuitas sering terlihat pada pemrograman _asynchronous_ saat program +perlu menunggu untuk menerima data sebelum dapat melanjutkan. Responnya +sering dilewatkan ke sisa program, yang merupakan kelanjutannya, begitu +sudah diterima. + ```js const continueProgramWith = (data) => { - // Continues program with data + // Melanjutkan program dengan data } readFileAsync('path/to/file', (err, response) => { if (err) { - // handle error + // mengatasi galat return } continueProgramWith(response) @@ -232,8 +295,10 @@ readFileAsync('path/to/file', (err, response) => { ## Purity -A function is pure if the return value is only determined by its -input values, and does not produce side effects. +Sebuah fungsi dikatan murni atau _pure_ jika mengembalikan nilai yang hanya +ditentukan oleh nilai masukannya, dan tidak menghasilkan efek samping +atau _side effect_. + ```js const greet = (name) => `Hi, ${name}` @@ -241,7 +306,8 @@ const greet = (name) => `Hi, ${name}` greet('Brianne') // 'Hi, Brianne' ``` -As opposed to each of the following: +Berbeda dengan masing-masing hal di bawah: + ```js window.name = 'Brianne' @@ -251,7 +317,8 @@ const greet = () => `Hi, ${window.name}` greet() // "Hi, Brianne" ``` -The above example's output is based on data stored outside of the function... +Contoh keluaran di atas didasarkan pada data yang tersimpan di luar fungsi... + ```js let greeting @@ -264,11 +331,14 @@ greet('Brianne') greeting // "Hi, Brianne" ``` -... and this one modifies state outside of the function. +... dan yang satu ini memodifikasi keadaan di luar fungsi. -## Side effects +## Side Effect + +Sebuah fungsi atau ekspresi dikatakan memiliki efek samping jika selain +mengembalikan nilai, ia berinterasksi dengan (membaca dari atau menulis ke) +keadaan yang dapat berubah eksternal. -A function or expression is said to have a side effect if apart from returning a value, it interacts with (reads from or writes to) external mutable state. ```js const differentEveryTime = new Date() @@ -280,7 +350,9 @@ console.log('IO is a side effect!') ## Idempotent -A function is idempotent if reapplying it to its result does not produce a different result. +Suatu fungsi _idempotent_ jika mengaplikasikannya kembali hasilnya tidak +menghasilkan hasil yang berbeda. + ``` f(f(x)) ≍ f(x) @@ -296,28 +368,40 @@ sort(sort(sort([2, 1]))) ## Point-Free Style -Writing functions where the definition does not explicitly identify the arguments used. This style usually requires [currying](#currying) or other [Higher-Order functions](#higher-order-functions-hof). A.K.A Tacit programming. +Menulis fungsi dimana definisi tidak secara eksplisit mengidentifikasi +argumen yang digunakan. Gaya ini biasanya memerlukan [_currying_](#currying) +atau lainnya [_Higher-Order function_](#higher-order-functions-hof). +Alias, _Tacit programming_. + ```js -// Given +// Diberikan const map = (fn) => (list) => list.map(fn) const add = (a) => (b) => a + b -// Then +// Lalu -// Not points-free - `numbers` is an explicit argument +// Bukan points-free - `numbers` merupakan argumen eksplisit const incrementAll = (numbers) => map(add(1))(numbers) -// Points-free - The list is an implicit argument +// Points-free - `list` merupakan argumen implisit const incrementAll2 = map(add(1)) ``` -`incrementAll` identifies and uses the parameter `numbers`, so it is not points-free. `incrementAll2` is written just by combining functions and values, making no mention of its arguments. It __is__ points-free. +`incrementAll` mengidentifikasi dan menggunakan parameter `numbers`, jadi itu +bukan _points-free_. `incrementAll2` dituliskan hanya dengan menggabungkan +beberapa fungsi dan beberapa nilai, membuatnya tidak menyebut satu pun +argumennya. Itu __adalah__ _points-free_. -Points-free function definitions look just like normal assignments without `function` or `=>`. +Definisi _points-free function_ terlihat seperti _assignment_ normal tanpa +`function` atau `=>`. ## Predicate -A predicate is a function that returns true or false for a given value. A common use of a predicate is as the callback for array filter. + +Suatu _predicate_ adalah sebuah fungsi yang mengembalikan nilai `true` atau +`false` untuk suatu nilai yang diberikan. Biasanya digunakan sebagai _callback_ +untuk menyaring _array_. + ```js const predicate = (a) => a > 2 @@ -325,12 +409,16 @@ const predicate = (a) => a > 2 ;[1, 2, 3, 4].filter(predicate) // [3, 4] ``` -## Contracts +## Contract + +Suatu _contract_ menentukan kewajiban dan jaminan perilaku dari suatu fungsi +atau ekspresi saat _runtime_. Ini bertindak sebagai seperangkat aturan yang +diharapkan dari masukan dan keluaran suatu fungsi atau ekspresi, dan +kesalahan umumnya dilaporkan setiap kali sebuah kontrak dilanggar. -A contract specifies the obligations and guarantees of the behavior from a function or expression at runtime. This acts as a set of rules that are expected from the input and output of a function or expression, and errors are generally reported whenever a contract is violated. ```js -// Define our contract : int -> int +// Mendefinisikan contract kami : int -> int const contract = (input) => { if (typeof input === 'number') return true throw new Error('Contract violated: expected int -> int') @@ -344,30 +432,34 @@ addOne('some string') // Contract violated: expected int -> int ## Category -A category in category theory is a collection of objects and morphisms between them. In programming, typically types -act as the objects and functions as morphisms. +Kategori dalam _category theory_ adalah kumpulan objek dan morfisme +(_morphism_) di antara keduanya. Dalam pemrograman, biasanya _types_ bertindak +sebagai objek dan fungsi sebagai morfisme. -To be a valid category 3 rules must be met: -1. There must be an identity morphism that maps an object to itself. - Where `a` is an object in some category, - there must be a function from `a -> a`. -2. Morphisms must compose. - Where `a`, `b`, and `c` are objects in some category, - and `f` is a morphism from `a -> b`, and `g` is a morphism from `b -> c`; - `g(f(x))` must be equivalent to `(g • f)(x)`. -3. Composition must be associative - `f • (g • h)` is the same as `(f • g) • h` +Untuk menjadi kategori yang sah, tiga aturan harus dipenuhi: -Since these rules govern composition at very abstract level, category theory is great at uncovering new ways of composing things. +1. Harus ada morfisme identitas yang memetakan objek itu sendiri. + Dimana `a` adalah sebuah objek dalam beberapa kategori, + harus ada fungsi dari `a -> a`. +2. Morfisme harus disusun. + Dimana `a`, `b`, dan `c` adalah objek dalam beberapa kategori, + dan `f` adalah morfisme dari `a -> b`, serta `g` adalah morfisme dari + `b -> c`; `g(f(x))` harus sama dengan `(g • f)(x)`. +3. Komposisi harus asosiatif. + `f • (g • h)` sama halnya dengan `(f • g) • h`. -__Further reading__ +Karena aturan ini mengatur komposisi pada tingkat yang sangat abstrak, +teori kategori sangat bagus dalam menemukan cara baru untuk menyusun sesuatu. + +__Bacaan lebih lanjut__ * [Category Theory for Programmers](https://bartoszmilewski.com/2014/10/28/category-theory-for-programmers-the-preface/) ## Value -Anything that can be assigned to a variable. +Apa saja yang dapat di-_assign_ ke variabel. + ```js 5 @@ -379,16 +471,20 @@ undefined ## Constant -A variable that cannot be reassigned once defined. +Sebuah variabel yang tidak dapat ditetapkan kembali setelah ditentukan nilainya. ```js const five = 5 const john = Object.freeze({name: 'John', age: 30}) ``` -Constants are [referentially transparent](#referential-transparency). That is, they can be replaced with the values that they represent without affecting the result. +_Constant_ atau konstanta adalah +[_referentially transparent_](#referential-transparency). Artinya, mereka +dapat diganti dengan nilai yang mereka wakili tanpa mempengaruhi hasilnya. + +Dengan dua konstanta di atas, ekspresi berikut akan selalu mengembalikan +nilai `true`. -With the above two constants the following expression will always return `true`. ```js john.age + five === ({name: 'John', age: 30}).age + (5) @@ -396,7 +492,10 @@ john.age + five === ({name: 'John', age: 30}).age + (5) ## Functor -An object that implements a `map` function which, while running over each value in the object to produce a new object, adheres to two rules: +Suatu objek yang mengimplementasikan fungsi `map`, yang ketika menjalankan +lebih dari setiap nilai pada objek untuk menghasilkan objek baru, mematuhi +dua aturan: + __Preserves identity__ ``` @@ -409,15 +508,18 @@ __Composable__ object.map(compose(f, g)) ≍ object.map(g).map(f) ``` -(`f`, `g` be arbitrary functions) +(`f`, `g` menjadi fungsi sewenang-wenang) + +_Functor_ umum dalam JavaScript adalah `Array` karena mematuhi dua aturan +_functor_, yaitu: -A common functor in JavaScript is `Array` since it abides to the two functor rules: ```js [1, 2, 3].map(x => x) // = [1, 2, 3] ``` -and +dan + ```js const f = x => x + 1 @@ -428,9 +530,12 @@ const g = x => x * 2 ``` ## Pointed Functor -An object with an `of` function that puts _any_ single value into it. -ES2015 adds `Array.of` making arrays a pointed functor. +Suatu objek dengan sebuah fungsi `of` yang mengambil _semua_ nilai tunggal +ke dalamnya. + +ES2015 menambahkan `Array.of` yang menjadikannya _pointed functor_. + ```js Array.of(1) // [1] @@ -438,22 +543,30 @@ Array.of(1) // [1] ## Lift -Lifting is when you take a value and put it into an object like a [functor](#pointed-functor). If you lift a function into an [Applicative Functor](#applicative-functor) then you can make it work on values that are also in that functor. +_Lifting_ atau mengangkat (dari kata _lift_, angkat) adalah saat Anda +mengambil sebuah nilai dan mengambilnya ke dalam suatu objek seperti +[functor](#pointed-functor). Jika Anda mengangkat sebuah fungsi ke dalam +[Applicative Functor](#applicative-functor), maka Anda dapat membuatnya +bekerja pada nilai-nilai yang juga ada di _functor_ itu. + +Beberapa implementasi memiliki fungsi yang disebut `lift`, atau `liftA2` agar +lebih mudah menjalankan fungsi pada _functor_. -Some implementations have a function called `lift`, or `liftA2` to make it easier to run functions on functors. ```js -const liftA2 = (f) => (a, b) => a.map(f).ap(b) // note it's `ap` and not `map`. +const liftA2 = (f) => (a, b) => a.map(f).ap(b) // catatan: itu `ap`, bukan `map`. const mult = a => b => a * b -const liftedMult = liftA2(mult) // this function now works on functors like array +const liftedMult = liftA2(mult) // fungsi ini sekarang bekerja pada functor seperti array liftedMult([1, 2], [3]) // [3, 6] liftA2(a => b => a + b)([1, 2], [3, 4]) // [4, 5, 5, 6] ``` -Lifting a one-argument function and applying it does the same thing as `map`. +Mengangkat fungsi satu argumen dan menerapkannya melakukan hal yang sama +seperti `map`. + ```js const increment = (x) => x + 1 @@ -462,28 +575,30 @@ lift(increment)([2]) // [3] ;[2].map(increment) // [3] ``` - ## Referential Transparency -An expression that can be replaced with its value without changing the -behavior of the program is said to be referentially transparent. +Sebuah ekspresi yang dapat diganti nilainya dengan tanpa mengubah tingkah laku +program tersebut dikatan _referentially_ transparan. + +Katakanlah kita memiliki fungsi `greet`: -Say we have function greet: ```js const greet = () => 'Hello World!' ``` -Any invocation of `greet()` can be replaced with `Hello World!` hence greet is -referentially transparent. +Setiap seruan dari `greet()` dapat ditimpa dengan `Hello World!`, karena itu +`greet` secara referensial transparan. ## Equational Reasoning -When an application is composed of expressions and devoid of side effects, truths about the system can be derived from the parts. +Ketika sebuah aplikasi terdiri dari ekspresi dan tanpa efek samping, +kebenaran tentang sistem dapat diturunkan dari bagian-bagiannya. ## Lambda -An anonymous function that can be treated like a value. +Fungsi anonim yang dapat diperlakukan seperti sebuah nilai. + ```js ;(function (a) { @@ -492,24 +607,33 @@ An anonymous function that can be treated like a value. ;(a) => a + 1 ``` -Lambdas are often passed as arguments to Higher-Order functions. + +_Lambda_ juga sering dilewatkan sebagai argumen ke _Higher-Order function_. + ```js [1, 2].map((a) => a + 1) // [2, 3] ``` -You can assign a lambda to a variable. +Anda dapat menugaskan (_assign_) suatu _lambda_ ke dalam sebuah variabel. + ```js const add1 = (a) => a + 1 ``` ## Lambda Calculus -A branch of mathematics that uses functions to create a [universal model of computation](https://en.wikipedia.org/wiki/Lambda_calculus). + +Sebuah cabang dari matematika yang menggunakan fungsi untuk membuat suatu +[model universal dari komputasi](https://en.wikipedia.org/wiki/Lambda_calculus). ## Lazy evaluation -Lazy evaluation is a call-by-need evaluation mechanism that delays the evaluation of an expression until its value is needed. In functional languages, this allows for structures like infinite lists, which would not normally be available in an imperative language where the sequencing of commands is significant. +_Lazy evaluation_ adalah mekanisme evaluasi panggilan-per-kebutuhan yang +menunda evaluasi suatu ekspresi sampai nilainya dibutuhkan. Dalam bahasa +fungsional, ini memungkinkan struktur seperti _infinite list_, yang biasanya +tidak tersedia dalam bahasa imperatif dimana urutan perintah sangat penting. + ```js const rand = function*() { @@ -521,79 +645,97 @@ const rand = function*() { ```js const randIter = rand() -randIter.next() // Each execution gives a random value, expression is evaluated on need. +randIter.next() // Setiap eksekusi memberikan nilai acak, ekspresi dievaluasi hanya saat dibutuhkan ``` ## Monoid -An object with a function that "combines" that object with another of the same type. +Objek dengan fungsi yang "menggabungkan" objek itu sendiri dengan tipe lain +yang sama. + +Salah satu _monoid_ sederhana adalah penjumlahan angka: -One simple monoid is the addition of numbers: ```js 1 + 1 // 2 ``` -In this case number is the object and `+` is the function. -An "identity" value must also exist that when combined with a value doesn't change it. +Dalam kasus ini, angka adalah objek dan `+` adalah fungsi. + +Nilai "identitas" juga harus ada bila dikombinasikan dengan nilai yang tidak +mengubahnya. + +Nilai identitas untuk penjumlahan adalah `0`. + -The identity value for addition is `0`. ```js 1 + 0 // 1 ``` -It's also required that the grouping of operations will not affect the result (associativity): +Ini juga memerlukan pengelompokkan operasi yang tidak akan mempengaruhi +hasilnya (asosiatif): + ```js 1 + (2 + 3) === (1 + 2) + 3 // true ``` -Array concatenation also forms a monoid: +Rangkaian _array_ juga membentuk _monoid_: + ```js ;[1, 2].concat([3, 4]) // [1, 2, 3, 4] ``` -The identity value is empty array `[]` +Nilai identitasnya adalah _array_ kosong atau `[]`. + ```js ;[1, 2].concat([]) // [1, 2] ``` -If identity and compose functions are provided, functions themselves form a monoid: +Jika fungsi identitas dan komposisi disediakan, maka fungsinya membentuk monoid: + ```js const identity = (a) => a const compose = (f, g) => (x) => f(g(x)) ``` -`foo` is any function that takes one argument. + +`foo` adalah fungsi apapun yang mengambil satu argumen. + + ``` compose(foo, identity) ≍ compose(identity, foo) ≍ foo ``` ## Monad -A monad is an object with [`of`](#pointed-functor) and `chain` functions. `chain` is like [`map`](#functor) except it un-nests the resulting nested object. +_Monad_ adalah sebuah objek dengan fungsi [`of`](#pointed-functor) dan `chain`. +`chain` ini seperti [`map`](#functor), kecuali itu "membatalkan" objek +bersarang yang dihasilkan. + ```js -// Implementation +// Implementasi Array.prototype.chain = function (f) { return this.reduce((acc, it) => acc.concat(f(it)), []) } -// Usage +// Penggunaan ;Array.of('cat,dog', 'fish,bird').chain((a) => a.split(',')) // ['cat', 'dog', 'fish', 'bird'] -// Contrast to map +// Kontras ke map ;Array.of('cat,dog', 'fish,bird').map((a) => a.split(',')) // [['cat', 'dog'], ['fish', 'bird']] ``` -`of` is also known as `return` in other functional languages. -`chain` is also known as `flatmap` and `bind` in other languages. +`of` juga diketahui sebagai `return` di bahasa fungsional lainnya. +`chain` juga diketahui sebagai `flatmap` dan `bind` di bahasa lainnya. ## Comonad -An object that has `extract` and `extend` functions. +Suatu objek yang memiliki fungsi `extract` dan `extend`. + ```js const CoIdentity = (v) => ({ @@ -607,13 +749,16 @@ const CoIdentity = (v) => ({ }) ``` -Extract takes a value out of a functor. +`extract` mengambil sebuah nilai keluar dari _functor_. + ```js CoIdentity(1).extract() // 1 ``` -Extend runs a function on the comonad. The function should return the same type as the comonad. +_extend_ menjalankan fungsi di atas _comonad_. Fungsi tersebut seharusnya +mengembalikan tipe yang sama dengan _comonad_. + ```js CoIdentity(1).extend((co) => co.extract() + 1) // CoIdentity(2) @@ -621,32 +766,38 @@ CoIdentity(1).extend((co) => co.extract() + 1) // CoIdentity(2) ## Applicative Functor -An applicative functor is an object with an `ap` function. `ap` applies a function in the object to a value in another object of the same type. +Suatu _applicative functor_ adalah sebuah objek dengan fungsi `ap`. `ap` +menerapkan fungsi pada objek ke nilai objek lain dari tipe yang sama. + ```js -// Implementation +// Implementasi Array.prototype.ap = function (xs) { return this.reduce((acc, f) => acc.concat(xs.map(f)), []) } -// Example usage +// Contoh penggunaan ;[(a) => a + 1].ap([1]) // [2] ``` -This is useful if you have two objects and you want to apply a binary function to their contents. +Ini berguna jika Anda memiliki dua objek dan Anda ingin menerapkan fungsi biner +ke isinya. + ```js -// Arrays that you want to combine +// Array yang ingin digabungkan const arg1 = [1, 3] const arg2 = [4, 5] -// combining function - must be curried for this to work +// menggabungkan fungsi - harus curried untuk pekerjaan ini const add = (x) => (y) => x + y const partiallyAppliedAdds = [add].ap(arg1) // [(y) => 1 + y, (y) => 3 + y] ``` -This gives you an array of functions that you can call `ap` on to get the result: +Ini memberi Anda sebuah _array_ dari sejumlah fungsi yang dapat Anda sebut `ap` +untuk mendapatkan hasilnya: + ```js partiallyAppliedAdds.ap(arg2) // [5, 6, 7, 8] @@ -654,11 +805,12 @@ partiallyAppliedAdds.ap(arg2) // [5, 6, 7, 8] ## Morphism -A transformation function. +Sebuah fungsi transformasi. ### Endomorphism -A function where the input type is the same as the output. +Sebuah fungsi dimana tipe masukannya sama dengan keluarannya. + ```js // uppercase :: String -> String @@ -670,12 +822,15 @@ const decrement = (x) => x - 1 ### Isomorphism -A pair of transformations between 2 types of objects that is structural in nature and no data is lost. +Sepasang transformasi antara dua jenis benda yang bersifat struktural dan tidak +ada data yang hilang. + +Sebagai contoh, koordinat 2D dapat disimpan sebagai _array_ `[2, 3]` atau objek +`{x: 2, y: 3}`. -For example, 2D coordinates could be stored as an array `[2,3]` or object `{x: 2, y: 3}`. ```js -// Providing functions to convert in both directions makes them isomorphic. +// Menyediakan fungsi untuk mengubah kedua arah membuat mereka isomorfik const pairToCoords = (pair) => ({x: pair[0], y: pair[1]}) const coordsToPair = (coords) => [coords.x, coords.y] @@ -685,13 +840,13 @@ coordsToPair(pairToCoords([1, 2])) // [1, 2] pairToCoords(coordsToPair({x: 1, y: 2})) // {x: 1, y: 2} ``` - - ## Setoid -An object that has an `equals` function which can be used to compare other objects of the same type. +Suatu objek yang memiliki fungsi `equals` yang mana dapat digunakan untuk +membandingkan objek lain dengan tipe yang sama. + +Menjadikan _array_ suatu _setoid_: -Make array a setoid: ```js Array.prototype.equals = function (arr) { @@ -713,7 +868,9 @@ Array.prototype.equals = function (arr) { ## Semigroup -An object that has a `concat` function that combines it with another object of the same type. +Suatu objek yang memiliki fungsi `concat` yang menggabungkannya dengan objek +lain dengan tipe yang sama. + ```js ;[1].concat([2]) // [1, 2] @@ -721,18 +878,23 @@ An object that has a `concat` function that combines it with another object of t ## Foldable -An object that has a `reduce` function that can transform that object into some other type. +Suatu objek yang memiliki fungsi `reduce` yang dapat mengubah objek tersebut +menjadi tipe yang lain. + ```js const sum = (list) => list.reduce((acc, val) => acc + val, 0) sum([1, 2, 3]) // 6 ``` -## Type Signatures +## Type Signature -Often functions in JavaScript will include comments that indicate the types of their arguments and return values. +Seringkali fungsi dalam JavaScript memiliki komentar yang menunjukkan tipe dari +argumen dan nilai pengembaliannya. + +Ada sedikit perbedaan di antara komunitas/masyarakat, namun mereka sering +mengikuti pola berikut: -There's quite a bit of variance across the community but they often follow the following patterns: ```js // functionName :: firstArgType -> secondArgType -> returnType @@ -744,66 +906,95 @@ const add = (x) => (y) => x + y const increment = (x) => x + 1 ``` -If a function accepts another function as an argument it is wrapped in parentheses. +Jika suatu fungsi menerima fungsi lain sebagai argumennya, maka itu dibungkus +dengan tanda kurung. + ```js // call :: (a -> b) -> a -> b const call = (f) => (x) => f(x) ``` -The letters `a`, `b`, `c`, `d` are used to signify that the argument can be of any type. The following version of `map` takes a function that transforms a value of some type `a` into another type `b`, an array of values of type `a`, and returns an array of values of type `b`. +Huruf `a`, `b`, `c`, `d` digunakan sebagai tanda bahwa argumen tersebut dapat +berbentuk apa saja. Layaknya versi dari `map`, mengambil sebuah fungsi +yang mengubah nilai dari bentuk `a` ke bentuk lain `b`, sebuah _array_ dengan +nilai berbentuk `a`, dan mengembalikan sebuah _array_ dengan nilai berbentuk +`b`. + ```js // map :: (a -> b) -> [a] -> [b] const map = (f) => (list) => list.map(f) ``` -__Further reading__ +__Bacan lebih lanjut__ * [Ramda's type signatures](https://github.com/ramda/ramda/wiki/Type-Signatures) * [Mostly Adequate Guide](https://drboolean.gitbooks.io/mostly-adequate-guide/content/ch7.html#whats-your-type) -* [What is Hindley-Milner?](http://stackoverflow.com/a/399392/22425) on Stack Overflow +* [What is Hindley-Milner?](http://stackoverflow.com/a/399392/22425) di Stack Overflow ## Algebraic data type -A composite type made from putting other types together. Two common classes of algebraic types are [sum](#sum-type) and [product](#product-type). + +Jenis komposit yang dibuat dari jenis lainnya. Dua kelas umum dari tipe aljabar +(_algebraic type_) adalah [_sum_](#sum-type) dan [_product_](#product-type). ### Sum type -A Sum type is the combination of two types together into another one. It is called sum because the number of possible values in the result type is the sum of the input types. -JavaScript doesn't have types like this but we can use `Set`s to pretend: +_Sum type_ adalah kombinasi dari dua _type_ menjadi satu sama lain. Ini disebut +jumlah (_sum_) karena jumlah nilai yang mungkin terjadi pada _type_ hasil +adalah jumlah dari tipe masukan. + +JavaScript tidak memiliki _type_ seperti ini, tapi kita dapat menggunakan `Set` +untuk berpura-pura: + + ```js -// imagine that rather than sets here we have types that can only have these values +// bayangkan bahwa daripada Set di sini kita memiliki tipe yang hanya memiliki nilai-nilai ini const bools = new Set([true, false]) const halfTrue = new Set(['half-true']) -// The weakLogic type contains the sum of the values from bools and halfTrue +// Tipe `weakLogic` mengandung jumlah nilai dari `bools` dan `halfTrue` const weakLogicValues = new Set([...bools, ...halfTrue]) ``` -Sum types are sometimes called union types, discriminated unions, or tagged unions. +_Sum type_ terkadang disebut _union type_, _discriminated union_, atau _tagged +union_. -There's a [couple](https://github.com/paldepind/union-type) [libraries](https://github.com/puffnfresh/daggy) in JS which help with defining and using union types. +Ada [beberapa](https://github.com/paldepind/union-type) +[pustaka](https://github.com/puffnfresh/daggy) dalam JavaScript yang +membantu mendefinisikan dan menggunakan _union type_. -Flow includes [union types](https://flow.org/en/docs/types/unions/) and TypeScript has [Enums](https://www.typescriptlang.org/docs/handbook/enums.html) to serve the same role. +_Flow_ memasukkan [_union type_](https://flow.org/en/docs/types/unions/) dan +TypeScript memiliki +[Enums](https://www.typescriptlang.org/docs/handbook/enums.html) untuk melayani +peran yang sama. ### Product type -A **product** type combines types together in a way you're probably more familiar with: +Tipe ***product*** menggabungkan beberapa tipe bersama, dengan cara yang mungkin +Anda telah akrab: ```js // point :: (Number, Number) -> {x: Number, y: Number} const point = (x, y) => ({x: x, y: y}) ``` -It's called a product because the total possible values of the data structure is the product of the different values. Many languages have a tuple type which is the simplest formulation of a product type. -See also [Set theory](https://en.wikipedia.org/wiki/Set_theory). +Ini disebut produk (_product_) karena nilai total dari struktur data adalah +produk dari nilai yang berbeda. Banyak bahasa memiliki tipe _tuple_ yang +merupakan formulasi sederhana dari _product type_. + +Lihat juga [teori himpunan](https://id.wikipedia.org/wiki/Teori_himpunan). ## Option -Option is a [sum type](#sum-type) with two cases often called `Some` and `None`. -Option is useful for composing functions that might not return a value. +_Option_ adalah suatu _[sum type](#sum-type)_ dengan dua kasus yang sering +disebut `Some` dan `None`. + +_Option_ sangat berguna untuk menyusun fungsi-fungsi yang mungkin tidak +mengembalikan sebuah nilai. + ```js -// Naive definition +// Definisi naif const Some = (v) => ({ val: v, @@ -827,7 +1018,10 @@ const None = () => ({ // maybeProp :: (String, {a}) -> Option a const maybeProp = (key, obj) => typeof obj[key] === 'undefined' ? None() : Some(obj[key]) ``` -Use `chain` to sequence functions that return `Option`s + +Gunakan `chain` untuk mengurutkan fungsi yang mengembalikan `Option`. + + ```js // getItem :: Cart -> Option CartItem @@ -844,9 +1038,10 @@ getNestedPrice({item: {foo: 1}}) // None() getNestedPrice({item: {price: 9.99}}) // Some(9.99) ``` -`Option` is also known as `Maybe`. `Some` is sometimes called `Just`. `None` is sometimes called `Nothing`. +`Option` juga dikenal sebagai `Maybe`. `Some` terkadang disebut `Just`. +`None` terkadang disebut `Nothing`. -## Functional Programming Libraries in JavaScript +## Pustaka Pemrograman Fungsional dalam JavaScript * [mori](https://github.com/swannodette/mori) * [Immutable](https://github.com/facebook/immutable-js/) @@ -862,4 +1057,8 @@ getNestedPrice({item: {price: 9.99}}) // Some(9.99) --- -__P.S:__ This repo is successful due to the wonderful [contributions](https://github.com/hemanth/functional-programming-jargon/graphs/contributors)! +__P.S:__ _Repository_ ini di-_fork_ dari proyek +[_Functional Programming Jargon_](https://github.com/hemanth/functional-programming-jargon/) +milik [hemanth](https://github.com/hemanth/) dan telah dikatakan berhasil karena +[kontribusi](https://github.com/hemanth/functional-programming-jargon/graphs/contributors) +yang luar biasa. From aed87fef7f3ba665df57cb0d789ce1b1ecdbc6e3 Mon Sep 17 00:00:00 2001 From: Wisnu Adi Nurcahyo Date: Thu, 15 Jun 2017 18:17:10 +0700 Subject: [PATCH 10/43] Rollback file and add a link of Bahasa Indonesia translation --- contributing.md | 34 ++- package.json | 12 +- readme.md | 549 ++++++++++++++++-------------------------------- 3 files changed, 210 insertions(+), 385 deletions(-) diff --git a/contributing.md b/contributing.md index a04a54a..138a49a 100644 --- a/contributing.md +++ b/contributing.md @@ -1,7 +1,29 @@ -# Berkontribusi +# Contributing -Proyek ini berkembang seiring dengan berkembangnya konten dari -[_Functional Programming Jargon_](https://github.com/hemanth/functional-programming-jargon/) -milik [hemanth](https://github.com/hemanth/). Maka dari itu sebaiknya Anda -berkontribusi langsung ke _repository_ tersebut. Akan tetapi, kontribusi dalam -bentuk apapun ke _repository_ ini sangat dipersilakan. +This project is a work in progress. Contributions are very welcome. + +## Hard rules +* Run `npm test` to lint the code examples. Your changes must pass. +* If you add a new definition or reorder them run `npm run toc` to regenerate the table of contents. + +That said, we'd like to maintain some consistency across the document. + +## Style guide +1. Every definition should include at least one JavaScript code example. +1. Definitions should be written using the simplest language possible. Every word should tell. +1. Target programmers that have no functional programming experience. +1. We value understandability more than accuracy. e.g. It's okay to describe a functor as a container. +1. Don't overuse jargon even if defined elsewhere in the document. +1. Link to terms defined in the document when you use them in a definition. +1. Avoid big walls of text + +## Code conventions +[![JavaScript Style Guide](https://cdn.rawgit.com/feross/standard/master/badge.svg)](https://github.com/feross/standard) + +* Be consistent with other examples +* Prefer arrow functions +* Parenthesis around function arguments +* Put output values in comments +* Keep it short and simple + +This styleguide is a WIP too! Send PRs :) diff --git a/package.json b/package.json index 0379bbc..e7cfe68 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { - "name": "jargon-pemrograman-fungsional", + "name": "functional-programming-jargons", "version": "1.0.0", - "description": "Jargon dari dunia pemrograman fungsional secara sederhana!", + "description": "Jargon from the functional programming world in simple terms!", "main": "index.js", "scripts": { "test": "eslint readme.md", @@ -9,14 +9,14 @@ }, "repository": { "type": "git", - "url": "git+https://github.com/wisn/jargon-pemrograman-fungsional.git" + "url": "git+https://github.com/hemanth/functional-programming-jargon.git" }, - "author": "wisn", + "author": "hemanth", "license": "MIT", "bugs": { - "url": "https://github.com/wisn/jargon-pemrograman-fungsional/issues" + "url": "https://github.com/hemanth/functional-programming-jargon/issues" }, - "homepage": "https://github.com/wisn/jargon-pemrograman-fungsional#readme", + "homepage": "https://github.com/hemanth/functional-programming-jargon#readme", "devDependencies": { "eslint": "^3.4.0", "eslint-config-standard": "^6.0.0", diff --git a/readme.md b/readme.md index 126080e..44c46ce 100644 --- a/readme.md +++ b/readme.md @@ -1,24 +1,20 @@ -# Jargon Pemrograman Fungsional +# Functional Programming Jargon -_Functional programming_ (FP) atau pemrograman fungsional memberikan banyak -keuntungan, dan kini popularitasnya telah meningkat sebagai hasilnya. Namun, -setiap paradigma pemrograman datang dengan jargon uniknya masing-masing -dan FP tidak terkecuali. Dengan memberikan glosarium, -kami berharap dapat mempermudah belajar FP. +Functional programming (FP) provides many advantages, and its popularity has been increasing as a result. However, each programming paradigm comes with its own unique jargon and FP is no exception. By providing a glossary, we hope to make learning FP easier. -Contoh yang ada disajikan dalam JavaScript (ES2015). -[Kenapa JavaScript?](https://github.com/hemanth/functional-programming-jargon/wiki/Why-JavaScript%3F) +Examples are presented in JavaScript (ES2015). [Why JavaScript?](https://github.com/hemanth/functional-programming-jargon/wiki/Why-JavaScript%3F) -*Ini adalah sebuah -[WIP](https://github.com/hemanth/functional-programming-jargon/issues/20) -dari -[Functional Programming Jargon](https://github.com/hemanth/functional-programming-jargon/) -milik [hemanth](https://github.com/hemanth/); Jangan ragu untuk mengirim PR ;)* +*This is a [WIP](https://github.com/hemanth/functional-programming-jargon/issues/20); please feel free to send a PR ;)* -Jika ada, dokumen ini menggunakan istilah yang didefinisikan dalam spesifikasi -[Fantasy Land](https://github.com/fantasyland/fantasy-land). +Where applicable, this document uses terms defined in the [Fantasy Land spec](https://github.com/fantasyland/fantasy-land) -__Daftar Isi__ +__Translations__ +* [Portuguese](https://github.com/alexmoreno/jargoes-programacao-funcional) +* [Spanish](https://github.com/idcmardelplata/functional-programming-jargon/tree/master) +* [Chinese](https://github.com/shfshanyue/fp-jargon-zh) +* [Bahasa Indonesia](https://github.com/wisn/jargon-pemrograman-fungsional) + +__Table of Contents__ * [Arity](#arity) @@ -30,11 +26,11 @@ __Daftar Isi__ * [Function Composition](#function-composition) * [Continuation](#continuation) * [Purity](#purity) -* [Side Effect](#side-effects) +* [Side effects](#side-effects) * [Idempotent](#idempotent) * [Point-Free Style](#point-free-style) * [Predicate](#predicate) -* [Contract](#contract) +* [Contracts](#contracts) * [Category](#category) * [Value](#value) * [Constant](#constant) @@ -56,29 +52,19 @@ __Daftar Isi__ * [Setoid](#setoid) * [Semigroup](#semigroup) * [Foldable](#foldable) -* [Type Signature](#type-signature) +* [Type Signatures](#type-signatures) * [Algebraic data type](#algebraic-data-type) * [Sum type](#sum-type) * [Product type](#product-type) * [Option](#option) -* [Pustaka Pemrograman Fungsional dalam JavaScript](#pustaka-pemrograman-fungsional-dalam-javascript) +* [Functional Programming Libraries in JavaScript](#functional-programming-libraries-in-javascript) ## Arity -_Arity_ merupakan banyaknya argumen yang diambil oleh fungsi. -Berasal dari kata-kata seperti _unary_, _binary_, _ternary_, dan lain-lain. -Kata ini memiliki perbedaan yang terdiri dari dua sufiks, "-ary" dan "-ity." -Penjumlahan, misalnya, mengambil dua argumen, dan jadi didefinisikan sebagai -fungsi biner (_binary function_) atau fungsi dengan dua _arity_. -Fungsi semacam itu terkadang disebut "_dyadic_" oleh orang-orang yang lebih -menyukai bahasa Yunani dari bahasa Latin. -Demikian juga, fungsi yang mengambil sejumlah variabel argumen disebut -"_variadic_", sedangkan fungsi biner harus diberikan dua dan hanya dua -argumen, meskipun _currying_ dan _partial application_ (lihat di bawah). - +The number of arguments a function takes. From words like unary, binary, ternary, etc. This word has the distinction of being composed of two suffixes, "-ary" and "-ity." Addition, for example, takes two arguments, and so it is defined as a binary function or a function with an arity of two. Such a function may sometimes be called "dyadic" by people who prefer Greek roots to Latin. Likewise, a function that takes a variable number of arguments is called "variadic," whereas a binary function must be given two and only two arguments, currying and partial application notwithstanding (see below). ```js const sum = (a, b) => a + b @@ -86,14 +72,12 @@ const sum = (a, b) => a + b const arity = sum.length console.log(arity) // 2 -// Arity dari fungsi `sum` adalah dua +// The arity of sum is 2 ``` ## Higher-Order Functions (HOF) -_Higher-Order Function_ adalah sebuah fungsi yang mengambil fungsi sebagai -argumen dan/atau mengembalikan sebuah fungsi. - +A function which takes a function as an argument and/or returns a function. ```js const filter = (predicate, xs) => xs.filter(predicate) @@ -109,50 +93,40 @@ filter(is(Number), [0, '1', 2, null]) // [0, 2] ## Partial Application -Menerapkan fungsi secara parsial (_Partial Application_ atau Fungsi Parsial) -artinya membuat fungsi baru dengan mengisi beberapa argumen ke fungsi semula. +Partially applying a function means creating a new function by pre-filling some of the arguments to the original function. ```js -// Helper membuat sebagian fungsi yang diaplikasikan -// Mengambil sebuah fungsi dan beberapa argumen +// Helper to create partially applied functions +// Takes a function and some arguments const partial = (f, ...args) => - // mengembalikan sebuah fungsi yang mengambil sisa argumen + // returns a function that takes the rest of the arguments (...moreArgs) => - // dan memanggil fungsi asilnya dengan semuanya + // and calls the original function with all of them f(...args, ...moreArgs) -// Sesuatu untuk diaplikasikan +// Something to apply const add3 = (a, b, c) => a + b + c -// Menerapkan `2` dan `3` secara parsial ke `add3` -// Sehingga, memberikan Anda sebuah fungsi dengan satu argumen +// Partially applying `2` and `3` to `add3` gives you a one-argument function const fivePlus = partial(add3, 2, 3) // (c) => 2 + 3 + c fivePlus(4) // 9 ``` -Anda juga dapat menggunakan `Function.prototype.bind` untuk menerapkan -fungsi parsial di JavaScript: - +You can also use `Function.prototype.bind` to partially apply a function in JS: ```js const add1More = add3.bind(null, 2, 3) // (c) => 2 + 3 + c ``` -_Partial application_ atau fungsi parsial membantu menciptakan fungsi yang -lebih sederhana dari yang lebih kompleks dengan memadukan data saat Anda -memilikinya. [_Curried_](#currying) _function_ sudah secara otomatis diterapkan -secara parsial. +Partial application helps create simpler functions from more complex ones by baking in data when you have it. [Curried](#currying) functions are automatically partially applied. ## Currying -_Currying_ merupakan sebuah proses mengubah fungsi yang membutuhkan banyak -argumen menjadi fungsi yang membawa mereka satu-persatu. - -Setiap kali fungsi dipanggil hanya menerima satu argumen dan mengembalikan -sebuah fungsi yang membutuhkan satu argumen sampai semua argumen dilewatkan. +The process of converting a function that takes multiple arguments into a function that takes them one at a time. +Each time the function is called it only accepts one argument and returns a function that takes one argument until all arguments are passed. ```js const sum = (a, b) => a + b @@ -169,66 +143,39 @@ add2(10) // 12 ## Closure -_Closure_ merupakan sebuah cara untuk mengakses sebuah variabel yang berada -di luar cakupannya. -Secara formal, _closure_ merupakan sebuah teknik untuk menerapkan _lexically -scoped_ bernama _binding_. Ini adalah cara untuk menyimpan sebuah fungsi -dengan sebuah _environment_. +A closure is a way of accessing a variable outside its scope. +Formally, a closure is a technique for implementing lexically scoped named binding. It is a way of storing a function with an environment. -_Closure_ adalah lingkup yang menangkap variabel lokal dari suatu fungsi untuk -askes bahkan setelah eksekusi telah berpindah dari blok yang didefinisikan. -Yaitu, mereka membiarkan referensi lingkup setelah blok dimana variabel -dinyatakan telah selesai mengeksekusi. +A closure is a scope which captures local variables of a function for access even after the execution has moved out of the block in which it is defined. +ie. they allow referencing a scope after the block in which the variables were declared has finished executing. ```js const addTo = x => y => x + y var addToFive = addTo(5) -addToFive(3) // mengembalikan 8 +addToFive(3) // returns 8 ``` +The function ```addTo()``` returns a function(internally called ```add()```), lets store it in a variable called ```addToFive``` with a curried call having parameter 5. -Fungsi `addTo()` mengembalikan sebuah fungsi (secara internal disebut `add()`), -lalu disimpan di variabel yang disebut `addToFive` dengan _curried call_ yang -memiliki parameter `5`. +Ideally, when the function ```addTo``` finishes execution, its scope, with local variables add, x, y should not be accessible. But, it returns 8 on calling ```addToFive()```. This means that the state of the function ```addTo``` is saved even after the block of code has finished executing, otherwise there is no way of knowing that ```addTo``` was called as ```addTo(5)``` and the value of x was set to 5. -Idealnya, ketika fungsi `addTo` selesai dieksekusi, cakupannya, -dengan variabel lokal `add`, `x`, `y` seharusnya tidak dapat diakses. Tapi, -itu mengembalikan `8` ketika memanggil `addToFive()`. Ini artinya kondisi -dari fungsi `addTo` disimpan bahkan setelah blok kode selesai dieksekusi. -Jika tidak, tidak mungkin dapat mengetahui bahwa `addTo` telah dipanggil -sebagai `addTo(5)` dan nilai dari `x` telah ditentukan menjadi `5`. +Lexical scoping is the reason why it is able to find the values of x and add - the private variables of the parent which has finished executing. This value is called a Closure. -_Lexical scoping_ adalah alasan mengapa ia dapat menemukan nilai dari `x` dan -`add` - sebuah variabel _private_ induk yang telah selesai dieksekusi. -Nilai ini disebut _Closure_. +The stack along with the lexical scope of the function is stored in form of reference to the parent. This prevents the closure and the underlying variables from being garbage collected(since there is at least one live reference to it). -`Stack` beserta `lexical scope` fungsinya disimpan dalam bentuk referensi -ke induknya. Hal ini mencegah _closure_ dan variabel-variabel mendasar agar -tidak dikumpulkan sebagai sampah (karena setidaknya ada satu refernsi -langsung untuk itu). +Lambda Vs Closure: A lambda is essentially a function that is defined inline rather than the standard method of declaring functions. Lambdas can frequently be passed around as objects. -__Lambda Vs. Closure__ -_Lambda_ pada dasarnya adalah fungsi yang didefinisikan secara _inline_ -daripada metode standar untuk mendeklarasikan fungsi. Lambda sering dapat -dilewatkan sebagai objek. - -_Closure_ adalah fungsi yang membungkus keadaan sekitarnya dengan -mereferensikan bidang yang ada di luar tubuhnya. _State_ tertutup tetap -berada di seberang seruan _closure_. +A closure is a function that encloses its surrounding state by referencing fields external to its body. The enclosed state remains across invocations of the closure. -__Bacaan lebih lanjut/Sumber__ +__Further reading/Sources__ * [Lambda Vs Closure](http://stackoverflow.com/questions/220658/what-is-the-difference-between-a-closure-and-a-lambda) * [How do JavaScript Closures Work?](http://stackoverflow.com/questions/111102/how-do-javascript-closures-work) ## Auto Currying +Transforming a function that takes multiple arguments into one that if given less than its correct number of arguments returns a function that takes the rest. When the function gets the correct number of arguments it is then evaluated. -_Auto currying_ mengubah fungsi yang membutuhkan banyak argumen menjadi -argumen yang jika diberikan kurang dari jumlah argumen yang benar mengembalikan -sebuah fungsi yang mengambil sisanya. Bila fungsi mendapatkan jumlah argumen -yang benar, maka akan dievaluasi. - -lodash dan Ramda memiliki fungsi `curry` yang bekerja seperti di bawah. +lodash & Ramda have a `curry` function that works this way. ```js const add = (x, y) => x + y @@ -239,28 +186,23 @@ curriedAdd(1) // (y) => 1 + y curriedAdd(1)(2) // 3 ``` -__Bacaan lebih lanjut__ +__Further reading__ * [Favoring Curry](http://fr.umio.us/favoring-curry/) * [Hey Underscore, You're Doing It Wrong!](https://www.youtube.com/watch?v=m3svKOdZijA) ## Function Composition -_Function composition_ atau komposisi fungsi adalah tindakan yang menempatkan -dua fungsi bersama untuk membentuk fungsi ketiga dimana keluaran dari satu -fungsi adalah masukan dari yang lain. - +The act of putting two functions together to form a third function where the output of one function is the input of the other. ```js -const compose = (f, g) => (a) => f(g(a)) // Definisi -const floorAndToString = compose((val) => val.toString(), Math.floor) // Penggunaan +const compose = (f, g) => (a) => f(g(a)) // Definition +const floorAndToString = compose((val) => val.toString(), Math.floor) // Usage floorAndToString(121.212121) // '121' ``` ## Continuation -Pada suatu titik dalam sebuah program, bagian dari kode yang belum dieksekusi -dikenal sebagai kelanjutan/kontinuitas atau _continuation_. - +At any given point in a program, the part of the code that's yet to be executed is known as a continuation. ```js const printAsString = (num) => console.log(`Given ${num}`) @@ -273,20 +215,16 @@ const addOneAndContinue = (num, cc) => { addOneAndContinue(2, printAsString) // 'Given 3' ``` -Kontinuitas sering terlihat pada pemrograman _asynchronous_ saat program -perlu menunggu untuk menerima data sebelum dapat melanjutkan. Responnya -sering dilewatkan ke sisa program, yang merupakan kelanjutannya, begitu -sudah diterima. - +Continuations are often seen in asynchronous programming when the program needs to wait to receive data before it can continue. The response is often passed off to the rest of the program, which is the continuation, once it's been received. ```js const continueProgramWith = (data) => { - // Melanjutkan program dengan data + // Continues program with data } readFileAsync('path/to/file', (err, response) => { if (err) { - // mengatasi galat + // handle error return } continueProgramWith(response) @@ -295,10 +233,8 @@ readFileAsync('path/to/file', (err, response) => { ## Purity -Sebuah fungsi dikatan murni atau _pure_ jika mengembalikan nilai yang hanya -ditentukan oleh nilai masukannya, dan tidak menghasilkan efek samping -atau _side effect_. - +A function is pure if the return value is only determined by its +input values, and does not produce side effects. ```js const greet = (name) => `Hi, ${name}` @@ -306,8 +242,7 @@ const greet = (name) => `Hi, ${name}` greet('Brianne') // 'Hi, Brianne' ``` -Berbeda dengan masing-masing hal di bawah: - +As opposed to each of the following: ```js window.name = 'Brianne' @@ -317,8 +252,7 @@ const greet = () => `Hi, ${window.name}` greet() // "Hi, Brianne" ``` -Contoh keluaran di atas didasarkan pada data yang tersimpan di luar fungsi... - +The above example's output is based on data stored outside of the function... ```js let greeting @@ -331,14 +265,11 @@ greet('Brianne') greeting // "Hi, Brianne" ``` -... dan yang satu ini memodifikasi keadaan di luar fungsi. +... and this one modifies state outside of the function. -## Side Effect - -Sebuah fungsi atau ekspresi dikatakan memiliki efek samping jika selain -mengembalikan nilai, ia berinterasksi dengan (membaca dari atau menulis ke) -keadaan yang dapat berubah eksternal. +## Side effects +A function or expression is said to have a side effect if apart from returning a value, it interacts with (reads from or writes to) external mutable state. ```js const differentEveryTime = new Date() @@ -350,9 +281,7 @@ console.log('IO is a side effect!') ## Idempotent -Suatu fungsi _idempotent_ jika mengaplikasikannya kembali hasilnya tidak -menghasilkan hasil yang berbeda. - +A function is idempotent if reapplying it to its result does not produce a different result. ``` f(f(x)) ≍ f(x) @@ -368,40 +297,28 @@ sort(sort(sort([2, 1]))) ## Point-Free Style -Menulis fungsi dimana definisi tidak secara eksplisit mengidentifikasi -argumen yang digunakan. Gaya ini biasanya memerlukan [_currying_](#currying) -atau lainnya [_Higher-Order function_](#higher-order-functions-hof). -Alias, _Tacit programming_. - +Writing functions where the definition does not explicitly identify the arguments used. This style usually requires [currying](#currying) or other [Higher-Order functions](#higher-order-functions-hof). A.K.A Tacit programming. ```js -// Diberikan +// Given const map = (fn) => (list) => list.map(fn) const add = (a) => (b) => a + b -// Lalu +// Then -// Bukan points-free - `numbers` merupakan argumen eksplisit +// Not points-free - `numbers` is an explicit argument const incrementAll = (numbers) => map(add(1))(numbers) -// Points-free - `list` merupakan argumen implisit +// Points-free - The list is an implicit argument const incrementAll2 = map(add(1)) ``` -`incrementAll` mengidentifikasi dan menggunakan parameter `numbers`, jadi itu -bukan _points-free_. `incrementAll2` dituliskan hanya dengan menggabungkan -beberapa fungsi dan beberapa nilai, membuatnya tidak menyebut satu pun -argumennya. Itu __adalah__ _points-free_. +`incrementAll` identifies and uses the parameter `numbers`, so it is not points-free. `incrementAll2` is written just by combining functions and values, making no mention of its arguments. It __is__ points-free. -Definisi _points-free function_ terlihat seperti _assignment_ normal tanpa -`function` atau `=>`. +Points-free function definitions look just like normal assignments without `function` or `=>`. ## Predicate - -Suatu _predicate_ adalah sebuah fungsi yang mengembalikan nilai `true` atau -`false` untuk suatu nilai yang diberikan. Biasanya digunakan sebagai _callback_ -untuk menyaring _array_. - +A predicate is a function that returns true or false for a given value. A common use of a predicate is as the callback for array filter. ```js const predicate = (a) => a > 2 @@ -409,16 +326,12 @@ const predicate = (a) => a > 2 ;[1, 2, 3, 4].filter(predicate) // [3, 4] ``` -## Contract - -Suatu _contract_ menentukan kewajiban dan jaminan perilaku dari suatu fungsi -atau ekspresi saat _runtime_. Ini bertindak sebagai seperangkat aturan yang -diharapkan dari masukan dan keluaran suatu fungsi atau ekspresi, dan -kesalahan umumnya dilaporkan setiap kali sebuah kontrak dilanggar. +## Contracts +A contract specifies the obligations and guarantees of the behavior from a function or expression at runtime. This acts as a set of rules that are expected from the input and output of a function or expression, and errors are generally reported whenever a contract is violated. ```js -// Mendefinisikan contract kami : int -> int +// Define our contract : int -> int const contract = (input) => { if (typeof input === 'number') return true throw new Error('Contract violated: expected int -> int') @@ -432,34 +345,30 @@ addOne('some string') // Contract violated: expected int -> int ## Category -Kategori dalam _category theory_ adalah kumpulan objek dan morfisme -(_morphism_) di antara keduanya. Dalam pemrograman, biasanya _types_ bertindak -sebagai objek dan fungsi sebagai morfisme. +A category in category theory is a collection of objects and morphisms between them. In programming, typically types +act as the objects and functions as morphisms. +To be a valid category 3 rules must be met: -Untuk menjadi kategori yang sah, tiga aturan harus dipenuhi: +1. There must be an identity morphism that maps an object to itself. + Where `a` is an object in some category, + there must be a function from `a -> a`. +2. Morphisms must compose. + Where `a`, `b`, and `c` are objects in some category, + and `f` is a morphism from `a -> b`, and `g` is a morphism from `b -> c`; + `g(f(x))` must be equivalent to `(g • f)(x)`. +3. Composition must be associative + `f • (g • h)` is the same as `(f • g) • h` -1. Harus ada morfisme identitas yang memetakan objek itu sendiri. - Dimana `a` adalah sebuah objek dalam beberapa kategori, - harus ada fungsi dari `a -> a`. -2. Morfisme harus disusun. - Dimana `a`, `b`, dan `c` adalah objek dalam beberapa kategori, - dan `f` adalah morfisme dari `a -> b`, serta `g` adalah morfisme dari - `b -> c`; `g(f(x))` harus sama dengan `(g • f)(x)`. -3. Komposisi harus asosiatif. - `f • (g • h)` sama halnya dengan `(f • g) • h`. +Since these rules govern composition at very abstract level, category theory is great at uncovering new ways of composing things. -Karena aturan ini mengatur komposisi pada tingkat yang sangat abstrak, -teori kategori sangat bagus dalam menemukan cara baru untuk menyusun sesuatu. - -__Bacaan lebih lanjut__ +__Further reading__ * [Category Theory for Programmers](https://bartoszmilewski.com/2014/10/28/category-theory-for-programmers-the-preface/) ## Value -Apa saja yang dapat di-_assign_ ke variabel. - +Anything that can be assigned to a variable. ```js 5 @@ -471,20 +380,16 @@ undefined ## Constant -Sebuah variabel yang tidak dapat ditetapkan kembali setelah ditentukan nilainya. +A variable that cannot be reassigned once defined. ```js const five = 5 const john = Object.freeze({name: 'John', age: 30}) ``` -_Constant_ atau konstanta adalah -[_referentially transparent_](#referential-transparency). Artinya, mereka -dapat diganti dengan nilai yang mereka wakili tanpa mempengaruhi hasilnya. - -Dengan dua konstanta di atas, ekspresi berikut akan selalu mengembalikan -nilai `true`. +Constants are [referentially transparent](#referential-transparency). That is, they can be replaced with the values that they represent without affecting the result. +With the above two constants the following expression will always return `true`. ```js john.age + five === ({name: 'John', age: 30}).age + (5) @@ -492,10 +397,7 @@ john.age + five === ({name: 'John', age: 30}).age + (5) ## Functor -Suatu objek yang mengimplementasikan fungsi `map`, yang ketika menjalankan -lebih dari setiap nilai pada objek untuk menghasilkan objek baru, mematuhi -dua aturan: - +An object that implements a `map` function which, while running over each value in the object to produce a new object, adheres to two rules: __Preserves identity__ ``` @@ -508,18 +410,15 @@ __Composable__ object.map(compose(f, g)) ≍ object.map(g).map(f) ``` -(`f`, `g` menjadi fungsi sewenang-wenang) - -_Functor_ umum dalam JavaScript adalah `Array` karena mematuhi dua aturan -_functor_, yaitu: +(`f`, `g` be arbitrary functions) +A common functor in JavaScript is `Array` since it abides to the two functor rules: ```js [1, 2, 3].map(x => x) // = [1, 2, 3] ``` -dan - +and ```js const f = x => x + 1 @@ -530,12 +429,9 @@ const g = x => x * 2 ``` ## Pointed Functor +An object with an `of` function that puts _any_ single value into it. -Suatu objek dengan sebuah fungsi `of` yang mengambil _semua_ nilai tunggal -ke dalamnya. - -ES2015 menambahkan `Array.of` yang menjadikannya _pointed functor_. - +ES2015 adds `Array.of` making arrays a pointed functor. ```js Array.of(1) // [1] @@ -543,30 +439,22 @@ Array.of(1) // [1] ## Lift -_Lifting_ atau mengangkat (dari kata _lift_, angkat) adalah saat Anda -mengambil sebuah nilai dan mengambilnya ke dalam suatu objek seperti -[functor](#pointed-functor). Jika Anda mengangkat sebuah fungsi ke dalam -[Applicative Functor](#applicative-functor), maka Anda dapat membuatnya -bekerja pada nilai-nilai yang juga ada di _functor_ itu. - -Beberapa implementasi memiliki fungsi yang disebut `lift`, atau `liftA2` agar -lebih mudah menjalankan fungsi pada _functor_. +Lifting is when you take a value and put it into an object like a [functor](#pointed-functor). If you lift a function into an [Applicative Functor](#applicative-functor) then you can make it work on values that are also in that functor. +Some implementations have a function called `lift`, or `liftA2` to make it easier to run functions on functors. ```js -const liftA2 = (f) => (a, b) => a.map(f).ap(b) // catatan: itu `ap`, bukan `map`. +const liftA2 = (f) => (a, b) => a.map(f).ap(b) // note it's `ap` and not `map`. const mult = a => b => a * b -const liftedMult = liftA2(mult) // fungsi ini sekarang bekerja pada functor seperti array +const liftedMult = liftA2(mult) // this function now works on functors like array liftedMult([1, 2], [3]) // [3, 6] liftA2(a => b => a + b)([1, 2], [3, 4]) // [4, 5, 5, 6] ``` -Mengangkat fungsi satu argumen dan menerapkannya melakukan hal yang sama -seperti `map`. - +Lifting a one-argument function and applying it does the same thing as `map`. ```js const increment = (x) => x + 1 @@ -575,30 +463,28 @@ lift(increment)([2]) // [3] ;[2].map(increment) // [3] ``` + ## Referential Transparency -Sebuah ekspresi yang dapat diganti nilainya dengan tanpa mengubah tingkah laku -program tersebut dikatan _referentially_ transparan. - -Katakanlah kita memiliki fungsi `greet`: +An expression that can be replaced with its value without changing the +behavior of the program is said to be referentially transparent. +Say we have function greet: ```js const greet = () => 'Hello World!' ``` -Setiap seruan dari `greet()` dapat ditimpa dengan `Hello World!`, karena itu -`greet` secara referensial transparan. +Any invocation of `greet()` can be replaced with `Hello World!` hence greet is +referentially transparent. ## Equational Reasoning -Ketika sebuah aplikasi terdiri dari ekspresi dan tanpa efek samping, -kebenaran tentang sistem dapat diturunkan dari bagian-bagiannya. +When an application is composed of expressions and devoid of side effects, truths about the system can be derived from the parts. ## Lambda -Fungsi anonim yang dapat diperlakukan seperti sebuah nilai. - +An anonymous function that can be treated like a value. ```js ;(function (a) { @@ -607,33 +493,24 @@ Fungsi anonim yang dapat diperlakukan seperti sebuah nilai. ;(a) => a + 1 ``` - -_Lambda_ juga sering dilewatkan sebagai argumen ke _Higher-Order function_. - +Lambdas are often passed as arguments to Higher-Order functions. ```js [1, 2].map((a) => a + 1) // [2, 3] ``` -Anda dapat menugaskan (_assign_) suatu _lambda_ ke dalam sebuah variabel. - +You can assign a lambda to a variable. ```js const add1 = (a) => a + 1 ``` ## Lambda Calculus - -Sebuah cabang dari matematika yang menggunakan fungsi untuk membuat suatu -[model universal dari komputasi](https://en.wikipedia.org/wiki/Lambda_calculus). +A branch of mathematics that uses functions to create a [universal model of computation](https://en.wikipedia.org/wiki/Lambda_calculus). ## Lazy evaluation -_Lazy evaluation_ adalah mekanisme evaluasi panggilan-per-kebutuhan yang -menunda evaluasi suatu ekspresi sampai nilainya dibutuhkan. Dalam bahasa -fungsional, ini memungkinkan struktur seperti _infinite list_, yang biasanya -tidak tersedia dalam bahasa imperatif dimana urutan perintah sangat penting. - +Lazy evaluation is a call-by-need evaluation mechanism that delays the evaluation of an expression until its value is needed. In functional languages, this allows for structures like infinite lists, which would not normally be available in an imperative language where the sequencing of commands is significant. ```js const rand = function*() { @@ -645,97 +522,79 @@ const rand = function*() { ```js const randIter = rand() -randIter.next() // Setiap eksekusi memberikan nilai acak, ekspresi dievaluasi hanya saat dibutuhkan +randIter.next() // Each execution gives a random value, expression is evaluated on need. ``` ## Monoid -Objek dengan fungsi yang "menggabungkan" objek itu sendiri dengan tipe lain -yang sama. - -Salah satu _monoid_ sederhana adalah penjumlahan angka: +An object with a function that "combines" that object with another of the same type. +One simple monoid is the addition of numbers: ```js 1 + 1 // 2 ``` +In this case number is the object and `+` is the function. -Dalam kasus ini, angka adalah objek dan `+` adalah fungsi. - -Nilai "identitas" juga harus ada bila dikombinasikan dengan nilai yang tidak -mengubahnya. - -Nilai identitas untuk penjumlahan adalah `0`. - +An "identity" value must also exist that when combined with a value doesn't change it. +The identity value for addition is `0`. ```js 1 + 0 // 1 ``` -Ini juga memerlukan pengelompokkan operasi yang tidak akan mempengaruhi -hasilnya (asosiatif): - +It's also required that the grouping of operations will not affect the result (associativity): ```js 1 + (2 + 3) === (1 + 2) + 3 // true ``` -Rangkaian _array_ juga membentuk _monoid_: - +Array concatenation also forms a monoid: ```js ;[1, 2].concat([3, 4]) // [1, 2, 3, 4] ``` -Nilai identitasnya adalah _array_ kosong atau `[]`. - +The identity value is empty array `[]` ```js ;[1, 2].concat([]) // [1, 2] ``` -Jika fungsi identitas dan komposisi disediakan, maka fungsinya membentuk monoid: - +If identity and compose functions are provided, functions themselves form a monoid: ```js const identity = (a) => a const compose = (f, g) => (x) => f(g(x)) ``` - -`foo` adalah fungsi apapun yang mengambil satu argumen. - - +`foo` is any function that takes one argument. ``` compose(foo, identity) ≍ compose(identity, foo) ≍ foo ``` ## Monad -_Monad_ adalah sebuah objek dengan fungsi [`of`](#pointed-functor) dan `chain`. -`chain` ini seperti [`map`](#functor), kecuali itu "membatalkan" objek -bersarang yang dihasilkan. - +A monad is an object with [`of`](#pointed-functor) and `chain` functions. `chain` is like [`map`](#functor) except it un-nests the resulting nested object. ```js -// Implementasi +// Implementation Array.prototype.chain = function (f) { return this.reduce((acc, it) => acc.concat(f(it)), []) } -// Penggunaan +// Usage ;Array.of('cat,dog', 'fish,bird').chain((a) => a.split(',')) // ['cat', 'dog', 'fish', 'bird'] -// Kontras ke map +// Contrast to map ;Array.of('cat,dog', 'fish,bird').map((a) => a.split(',')) // [['cat', 'dog'], ['fish', 'bird']] ``` -`of` juga diketahui sebagai `return` di bahasa fungsional lainnya. -`chain` juga diketahui sebagai `flatmap` dan `bind` di bahasa lainnya. +`of` is also known as `return` in other functional languages. +`chain` is also known as `flatmap` and `bind` in other languages. ## Comonad -Suatu objek yang memiliki fungsi `extract` dan `extend`. - +An object that has `extract` and `extend` functions. ```js const CoIdentity = (v) => ({ @@ -749,16 +608,13 @@ const CoIdentity = (v) => ({ }) ``` -`extract` mengambil sebuah nilai keluar dari _functor_. - +Extract takes a value out of a functor. ```js CoIdentity(1).extract() // 1 ``` -_extend_ menjalankan fungsi di atas _comonad_. Fungsi tersebut seharusnya -mengembalikan tipe yang sama dengan _comonad_. - +Extend runs a function on the comonad. The function should return the same type as the comonad. ```js CoIdentity(1).extend((co) => co.extract() + 1) // CoIdentity(2) @@ -766,38 +622,32 @@ CoIdentity(1).extend((co) => co.extract() + 1) // CoIdentity(2) ## Applicative Functor -Suatu _applicative functor_ adalah sebuah objek dengan fungsi `ap`. `ap` -menerapkan fungsi pada objek ke nilai objek lain dari tipe yang sama. - +An applicative functor is an object with an `ap` function. `ap` applies a function in the object to a value in another object of the same type. ```js -// Implementasi +// Implementation Array.prototype.ap = function (xs) { return this.reduce((acc, f) => acc.concat(xs.map(f)), []) } -// Contoh penggunaan +// Example usage ;[(a) => a + 1].ap([1]) // [2] ``` -Ini berguna jika Anda memiliki dua objek dan Anda ingin menerapkan fungsi biner -ke isinya. - +This is useful if you have two objects and you want to apply a binary function to their contents. ```js -// Array yang ingin digabungkan +// Arrays that you want to combine const arg1 = [1, 3] const arg2 = [4, 5] -// menggabungkan fungsi - harus curried untuk pekerjaan ini +// combining function - must be curried for this to work const add = (x) => (y) => x + y const partiallyAppliedAdds = [add].ap(arg1) // [(y) => 1 + y, (y) => 3 + y] ``` -Ini memberi Anda sebuah _array_ dari sejumlah fungsi yang dapat Anda sebut `ap` -untuk mendapatkan hasilnya: - +This gives you an array of functions that you can call `ap` on to get the result: ```js partiallyAppliedAdds.ap(arg2) // [5, 6, 7, 8] @@ -805,12 +655,11 @@ partiallyAppliedAdds.ap(arg2) // [5, 6, 7, 8] ## Morphism -Sebuah fungsi transformasi. +A transformation function. ### Endomorphism -Sebuah fungsi dimana tipe masukannya sama dengan keluarannya. - +A function where the input type is the same as the output. ```js // uppercase :: String -> String @@ -822,15 +671,12 @@ const decrement = (x) => x - 1 ### Isomorphism -Sepasang transformasi antara dua jenis benda yang bersifat struktural dan tidak -ada data yang hilang. - -Sebagai contoh, koordinat 2D dapat disimpan sebagai _array_ `[2, 3]` atau objek -`{x: 2, y: 3}`. +A pair of transformations between 2 types of objects that is structural in nature and no data is lost. +For example, 2D coordinates could be stored as an array `[2,3]` or object `{x: 2, y: 3}`. ```js -// Menyediakan fungsi untuk mengubah kedua arah membuat mereka isomorfik +// Providing functions to convert in both directions makes them isomorphic. const pairToCoords = (pair) => ({x: pair[0], y: pair[1]}) const coordsToPair = (coords) => [coords.x, coords.y] @@ -840,13 +686,13 @@ coordsToPair(pairToCoords([1, 2])) // [1, 2] pairToCoords(coordsToPair({x: 1, y: 2})) // {x: 1, y: 2} ``` + + ## Setoid -Suatu objek yang memiliki fungsi `equals` yang mana dapat digunakan untuk -membandingkan objek lain dengan tipe yang sama. - -Menjadikan _array_ suatu _setoid_: +An object that has an `equals` function which can be used to compare other objects of the same type. +Make array a setoid: ```js Array.prototype.equals = function (arr) { @@ -868,9 +714,7 @@ Array.prototype.equals = function (arr) { ## Semigroup -Suatu objek yang memiliki fungsi `concat` yang menggabungkannya dengan objek -lain dengan tipe yang sama. - +An object that has a `concat` function that combines it with another object of the same type. ```js ;[1].concat([2]) // [1, 2] @@ -878,23 +722,18 @@ lain dengan tipe yang sama. ## Foldable -Suatu objek yang memiliki fungsi `reduce` yang dapat mengubah objek tersebut -menjadi tipe yang lain. - +An object that has a `reduce` function that can transform that object into some other type. ```js const sum = (list) => list.reduce((acc, val) => acc + val, 0) sum([1, 2, 3]) // 6 ``` -## Type Signature +## Type Signatures -Seringkali fungsi dalam JavaScript memiliki komentar yang menunjukkan tipe dari -argumen dan nilai pengembaliannya. - -Ada sedikit perbedaan di antara komunitas/masyarakat, namun mereka sering -mengikuti pola berikut: +Often functions in JavaScript will include comments that indicate the types of their arguments and return values. +There's quite a bit of variance across the community but they often follow the following patterns: ```js // functionName :: firstArgType -> secondArgType -> returnType @@ -906,95 +745,66 @@ const add = (x) => (y) => x + y const increment = (x) => x + 1 ``` -Jika suatu fungsi menerima fungsi lain sebagai argumennya, maka itu dibungkus -dengan tanda kurung. - +If a function accepts another function as an argument it is wrapped in parentheses. ```js // call :: (a -> b) -> a -> b const call = (f) => (x) => f(x) ``` -Huruf `a`, `b`, `c`, `d` digunakan sebagai tanda bahwa argumen tersebut dapat -berbentuk apa saja. Layaknya versi dari `map`, mengambil sebuah fungsi -yang mengubah nilai dari bentuk `a` ke bentuk lain `b`, sebuah _array_ dengan -nilai berbentuk `a`, dan mengembalikan sebuah _array_ dengan nilai berbentuk -`b`. - +The letters `a`, `b`, `c`, `d` are used to signify that the argument can be of any type. The following version of `map` takes a function that transforms a value of some type `a` into another type `b`, an array of values of type `a`, and returns an array of values of type `b`. ```js // map :: (a -> b) -> [a] -> [b] const map = (f) => (list) => list.map(f) ``` -__Bacan lebih lanjut__ +__Further reading__ * [Ramda's type signatures](https://github.com/ramda/ramda/wiki/Type-Signatures) * [Mostly Adequate Guide](https://drboolean.gitbooks.io/mostly-adequate-guide/content/ch7.html#whats-your-type) -* [What is Hindley-Milner?](http://stackoverflow.com/a/399392/22425) di Stack Overflow +* [What is Hindley-Milner?](http://stackoverflow.com/a/399392/22425) on Stack Overflow ## Algebraic data type - -Jenis komposit yang dibuat dari jenis lainnya. Dua kelas umum dari tipe aljabar -(_algebraic type_) adalah [_sum_](#sum-type) dan [_product_](#product-type). +A composite type made from putting other types together. Two common classes of algebraic types are [sum](#sum-type) and [product](#product-type). ### Sum type +A Sum type is the combination of two types together into another one. It is called sum because the number of possible values in the result type is the sum of the input types. -_Sum type_ adalah kombinasi dari dua _type_ menjadi satu sama lain. Ini disebut -jumlah (_sum_) karena jumlah nilai yang mungkin terjadi pada _type_ hasil -adalah jumlah dari tipe masukan. - -JavaScript tidak memiliki _type_ seperti ini, tapi kita dapat menggunakan `Set` -untuk berpura-pura: - - +JavaScript doesn't have types like this but we can use `Set`s to pretend: ```js -// bayangkan bahwa daripada Set di sini kita memiliki tipe yang hanya memiliki nilai-nilai ini +// imagine that rather than sets here we have types that can only have these values const bools = new Set([true, false]) const halfTrue = new Set(['half-true']) -// Tipe `weakLogic` mengandung jumlah nilai dari `bools` dan `halfTrue` +// The weakLogic type contains the sum of the values from bools and halfTrue const weakLogicValues = new Set([...bools, ...halfTrue]) ``` -_Sum type_ terkadang disebut _union type_, _discriminated union_, atau _tagged -union_. +Sum types are sometimes called union types, discriminated unions, or tagged unions. -Ada [beberapa](https://github.com/paldepind/union-type) -[pustaka](https://github.com/puffnfresh/daggy) dalam JavaScript yang -membantu mendefinisikan dan menggunakan _union type_. +There's a [couple](https://github.com/paldepind/union-type) [libraries](https://github.com/puffnfresh/daggy) in JS which help with defining and using union types. -_Flow_ memasukkan [_union type_](https://flow.org/en/docs/types/unions/) dan -TypeScript memiliki -[Enums](https://www.typescriptlang.org/docs/handbook/enums.html) untuk melayani -peran yang sama. +Flow includes [union types](https://flow.org/en/docs/types/unions/) and TypeScript has [Enums](https://www.typescriptlang.org/docs/handbook/enums.html) to serve the same role. ### Product type -Tipe ***product*** menggabungkan beberapa tipe bersama, dengan cara yang mungkin -Anda telah akrab: +A **product** type combines types together in a way you're probably more familiar with: ```js // point :: (Number, Number) -> {x: Number, y: Number} const point = (x, y) => ({x: x, y: y}) ``` +It's called a product because the total possible values of the data structure is the product of the different values. Many languages have a tuple type which is the simplest formulation of a product type. -Ini disebut produk (_product_) karena nilai total dari struktur data adalah -produk dari nilai yang berbeda. Banyak bahasa memiliki tipe _tuple_ yang -merupakan formulasi sederhana dari _product type_. - -Lihat juga [teori himpunan](https://id.wikipedia.org/wiki/Teori_himpunan). +See also [Set theory](https://en.wikipedia.org/wiki/Set_theory). ## Option +Option is a [sum type](#sum-type) with two cases often called `Some` and `None`. -_Option_ adalah suatu _[sum type](#sum-type)_ dengan dua kasus yang sering -disebut `Some` dan `None`. - -_Option_ sangat berguna untuk menyusun fungsi-fungsi yang mungkin tidak -mengembalikan sebuah nilai. - +Option is useful for composing functions that might not return a value. ```js -// Definisi naif +// Naive definition const Some = (v) => ({ val: v, @@ -1018,10 +828,7 @@ const None = () => ({ // maybeProp :: (String, {a}) -> Option a const maybeProp = (key, obj) => typeof obj[key] === 'undefined' ? None() : Some(obj[key]) ``` - -Gunakan `chain` untuk mengurutkan fungsi yang mengembalikan `Option`. - - +Use `chain` to sequence functions that return `Option`s ```js // getItem :: Cart -> Option CartItem @@ -1038,10 +845,9 @@ getNestedPrice({item: {foo: 1}}) // None() getNestedPrice({item: {price: 9.99}}) // Some(9.99) ``` -`Option` juga dikenal sebagai `Maybe`. `Some` terkadang disebut `Just`. -`None` terkadang disebut `Nothing`. +`Option` is also known as `Maybe`. `Some` is sometimes called `Just`. `None` is sometimes called `Nothing`. -## Pustaka Pemrograman Fungsional dalam JavaScript +## Functional Programming Libraries in JavaScript * [mori](https://github.com/swannodette/mori) * [Immutable](https://github.com/facebook/immutable-js/) @@ -1054,11 +860,8 @@ getNestedPrice({item: {price: 9.99}}) // Some(9.99) * [Lazy.js](https://github.com/dtao/lazy.js) * [maryamyriameliamurphies.js](https://github.com/sjsyrek/maryamyriameliamurphies.js) * [Haskell in ES6](https://github.com/casualjavascript/haskell-in-es6) +* [Sanctuary](https://github.com/sanctuary-js/sanctuary) --- -__P.S:__ _Repository_ ini di-_fork_ dari proyek -[_Functional Programming Jargon_](https://github.com/hemanth/functional-programming-jargon/) -milik [hemanth](https://github.com/hemanth/) dan telah dikatakan berhasil karena -[kontribusi](https://github.com/hemanth/functional-programming-jargon/graphs/contributors) -yang luar biasa. +__P.S:__ This repo is successful due to the wonderful [contributions](https://github.com/hemanth/functional-programming-jargon/graphs/contributors)! From 28aa73f0c6805cffcc2825670fe575cb6fbcd8dd Mon Sep 17 00:00:00 2001 From: trueproof Date: Tue, 4 Jul 2017 14:48:42 +0300 Subject: [PATCH 11/43] missing semicolon --- readme.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/readme.md b/readme.md index 44c46ce..50c8c3f 100644 --- a/readme.md +++ b/readme.md @@ -415,7 +415,7 @@ object.map(compose(f, g)) ≍ object.map(g).map(f) A common functor in JavaScript is `Array` since it abides to the two functor rules: ```js -[1, 2, 3].map(x => x) // = [1, 2, 3] +;[1, 2, 3].map(x => x) // = [1, 2, 3] ``` and @@ -496,7 +496,7 @@ An anonymous function that can be treated like a value. Lambdas are often passed as arguments to Higher-Order functions. ```js -[1, 2].map((a) => a + 1) // [2, 3] +;[1, 2].map((a) => a + 1) // [2, 3] ``` You can assign a lambda to a variable. From d8a5ab23490f27c910018504f872b6e6e7bd6704 Mon Sep 17 00:00:00 2001 From: trueproof Date: Fri, 7 Jul 2017 10:55:48 +0300 Subject: [PATCH 12/43] redundant semicolon --- readme.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/readme.md b/readme.md index 50c8c3f..d3d5314 100644 --- a/readme.md +++ b/readme.md @@ -583,10 +583,10 @@ Array.prototype.chain = function (f) { } // Usage -;Array.of('cat,dog', 'fish,bird').chain((a) => a.split(',')) // ['cat', 'dog', 'fish', 'bird'] +Array.of('cat,dog', 'fish,bird').chain((a) => a.split(',')) // ['cat', 'dog', 'fish', 'bird'] // Contrast to map -;Array.of('cat,dog', 'fish,bird').map((a) => a.split(',')) // [['cat', 'dog'], ['fish', 'bird']] +Array.of('cat,dog', 'fish,bird').map((a) => a.split(',')) // [['cat', 'dog'], ['fish', 'bird']] ``` `of` is also known as `return` in other functional languages. From 7f91c1b022e2b364e963a6aa5c76293573c6d1f0 Mon Sep 17 00:00:00 2001 From: TobiasRoland Date: Fri, 8 Sep 2017 13:47:31 -0400 Subject: [PATCH 13/43] "are" instead of "be" ... for a less pirate-sounding sentence. --- readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.md b/readme.md index d3d5314..afa5ed8 100644 --- a/readme.md +++ b/readme.md @@ -410,7 +410,7 @@ __Composable__ object.map(compose(f, g)) ≍ object.map(g).map(f) ``` -(`f`, `g` be arbitrary functions) +(`f`, `g` are arbitrary functions) A common functor in JavaScript is `Array` since it abides to the two functor rules: From 9d53306b52133e143962301011e5473d7236a3b5 Mon Sep 17 00:00:00 2001 From: jethro larson Date: Mon, 2 Oct 2017 18:33:41 -0700 Subject: [PATCH 14/43] Add definition for lens #166 --- readme.md | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/readme.md b/readme.md index afa5ed8..0aa6b4f 100644 --- a/readme.md +++ b/readme.md @@ -52,6 +52,7 @@ __Table of Contents__ * [Setoid](#setoid) * [Semigroup](#semigroup) * [Foldable](#foldable) +* [Lens](#lens) * [Type Signatures](#type-signatures) * [Algebraic data type](#algebraic-data-type) * [Sum type](#sum-type) @@ -729,6 +730,56 @@ const sum = (list) => list.reduce((acc, val) => acc + val, 0) sum([1, 2, 3]) // 6 ``` +## Lens ## +A lens is a structure (often an object or function) that pairs a getter and a non-mutating setter for some other data +structure. + +```js +// Using [Ramda's lens](http://ramdajs.com/docs/#lens) +const nameLens = R.lens( + // getter for name property on an object + (obj) => obj.name, + // setter for name property + (val, obj) => Object.assign({}, obj, {name: val}) +) +``` + +Having the pair of get and set for a given data structure enables a few key features. + +```js +const person = {name: 'Gertrude Blanch'} + +// invoke the getter +R.view(nameLens, person) // 'Gertrude Blanch' + +// invoke the setter +R.set(nameLens, 'Shafi Goldwasser', person) // {name: 'Shafi Goldwasser'} + +// run a function on the value in the structure +R.over(nameLens, uppercase, person) // {name: 'GERTRUDE BLANCH'} +``` + +Lenses are also composable. This allows easy immutable updates to deeply nested data. + +```js +// This lens focuses on the first item in a non-empty array +const firstLens = R.lens( + // get first item in array + xs => xs[0], + // non-mutating setter for first item in array + (val, [__, ...xs]) => [val, ...xs] +) + +const people = [{name: 'Gertrude Blanch'}, {name: 'Shafi Goldwasser'}] + +// Despite what you may assume, lenses compose left-to-right. +R.over(compose(firstLens, nameLens), uppercase, people) // [{'name': 'GERTRUDE BLANCH'}, {'name': 'Shafi Goldwasser'}] +``` + +Other implementations: +* [partial.lenses](https://github.com/calmm-js/partial.lenses) - Tasty syntax sugar and a lot of powerful features +* [nanoscope](http://www.kovach.me/nanoscope/) - Fluent-interface + ## Type Signatures Often functions in JavaScript will include comments that indicate the types of their arguments and return values. From f6f0511100cc1092e70dcfde8f65d23a557e8edf Mon Sep 17 00:00:00 2001 From: Mitch Keenan Date: Tue, 7 Nov 2017 11:36:32 -0400 Subject: [PATCH 15/43] Fixed inline code formatting in Closure Section --- readme.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/readme.md b/readme.md index 0aa6b4f..225bdfc 100644 --- a/readme.md +++ b/readme.md @@ -156,9 +156,9 @@ const addTo = x => y => x + y var addToFive = addTo(5) addToFive(3) // returns 8 ``` -The function ```addTo()``` returns a function(internally called ```add()```), lets store it in a variable called ```addToFive``` with a curried call having parameter 5. +The function `addTo()` returns a function(internally called `add()`), lets store it in a variable called `addToFive` with a curried call having parameter 5. -Ideally, when the function ```addTo``` finishes execution, its scope, with local variables add, x, y should not be accessible. But, it returns 8 on calling ```addToFive()```. This means that the state of the function ```addTo``` is saved even after the block of code has finished executing, otherwise there is no way of knowing that ```addTo``` was called as ```addTo(5)``` and the value of x was set to 5. +Ideally, when the function `addTo` finishes execution, its scope, with local variables add, x, y should not be accessible. But, it returns 8 on calling `addToFive()`. This means that the state of the function `addTo` is saved even after the block of code has finished executing, otherwise there is no way of knowing that `addTo` was called as `addTo(5)` and the value of x was set to 5. Lexical scoping is the reason why it is able to find the values of x and add - the private variables of the parent which has finished executing. This value is called a Closure. From bbd80f9623965c2c7c571a61f2ef9943bdc4b063 Mon Sep 17 00:00:00 2001 From: iangregor Date: Wed, 8 Nov 2017 15:24:02 +1000 Subject: [PATCH 16/43] Add line after code block to fix inline code https://functional.works-hub.com/blog/Functional-Programming-Jargon The line below is shown instead of having the single backticks in the md rendered into inline code. > The function \`\`\`addTo()\`\`\` returns a function(internally called \`\`\`add()\`\`\`), lets --- readme.md | 1 + 1 file changed, 1 insertion(+) diff --git a/readme.md b/readme.md index 225bdfc..6c26de7 100644 --- a/readme.md +++ b/readme.md @@ -156,6 +156,7 @@ const addTo = x => y => x + y var addToFive = addTo(5) addToFive(3) // returns 8 ``` + The function `addTo()` returns a function(internally called `add()`), lets store it in a variable called `addToFive` with a curried call having parameter 5. Ideally, when the function `addTo` finishes execution, its scope, with local variables add, x, y should not be accessible. But, it returns 8 on calling `addToFive()`. This means that the state of the function `addTo` is saved even after the block of code has finished executing, otherwise there is no way of knowing that `addTo` was called as `addTo(5)` and the value of x was set to 5. From ce3d8fca474c599bd998add14db0e5116d77815b Mon Sep 17 00:00:00 2001 From: Talasan Nicholson Date: Wed, 8 Nov 2017 01:10:39 -0600 Subject: [PATCH 17/43] use object init shorthand for prod types --- readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.md b/readme.md index 225bdfc..47ed822 100644 --- a/readme.md +++ b/readme.md @@ -843,7 +843,7 @@ A **product** type combines types together in a way you're probably more familia ```js // point :: (Number, Number) -> {x: Number, y: Number} -const point = (x, y) => ({x: x, y: y}) +const point = (x, y) => ({ x, y }) ``` It's called a product because the total possible values of the data structure is the product of the different values. Many languages have a tuple type which is the simplest formulation of a product type. From 622d06ef546b6ddbbd9e78685aa45e9e6c5bcee0 Mon Sep 17 00:00:00 2001 From: Ikhoon Eom Date: Mon, 13 Nov 2017 02:16:19 +0900 Subject: [PATCH 18/43] Add scala translation :-) --- readme.md | 1 + 1 file changed, 1 insertion(+) diff --git a/readme.md b/readme.md index f94f090..814b566 100644 --- a/readme.md +++ b/readme.md @@ -13,6 +13,7 @@ __Translations__ * [Spanish](https://github.com/idcmardelplata/functional-programming-jargon/tree/master) * [Chinese](https://github.com/shfshanyue/fp-jargon-zh) * [Bahasa Indonesia](https://github.com/wisn/jargon-pemrograman-fungsional) +* [Scala World](https://github.com/ikhoon/functional-programming-jargon.scala) __Table of Contents__ From 5842916f92a3569c515351252ecfa743e0764352 Mon Sep 17 00:00:00 2001 From: GH Lee Date: Wed, 15 Nov 2017 14:59:37 +0900 Subject: [PATCH 19/43] Add Korean translation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I am interested in functional programming paradigm. So I made Korean translation for functional programming jargon. Thanks for the good info. 😄 --- readme.md | 1 + 1 file changed, 1 insertion(+) diff --git a/readme.md b/readme.md index 814b566..3b568e8 100644 --- a/readme.md +++ b/readme.md @@ -14,6 +14,7 @@ __Translations__ * [Chinese](https://github.com/shfshanyue/fp-jargon-zh) * [Bahasa Indonesia](https://github.com/wisn/jargon-pemrograman-fungsional) * [Scala World](https://github.com/ikhoon/functional-programming-jargon.scala) +* [Korean](https://github.com/sphilee/functional-programming-jargon) __Table of Contents__ From 5dd81ec32c7de965f1b42a5c214a5ba1df037291 Mon Sep 17 00:00:00 2001 From: "Hemanth.HM" Date: Sun, 10 Dec 2017 12:02:38 +0530 Subject: [PATCH 20/43] pre-commit hook for lint and TOC. --- contributing.md | 3 +-- package.json | 10 ++++++++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/contributing.md b/contributing.md index 138a49a..b7bdd87 100644 --- a/contributing.md +++ b/contributing.md @@ -3,8 +3,7 @@ This project is a work in progress. Contributions are very welcome. ## Hard rules -* Run `npm test` to lint the code examples. Your changes must pass. -* If you add a new definition or reorder them run `npm run toc` to regenerate the table of contents. +There is a pre-commit hook that runs: `npm run test && npm run roadmarks` for linting the readme and creating the TOC. That said, we'd like to maintain some consistency across the document. diff --git a/package.json b/package.json index e7cfe68..9086e8c 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,13 @@ "devDependencies": { "eslint": "^3.4.0", "eslint-config-standard": "^6.0.0", - "eslint-plugin-markdown": "^1.0.0-beta.2", + "eslint-plugin-markdown": "^1.0.0-beta.6", + "eslint-plugin-standard": "^3.0.1", + "pre-commit": "^1.2.2", "roadmarks": "^1.6.3" - } + }, + "pre-commit": [ + "test", + "toc" + ] } From 951e888bd2898f0f6f52286905cd1a4c3a1618e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Lula?= Date: Tue, 9 Jan 2018 11:43:59 +0100 Subject: [PATCH 21/43] Fix Option example --- readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.md b/readme.md index 3b568e8..70caefa 100644 --- a/readme.md +++ b/readme.md @@ -892,7 +892,7 @@ const getItem = (cart) => maybeProp('item', cart) const getPrice = (item) => maybeProp('price', item) // getNestedPrice :: cart -> Option a -const getNestedPrice = (cart) => getItem(obj).chain(getPrice) +const getNestedPrice = (cart) => getItem(cart).chain(getPrice) getNestedPrice({}) // None() getNestedPrice({item: {foo: 1}}) // None() From cc1cd095187cbec0ed3556ba5e035e6b16785ac2 Mon Sep 17 00:00:00 2001 From: Joel McCracken Date: Sat, 13 Jan 2018 16:59:44 -0500 Subject: [PATCH 22/43] Fixed url for folktale The other is on a domain that must be dead, because it was redirecting to some spammy nonsense. --- readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.md b/readme.md index 70caefa..9f11813 100644 --- a/readme.md +++ b/readme.md @@ -907,7 +907,7 @@ getNestedPrice({item: {price: 9.99}}) // Some(9.99) * [Immutable](https://github.com/facebook/immutable-js/) * [Ramda](https://github.com/ramda/ramda) * [ramda-adjunct](https://github.com/char0n/ramda-adjunct) -* [Folktale](http://folktalejs.org) +* [Folktale](http://folktale.origamitower.com/) * [monet.js](https://cwmyers.github.io/monet.js/) * [lodash](https://github.com/lodash/lodash) * [Underscore.js](https://github.com/jashkenas/underscore) From aeac2ee26f6cf36a93143ea7ca7ef9eb3031ffd5 Mon Sep 17 00:00:00 2001 From: jethro larson Date: Tue, 20 Mar 2018 11:26:49 -0700 Subject: [PATCH 23/43] Simplified closure definition #162 --- readme.md | 72 ++++++++++++++++++++++++++++++------------------------- 1 file changed, 39 insertions(+), 33 deletions(-) diff --git a/readme.md b/readme.md index 9f11813..9b5572e 100644 --- a/readme.md +++ b/readme.md @@ -21,9 +21,9 @@ __Table of Contents__ * [Arity](#arity) * [Higher-Order Functions (HOF)](#higher-order-functions-hof) +* [Closure](#closure) * [Partial Application](#partial-application) * [Currying](#currying) -* [Closure](#closure) * [Auto Currying](#auto-currying) * [Function Composition](#function-composition) * [Continuation](#continuation) @@ -94,6 +94,43 @@ const is = (type) => (x) => Object(x) instanceof type filter(is(Number), [0, '1', 2, null]) // [0, 2] ``` +## Closure + +A closure is a scope which retains variables available to a function when it's created. This is important for +[partial application](#partial-application) to work. + + +```js +const addTo = (x) => { + return (y) => { + return x + y + } +} +``` + +We can call `addTo` with a number and get back a function with a baked-in `x`. + +```js +var addToFive = addTo(5) +``` + +In this case the `x` is retained in `addToFive`'s closure with the value `5`. We can then call `addToFive` with the `y` +and get back the desired number. + +``` +addToFive(3) // => 8 +``` + +This works because variables that are in parent scopes are not garbage-collected as long as the function itself is retained. + +Closures are commonly used in event handlers so that they still have access to variables defined in their parents when they +are eventually called. + +__Further reading__ +* [Lambda Vs Closure](http://stackoverflow.com/questions/220658/what-is-the-difference-between-a-closure-and-a-lambda) +* [How do JavaScript Closures Work?](http://stackoverflow.com/questions/111102/how-do-javascript-closures-work) + + ## Partial Application Partially applying a function means creating a new function by pre-filling some of the arguments to the original function. @@ -125,6 +162,7 @@ const add1More = add3.bind(null, 2, 3) // (c) => 2 + 3 + c Partial application helps create simpler functions from more complex ones by baking in data when you have it. [Curried](#currying) functions are automatically partially applied. + ## Currying The process of converting a function that takes multiple arguments into a function that takes them one at a time. @@ -144,38 +182,6 @@ add2(10) // 12 ``` -## Closure - -A closure is a way of accessing a variable outside its scope. -Formally, a closure is a technique for implementing lexically scoped named binding. It is a way of storing a function with an environment. - -A closure is a scope which captures local variables of a function for access even after the execution has moved out of the block in which it is defined. -ie. they allow referencing a scope after the block in which the variables were declared has finished executing. - - -```js -const addTo = x => y => x + y -var addToFive = addTo(5) -addToFive(3) // returns 8 -``` - -The function `addTo()` returns a function(internally called `add()`), lets store it in a variable called `addToFive` with a curried call having parameter 5. - -Ideally, when the function `addTo` finishes execution, its scope, with local variables add, x, y should not be accessible. But, it returns 8 on calling `addToFive()`. This means that the state of the function `addTo` is saved even after the block of code has finished executing, otherwise there is no way of knowing that `addTo` was called as `addTo(5)` and the value of x was set to 5. - -Lexical scoping is the reason why it is able to find the values of x and add - the private variables of the parent which has finished executing. This value is called a Closure. - -The stack along with the lexical scope of the function is stored in form of reference to the parent. This prevents the closure and the underlying variables from being garbage collected(since there is at least one live reference to it). - -Lambda Vs Closure: A lambda is essentially a function that is defined inline rather than the standard method of declaring functions. Lambdas can frequently be passed around as objects. - -A closure is a function that encloses its surrounding state by referencing fields external to its body. The enclosed state remains across invocations of the closure. - - -__Further reading/Sources__ -* [Lambda Vs Closure](http://stackoverflow.com/questions/220658/what-is-the-difference-between-a-closure-and-a-lambda) -* [How do JavaScript Closures Work?](http://stackoverflow.com/questions/111102/how-do-javascript-closures-work) - ## Auto Currying Transforming a function that takes multiple arguments into one that if given less than its correct number of arguments returns a function that takes the rest. When the function gets the correct number of arguments it is then evaluated. From b28cba25b8efcad8b29ef70981e6cf42aa8394ef Mon Sep 17 00:00:00 2001 From: Dale Francis Date: Wed, 6 Jun 2018 17:29:59 +1000 Subject: [PATCH 24/43] Added reference to Crocks ADT library crocks is a collection of popular Algebraic Data Types (ADTs) that are all the rage in functional programming. The main goal of crocks is to curate and provide not only a common interface between each type (where possible of course), but also provide all of the helper functions needed to hit the ground running. --- readme.md | 1 + 1 file changed, 1 insertion(+) diff --git a/readme.md b/readme.md index 9b5572e..111c7b8 100644 --- a/readme.md +++ b/readme.md @@ -921,6 +921,7 @@ getNestedPrice({item: {price: 9.99}}) // Some(9.99) * [maryamyriameliamurphies.js](https://github.com/sjsyrek/maryamyriameliamurphies.js) * [Haskell in ES6](https://github.com/casualjavascript/haskell-in-es6) * [Sanctuary](https://github.com/sanctuary-js/sanctuary) +* [Crocks](https://github.com/evilsoft/crocks) --- From 9c3077f43abc62675b60cba69639a4d92ab53aac Mon Sep 17 00:00:00 2001 From: Igor Date: Thu, 20 Sep 2018 17:10:22 +0200 Subject: [PATCH 25/43] Added info about function totality Some examples of total/partial functions with general advices how to avoid partial functions --- readme.md | 78 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) diff --git a/readme.md b/readme.md index 111c7b8..9c3b6f6 100644 --- a/readme.md +++ b/readme.md @@ -60,6 +60,7 @@ __Table of Contents__ * [Sum type](#sum-type) * [Product type](#product-type) * [Option](#option) +* [Totality](#totality) * [Functional Programming Libraries in JavaScript](#functional-programming-libraries-in-javascript) @@ -907,6 +908,83 @@ getNestedPrice({item: {price: 9.99}}) // Some(9.99) `Option` is also known as `Maybe`. `Some` is sometimes called `Just`. `None` is sometimes called `Nothing`. +## Totality +### Total functions +The total function is just like a function in math - it will always return a result of the expected type for expected inputs and will always terminate. The easiest example is `identity` function: +```js +// identity :: a -> a +const identity = a => a +``` +or `negate`: +```js +// negate :: Boolean -> Boolean +const negate = value => !value +``` +Such functions always meet the requirements, you just can't provide such arguments, which satisfy inputs but break outputs. +### Partial functions +It's a function which violates the requirements to be total - it may return an unexpected result with some inputs or it may never terminate. Partial functions add cognitive overhead, they are harder to reason about and they can lead to runtime errors. Some examples: +```js +// example 1: sum of the list +// sum :: [Number] -> Number +const sum = arr => arr.reduce((a, b) => a + b) +sum([1, 2, 3]) // 6 +sqrt([]) // TypeError: Reduce of empty array with no initial value + +// example 2: get the first item in list +// first :: [A] -> A +const first = a => a[0] +first([42]) // 42 +first([]) // undefined +//or even worse: +first([[42]])[0] // 42 +first([])[0] // Uncaught TypeError: Cannot read property '0' of undefined + +// example 3: repeat function N times +// times :: Number -> (Number -> Number) -> Number +const times = n => fn => n && (fn(n), times(n - 1)(fn)) +times(3)(console.log) +// 3 +// 2 +// 1 +times(-1)(console.log) +// RangeError: Maximum call stack size exceeded +``` +### Avoiding partial functions +Partial functions are dangerous, you can sometimes get the expected result, sometimes the wrong result, and sometimes your function can't stop the calculations at all. The input of partial functions should be always checked, and it can be hard to track all edge cases through entire applications, the easiest way to deal with it it's just to convert all partial functions to the total. General advice can be the usage of `Optional` type, providing default values for edge cases and checking function conditions to make them always terminate: +```js +// example 1: sum of the list +// we can provide default value so it will always return result +// sum :: [Number] -> Number +const sum = arr => arr.reduce((a, b) => a + b, 0) +sum([1, 2, 3]) // 6 +sqrt([]) // 0 + +// example 2: get the first item in list +// change result to Option +// first :: [A] -> Option A +const first = a => a.length ? Some(a[0]) : None() +first([[42]]).map(a => console.log(a)) // 42 +first([]).map(a => console.log(a)) // console.log won't execute at all +//our previous worst case +first([[42]]).map(a => console.log(a[0])) // 42 +first([]).map(a => console.log(a[0])) // won't execte, so we won't have error here +// more of that, you will know by function return type (Option) +// that you should use `.map` method to access the data and you will never forget +// to check your input because such check become built-in into the function + +// example 3: repeat function N times +// we should make function always terminate by changing conditions: +// times :: Number -> (Number -> Number) -> Number +const times = n => fn => n > 0 && (fn(n), times(n - 1)(fn)) +times(3)(console.log) +// 3 +// 2 +// 1 +times(-1)(console.log) +// won't execute anything +``` +If you will change all your functions from partial to total, it can prevent you from having runtime exceptions, will make code easier to reason about and easier to maintain. + ## Functional Programming Libraries in JavaScript * [mori](https://github.com/swannodette/mori) From 18a8507023e375cec834a62f1bc3e08bbbfdb050 Mon Sep 17 00:00:00 2001 From: Bhavdeep Dhanjal Date: Sun, 7 Oct 2018 04:01:51 +0530 Subject: [PATCH 26/43] Add references to Immer and Fluture --- readme.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/readme.md b/readme.md index 9c3b6f6..1a1e23b 100644 --- a/readme.md +++ b/readme.md @@ -989,6 +989,7 @@ If you will change all your functions from partial to total, it can prevent you * [mori](https://github.com/swannodette/mori) * [Immutable](https://github.com/facebook/immutable-js/) +* [Immer](https://github.com/mweststrate/immer) * [Ramda](https://github.com/ramda/ramda) * [ramda-adjunct](https://github.com/char0n/ramda-adjunct) * [Folktale](http://folktale.origamitower.com/) @@ -1000,6 +1001,7 @@ If you will change all your functions from partial to total, it can prevent you * [Haskell in ES6](https://github.com/casualjavascript/haskell-in-es6) * [Sanctuary](https://github.com/sanctuary-js/sanctuary) * [Crocks](https://github.com/evilsoft/crocks) +* [Fluture](https://github.com/fluture-js/Fluture) --- From e03612ea9e7d1bcb253cf206ae18c4842992bf97 Mon Sep 17 00:00:00 2001 From: Rea Sand Date: Thu, 18 Oct 2018 11:57:50 +0200 Subject: [PATCH 27/43] docs: consistently use Option instead of Optional --- readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.md b/readme.md index 1a1e23b..943a8d5 100644 --- a/readme.md +++ b/readme.md @@ -950,7 +950,7 @@ times(-1)(console.log) // RangeError: Maximum call stack size exceeded ``` ### Avoiding partial functions -Partial functions are dangerous, you can sometimes get the expected result, sometimes the wrong result, and sometimes your function can't stop the calculations at all. The input of partial functions should be always checked, and it can be hard to track all edge cases through entire applications, the easiest way to deal with it it's just to convert all partial functions to the total. General advice can be the usage of `Optional` type, providing default values for edge cases and checking function conditions to make them always terminate: +Partial functions are dangerous, you can sometimes get the expected result, sometimes the wrong result, and sometimes your function can't stop the calculations at all. The input of partial functions should be always checked, and it can be hard to track all edge cases through entire applications, the easiest way to deal with it it's just to convert all partial functions to the total. General advice can be the usage of `Option` type, providing default values for edge cases and checking function conditions to make them always terminate: ```js // example 1: sum of the list // we can provide default value so it will always return result From a7e26ce75613a24e6278e66f9369ce5a42030ed4 Mon Sep 17 00:00:00 2001 From: Rea Sand Date: Thu, 18 Oct 2018 11:59:54 +0200 Subject: [PATCH 28/43] fix: drop trailing whitespace --- readme.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/readme.md b/readme.md index 943a8d5..6531c19 100644 --- a/readme.md +++ b/readme.md @@ -946,7 +946,7 @@ times(3)(console.log) // 3 // 2 // 1 -times(-1)(console.log) +times(-1)(console.log) // RangeError: Maximum call stack size exceeded ``` ### Avoiding partial functions @@ -980,7 +980,7 @@ times(3)(console.log) // 3 // 2 // 1 -times(-1)(console.log) +times(-1)(console.log) // won't execute anything ``` If you will change all your functions from partial to total, it can prevent you from having runtime exceptions, will make code easier to reason about and easier to maintain. From 11294984aa0cc58f3571729a3d6aeb8ca084a7d7 Mon Sep 17 00:00:00 2001 From: Rea Sand Date: Thu, 18 Oct 2018 11:57:50 +0200 Subject: [PATCH 29/43] docs: consistently use Option instead of Optional --- readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.md b/readme.md index 1a1e23b..943a8d5 100644 --- a/readme.md +++ b/readme.md @@ -950,7 +950,7 @@ times(-1)(console.log) // RangeError: Maximum call stack size exceeded ``` ### Avoiding partial functions -Partial functions are dangerous, you can sometimes get the expected result, sometimes the wrong result, and sometimes your function can't stop the calculations at all. The input of partial functions should be always checked, and it can be hard to track all edge cases through entire applications, the easiest way to deal with it it's just to convert all partial functions to the total. General advice can be the usage of `Optional` type, providing default values for edge cases and checking function conditions to make them always terminate: +Partial functions are dangerous, you can sometimes get the expected result, sometimes the wrong result, and sometimes your function can't stop the calculations at all. The input of partial functions should be always checked, and it can be hard to track all edge cases through entire applications, the easiest way to deal with it it's just to convert all partial functions to the total. General advice can be the usage of `Option` type, providing default values for edge cases and checking function conditions to make them always terminate: ```js // example 1: sum of the list // we can provide default value so it will always return result From 0ebee1d815bced1677d353b4b1ba7d6496ae6c9e Mon Sep 17 00:00:00 2001 From: Rea Sand Date: Thu, 18 Oct 2018 11:59:54 +0200 Subject: [PATCH 30/43] fix: drop trailing whitespace --- readme.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/readme.md b/readme.md index 943a8d5..6531c19 100644 --- a/readme.md +++ b/readme.md @@ -946,7 +946,7 @@ times(3)(console.log) // 3 // 2 // 1 -times(-1)(console.log) +times(-1)(console.log) // RangeError: Maximum call stack size exceeded ``` ### Avoiding partial functions @@ -980,7 +980,7 @@ times(3)(console.log) // 3 // 2 // 1 -times(-1)(console.log) +times(-1)(console.log) // won't execute anything ``` If you will change all your functions from partial to total, it can prevent you from having runtime exceptions, will make code easier to reason about and easier to maintain. From 321806908c875ee40e63dbe77a1d95870195cbc1 Mon Sep 17 00:00:00 2001 From: Rea Sand Date: Fri, 19 Oct 2018 15:21:43 +0200 Subject: [PATCH 31/43] refactor: Introduce function section - dissolve totality section - make partial function a top-level section - reformulate content of partial function section --- readme.md | 43 ++++++++++++++++++++++++++++++++----------- 1 file changed, 32 insertions(+), 11 deletions(-) diff --git a/readme.md b/readme.md index 6531c19..7f8a2ed 100644 --- a/readme.md +++ b/readme.md @@ -60,7 +60,8 @@ __Table of Contents__ * [Sum type](#sum-type) * [Product type](#product-type) * [Option](#option) -* [Totality](#totality) +* [Function](#function) +* [Partial function](#partial-function) * [Functional Programming Libraries in JavaScript](#functional-programming-libraries-in-javascript) @@ -908,9 +909,12 @@ getNestedPrice({item: {price: 9.99}}) // Some(9.99) `Option` is also known as `Maybe`. `Some` is sometimes called `Just`. `None` is sometimes called `Nothing`. -## Totality -### Total functions -The total function is just like a function in math - it will always return a result of the expected type for expected inputs and will always terminate. The easiest example is `identity` function: +## Function +Category Threory: A function is just an arrow between types. It has a direction. Replace arrow with mapping maybe? + +A **function** `f: A -> B` maps every element from its domain (A) to an element in its co-domain (B); or in other words: takes exactly one argument and maps it to exactly one (and always the same) value. That value depends entirely on the argument. This is what makes functions so pleasant to work with: there is no room for side-effects; a function is always pure – by definition. Functions exhibit [referential transparency](#referential-transparency). + +A very simple example is the `identity` function: ```js // identity :: a -> a const identity = a => a @@ -920,9 +924,24 @@ or `negate`: // negate :: Boolean -> Boolean const negate = value => !value ``` -Such functions always meet the requirements, you just can't provide such arguments, which satisfy inputs but break outputs. -### Partial functions -It's a function which violates the requirements to be total - it may return an unexpected result with some inputs or it may never terminate. Partial functions add cognitive overhead, they are harder to reason about and they can lead to runtime errors. Some examples: + +When programmers talk about functions though they often mean **expressions**: methods, procedures, and the likes. This is where some of the misconceptions regarding e.g. [Purity](#purity) and [Side effects](#side-effects) as special to some subset of functions come from, so that they need to be adressed here. What we really mean to say is: An expression which does not produce any side-effects (or: is pure) is a function. Programmers also have a concept of *functions expecting more than one parameter*, although those are *convenience methods* for their [curried forms](#currying). And rightfully so! Convenience is an important aspect of programming. + +```js +// not a function, but an expression or more specifically a method +// add :: (number, number) -> number +const add = (a, b) => a + b + +// add :: number => number => number +// curried form: a function - taking one argument and returning a value, in this case another function +const addCurried = a => b => a + b +add(1, 2) // might be considered more convenient than addCurried(1)(2) +``` + +It's totally fine to use the term "function" in a more loose way – depending on context –, but keep in mind its original meaning as *side-effect-free* or *pure* is often implicit with resources like the documentation of your favourite [fp libraries](#functional-programming-libraries-in-javascript). + +## Partial function +A partial function is a function which may not be defined for all inputs - it might return an unexpected result with some inputs or it may never terminate. Partial functions add cognitive overhead, they are harder to reason about and they can lead to runtime errors. Some examples: ```js // example 1: sum of the list // sum :: [Number] -> Number @@ -949,8 +968,10 @@ times(3)(console.log) times(-1)(console.log) // RangeError: Maximum call stack size exceeded ``` -### Avoiding partial functions -Partial functions are dangerous, you can sometimes get the expected result, sometimes the wrong result, and sometimes your function can't stop the calculations at all. The input of partial functions should be always checked, and it can be hard to track all edge cases through entire applications, the easiest way to deal with it it's just to convert all partial functions to the total. General advice can be the usage of `Option` type, providing default values for edge cases and checking function conditions to make them always terminate: + +### Dealing with partial functions +Partial functions are dangerous as they need to be treated with great caution. You might get an unexpected (wrong) result or run into runtime errors. Sometimes a partial function might not return at all. Being aware of and treating all these edge cases accordingly can become very tedious. +Fortunately a partial function can be converted to a regular (or total) one. We can provide default values or use guards to deal with inputs for which the (previously) partial function is undefined. Utilizing the [`Option`](#Option) type, we can yield either `Some(value)` or `None` where we would otherwise have behaved unexpectedly: ```js // example 1: sum of the list // we can provide default value so it will always return result @@ -963,7 +984,7 @@ sqrt([]) // 0 // change result to Option // first :: [A] -> Option A const first = a => a.length ? Some(a[0]) : None() -first([[42]]).map(a => console.log(a)) // 42 +first([42]).map(a => console.log(a)) // 42 first([]).map(a => console.log(a)) // console.log won't execute at all //our previous worst case first([[42]]).map(a => console.log(a[0])) // 42 @@ -983,7 +1004,7 @@ times(3)(console.log) times(-1)(console.log) // won't execute anything ``` -If you will change all your functions from partial to total, it can prevent you from having runtime exceptions, will make code easier to reason about and easier to maintain. +Making your partial functions total ones, these kinds of runtime errors can be prevented. Always returning a value will also make for code that is both easier to maintain as well as to reason about. ## Functional Programming Libraries in JavaScript From c77168a62c923aae444de0c4c622edd50566c2d4 Mon Sep 17 00:00:00 2001 From: Rea Sand Date: Mon, 29 Oct 2018 09:51:19 +0100 Subject: [PATCH 32/43] chore: Minor adjustments to function section --- readme.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/readme.md b/readme.md index 7f8a2ed..0a4c2ac 100644 --- a/readme.md +++ b/readme.md @@ -910,9 +910,7 @@ getNestedPrice({item: {price: 9.99}}) // Some(9.99) `Option` is also known as `Maybe`. `Some` is sometimes called `Just`. `None` is sometimes called `Nothing`. ## Function -Category Threory: A function is just an arrow between types. It has a direction. Replace arrow with mapping maybe? - -A **function** `f: A -> B` maps every element from its domain (A) to an element in its co-domain (B); or in other words: takes exactly one argument and maps it to exactly one (and always the same) value. That value depends entirely on the argument. This is what makes functions so pleasant to work with: there is no room for side-effects; a function is always pure – by definition. Functions exhibit [referential transparency](#referential-transparency). +A **function** `f: A -> B` maps every element of type A to an element of type B. It takes *exactly one* argument and maps it to exactly one (and always the same) value. That value depends entirely on the argument. This is what makes functions so pleasant to work with: there is no room for side-effects; a function is always pure – by definition. Functions exhibit [referential transparency](#referential-transparency) which allow for [equational reasoning](#equational-reasoning). A very simple example is the `identity` function: ```js @@ -925,7 +923,7 @@ or `negate`: const negate = value => !value ``` -When programmers talk about functions though they often mean **expressions**: methods, procedures, and the likes. This is where some of the misconceptions regarding e.g. [Purity](#purity) and [Side effects](#side-effects) as special to some subset of functions come from, so that they need to be adressed here. What we really mean to say is: An expression which does not produce any side-effects (or: is pure) is a function. Programmers also have a concept of *functions expecting more than one parameter*, although those are *convenience methods* for their [curried forms](#currying). And rightfully so! Convenience is an important aspect of programming. +When programmers talk about functions though they often mean **expressions**: methods, procedures, and the likes. This is where some of the misconceptions regarding e.g. [purity](#purity) and [side effects](#side-effects) as special to some subset of function come from. What we really mean to say is: An expression which does not produce any side-effects (or: is pure) is a function. Programmers also have a concept of *functions expecting more than one parameter*, although those are *convenience methods* for their [curried forms](#currying). And rightfully so! Convenience is an important aspect of programming. ```js // not a function, but an expression or more specifically a method From 1e8238608b368d608f38f5ad2d82d47533ace729 Mon Sep 17 00:00:00 2001 From: Rea Sand Date: Sat, 3 Nov 2018 18:37:23 +0100 Subject: [PATCH 33/43] refactor: function - more concise wording --- readme.md | 41 ++++++++++++++++++----------------------- 1 file changed, 18 insertions(+), 23 deletions(-) diff --git a/readme.md b/readme.md index 0a4c2ac..95873f7 100644 --- a/readme.md +++ b/readme.md @@ -910,33 +910,28 @@ getNestedPrice({item: {price: 9.99}}) // Some(9.99) `Option` is also known as `Maybe`. `Some` is sometimes called `Just`. `None` is sometimes called `Nothing`. ## Function -A **function** `f: A -> B` maps every element of type A to an element of type B. It takes *exactly one* argument and maps it to exactly one (and always the same) value. That value depends entirely on the argument. This is what makes functions so pleasant to work with: there is no room for side-effects; a function is always pure – by definition. Functions exhibit [referential transparency](#referential-transparency) which allow for [equational reasoning](#equational-reasoning). - -A very simple example is the `identity` function: -```js -// identity :: a -> a -const identity = a => a -``` -or `negate`: -```js -// negate :: Boolean -> Boolean -const negate = value => !value -``` - -When programmers talk about functions though they often mean **expressions**: methods, procedures, and the likes. This is where some of the misconceptions regarding e.g. [purity](#purity) and [side effects](#side-effects) as special to some subset of function come from. What we really mean to say is: An expression which does not produce any side-effects (or: is pure) is a function. Programmers also have a concept of *functions expecting more than one parameter*, although those are *convenience methods* for their [curried forms](#currying). And rightfully so! Convenience is an important aspect of programming. +#### Definition +A **function** is a special kind of language construct: often specified as an arrow or lambda expression - an anonymous or named block of code (the body) with optional parameters. It allows us to treat a piece of code as data and e.g. pass it to methods: ```js -// not a function, but an expression or more specifically a method -// add :: (number, number) -> number -const add = (a, b) => a + b - -// add :: number => number => number -// curried form: a function - taking one argument and returning a value, in this case another function -const addCurried = a => b => a + b -add(1, 2) // might be considered more convenient than addCurried(1)(2) +button.onClick(e => console.log("the button has been clicked")) // valid function, but with a side effect (see below) ``` -It's totally fine to use the term "function" in a more loose way – depending on context –, but keep in mind its original meaning as *side-effect-free* or *pure* is often implicit with resources like the documentation of your favourite [fp libraries](#functional-programming-libraries-in-javascript). +```js +// times2 :: Number -> Number +const times2 = n => n * 2 + +[1, 2, 3].map(times2) // [2, 4, 6] +``` + +#### Differentiation +Functional programming has its origins in mathematics and so do a lot of its terms. We hence need to differentiate between the concept of a function and its implementation as a language construct (as outlined above): In terms of set theory, a function `f: X -> Y` is an arrow between two sets `X` and `Y`. It maps *every* element in its *domain* `X` to an element in its *codomain* `Y` (note the use of singular here). + + +Translating this into the language of computer science, a function is an expression with **exactly one (immutable)** parameter and **exactly one** return value. That value depends entirely on the argument which makes functions context-independant. This property is called [referential transparency](#referential-transparency) which allows for [equational reasoning](#equational-reasoning). Its mathematical origin also necessitates the absence of hidden [side effects](#side-effects) - a function is always [pure](#purity), by definition. These features make functions (as defined by mathematics) so pleasant to work with: they are entirely deterministic and therefore predictable. + + +Contrast this with the definition above: none of the aforementioned constrains are baked into the language constructs we need to deal with. They have been sacrificed in part for pragmatism, convenience, and expressiveness - useful features of programming languages. This mismatch the concept of a function and its concrete implementation must be accounted for by the programmer; she must appreciate the principles functional programming is grounded on in order to benefit from its promises. ## Partial function A partial function is a function which may not be defined for all inputs - it might return an unexpected result with some inputs or it may never terminate. Partial functions add cognitive overhead, they are harder to reason about and they can lead to runtime errors. Some examples: From 0ce557945eb72042c3cb3da1a1784a69d6d062d0 Mon Sep 17 00:00:00 2001 From: Rea Sand Date: Sat, 3 Nov 2018 18:39:52 +0100 Subject: [PATCH 34/43] chore: Remove inline comment --- readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.md b/readme.md index 95873f7..1cb2850 100644 --- a/readme.md +++ b/readme.md @@ -914,7 +914,7 @@ getNestedPrice({item: {price: 9.99}}) // Some(9.99) A **function** is a special kind of language construct: often specified as an arrow or lambda expression - an anonymous or named block of code (the body) with optional parameters. It allows us to treat a piece of code as data and e.g. pass it to methods: ```js -button.onClick(e => console.log("the button has been clicked")) // valid function, but with a side effect (see below) +button.onClick(e => console.log("the button has been clicked")) ``` ```js From 5ee03c4877362edc763198d5fcb3ee568035e517 Mon Sep 17 00:00:00 2001 From: Rea Sand Date: Sat, 3 Nov 2018 18:42:54 +0100 Subject: [PATCH 35/43] chore: function - Add forgotten word --- readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.md b/readme.md index 1cb2850..a8ef6d6 100644 --- a/readme.md +++ b/readme.md @@ -931,7 +931,7 @@ Functional programming has its origins in mathematics and so do a lot of its ter Translating this into the language of computer science, a function is an expression with **exactly one (immutable)** parameter and **exactly one** return value. That value depends entirely on the argument which makes functions context-independant. This property is called [referential transparency](#referential-transparency) which allows for [equational reasoning](#equational-reasoning). Its mathematical origin also necessitates the absence of hidden [side effects](#side-effects) - a function is always [pure](#purity), by definition. These features make functions (as defined by mathematics) so pleasant to work with: they are entirely deterministic and therefore predictable. -Contrast this with the definition above: none of the aforementioned constrains are baked into the language constructs we need to deal with. They have been sacrificed in part for pragmatism, convenience, and expressiveness - useful features of programming languages. This mismatch the concept of a function and its concrete implementation must be accounted for by the programmer; she must appreciate the principles functional programming is grounded on in order to benefit from its promises. +Contrast this with the definition above: none of the aforementioned constrains are baked into the language constructs we need to deal with. They have been sacrificed in part for pragmatism, convenience, and expressiveness - useful features of programming languages. This mismatch between the concept of a function and its concrete implementation must be accounted for by the programmer; she must appreciate the principles functional programming is grounded on in order to benefit from its promises. ## Partial function A partial function is a function which may not be defined for all inputs - it might return an unexpected result with some inputs or it may never terminate. Partial functions add cognitive overhead, they are harder to reason about and they can lead to runtime errors. Some examples: From c878e19ca7604d4037f189fff3c85996ef2114be Mon Sep 17 00:00:00 2001 From: Rea Sand Date: Sat, 3 Nov 2018 18:48:52 +0100 Subject: [PATCH 36/43] refactor: function - drop superfluous sentence --- readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.md b/readme.md index a8ef6d6..209ef49 100644 --- a/readme.md +++ b/readme.md @@ -931,7 +931,7 @@ Functional programming has its origins in mathematics and so do a lot of its ter Translating this into the language of computer science, a function is an expression with **exactly one (immutable)** parameter and **exactly one** return value. That value depends entirely on the argument which makes functions context-independant. This property is called [referential transparency](#referential-transparency) which allows for [equational reasoning](#equational-reasoning). Its mathematical origin also necessitates the absence of hidden [side effects](#side-effects) - a function is always [pure](#purity), by definition. These features make functions (as defined by mathematics) so pleasant to work with: they are entirely deterministic and therefore predictable. -Contrast this with the definition above: none of the aforementioned constrains are baked into the language constructs we need to deal with. They have been sacrificed in part for pragmatism, convenience, and expressiveness - useful features of programming languages. This mismatch between the concept of a function and its concrete implementation must be accounted for by the programmer; she must appreciate the principles functional programming is grounded on in order to benefit from its promises. +Contrast this with the definition above: none of the aforementioned constrains are baked into the language constructs we need to deal with. They have been sacrificed in part for pragmatism, convenience, and expressiveness - useful features of programming languages. This mismatch between the concept of a function and its concrete implementation must be accounted for by the programmer. ## Partial function A partial function is a function which may not be defined for all inputs - it might return an unexpected result with some inputs or it may never terminate. Partial functions add cognitive overhead, they are harder to reason about and they can lead to runtime errors. Some examples: From ccd128abb552b27f0894d831927ba5ca946bf5bf Mon Sep 17 00:00:00 2001 From: Rea Sand Date: Sat, 3 Nov 2018 19:28:43 +0100 Subject: [PATCH 37/43] refactor: function - rephrasing the last paragraph --- readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.md b/readme.md index 209ef49..8f516a2 100644 --- a/readme.md +++ b/readme.md @@ -931,7 +931,7 @@ Functional programming has its origins in mathematics and so do a lot of its ter Translating this into the language of computer science, a function is an expression with **exactly one (immutable)** parameter and **exactly one** return value. That value depends entirely on the argument which makes functions context-independant. This property is called [referential transparency](#referential-transparency) which allows for [equational reasoning](#equational-reasoning). Its mathematical origin also necessitates the absence of hidden [side effects](#side-effects) - a function is always [pure](#purity), by definition. These features make functions (as defined by mathematics) so pleasant to work with: they are entirely deterministic and therefore predictable. -Contrast this with the definition above: none of the aforementioned constrains are baked into the language constructs we need to deal with. They have been sacrificed in part for pragmatism, convenience, and expressiveness - useful features of programming languages. This mismatch between the concept of a function and its concrete implementation must be accounted for by the programmer. +Contrast this with the definition above: none of the aforementioned constrains are baked into the language constructs we need to deal with. They have been sacrificed in part for pragmatism, convenience, and expressiveness - useful, powerful, and at times dangerous features of programming languages. This mismatch between the concept of a function and its concrete implementation must be accounted for by the programmer if she wants to benefit from the promises of functional programming. ## Partial function A partial function is a function which may not be defined for all inputs - it might return an unexpected result with some inputs or it may never terminate. Partial functions add cognitive overhead, they are harder to reason about and they can lead to runtime errors. Some examples: From c23510813e87284ff4f0d6239fc7b9c3bb925120 Mon Sep 17 00:00:00 2001 From: Rea Sand Date: Sun, 11 Nov 2018 13:47:22 +0100 Subject: [PATCH 38/43] refactor: function - drastically shorten content --- readme.md | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/readme.md b/readme.md index 8f516a2..144bb83 100644 --- a/readme.md +++ b/readme.md @@ -910,12 +910,7 @@ getNestedPrice({item: {price: 9.99}}) // Some(9.99) `Option` is also known as `Maybe`. `Some` is sometimes called `Just`. `None` is sometimes called `Nothing`. ## Function -#### Definition -A **function** is a special kind of language construct: often specified as an arrow or lambda expression - an anonymous or named block of code (the body) with optional parameters. It allows us to treat a piece of code as data and e.g. pass it to methods: - -```js -button.onClick(e => console.log("the button has been clicked")) -``` +A **function** `f :: A => B` is an expression - often called arrow or lambda expression - with **exactly one (immutable)** parameter of type `A` and **exactly one** return value of type `B`. That value depends entirely on the argument, making functions context-independant, or [referentially transparent](#referential-transparency). What is implied here is that a function must not produce any hidden [side effects](#side-effects) - a function is always [pure](#purity), by definition. These properties make functions pleasant to work with: they are entirely deterministic and therefore predictable. Functions enable working with code as data, abstracting over behaviour: ```js // times2 :: Number -> Number @@ -924,15 +919,6 @@ const times2 = n => n * 2 [1, 2, 3].map(times2) // [2, 4, 6] ``` -#### Differentiation -Functional programming has its origins in mathematics and so do a lot of its terms. We hence need to differentiate between the concept of a function and its implementation as a language construct (as outlined above): In terms of set theory, a function `f: X -> Y` is an arrow between two sets `X` and `Y`. It maps *every* element in its *domain* `X` to an element in its *codomain* `Y` (note the use of singular here). - - -Translating this into the language of computer science, a function is an expression with **exactly one (immutable)** parameter and **exactly one** return value. That value depends entirely on the argument which makes functions context-independant. This property is called [referential transparency](#referential-transparency) which allows for [equational reasoning](#equational-reasoning). Its mathematical origin also necessitates the absence of hidden [side effects](#side-effects) - a function is always [pure](#purity), by definition. These features make functions (as defined by mathematics) so pleasant to work with: they are entirely deterministic and therefore predictable. - - -Contrast this with the definition above: none of the aforementioned constrains are baked into the language constructs we need to deal with. They have been sacrificed in part for pragmatism, convenience, and expressiveness - useful, powerful, and at times dangerous features of programming languages. This mismatch between the concept of a function and its concrete implementation must be accounted for by the programmer if she wants to benefit from the promises of functional programming. - ## Partial function A partial function is a function which may not be defined for all inputs - it might return an unexpected result with some inputs or it may never terminate. Partial functions add cognitive overhead, they are harder to reason about and they can lead to runtime errors. Some examples: ```js From ead281f50ea0051219ca2fd6ee568799b1966224 Mon Sep 17 00:00:00 2001 From: Rea Sand Date: Sun, 11 Nov 2018 13:58:43 +0100 Subject: [PATCH 39/43] refactor: partial function - Minor adjustments --- readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.md b/readme.md index 144bb83..94a50c6 100644 --- a/readme.md +++ b/readme.md @@ -920,7 +920,7 @@ const times2 = n => n * 2 ``` ## Partial function -A partial function is a function which may not be defined for all inputs - it might return an unexpected result with some inputs or it may never terminate. Partial functions add cognitive overhead, they are harder to reason about and they can lead to runtime errors. Some examples: +A partial function is a [function](#function) which is not defined for all arguments - it might return an unexpected result or may never terminate. Partial functions add cognitive overhead, they are harder to reason about and can lead to runtime errors. Some examples: ```js // example 1: sum of the list // sum :: [Number] -> Number From 7f6f4125527e9da05433d411965a7b198a353f2d Mon Sep 17 00:00:00 2001 From: Miroslav Petrik Date: Tue, 25 Dec 2018 13:19:53 +0100 Subject: [PATCH 40/43] fix partial function `sum` example --- readme.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/readme.md b/readme.md index 94a50c6..c40fed8 100644 --- a/readme.md +++ b/readme.md @@ -926,7 +926,7 @@ A partial function is a [function](#function) which is not defined for all argum // sum :: [Number] -> Number const sum = arr => arr.reduce((a, b) => a + b) sum([1, 2, 3]) // 6 -sqrt([]) // TypeError: Reduce of empty array with no initial value +sum([]) // TypeError: Reduce of empty array with no initial value // example 2: get the first item in list // first :: [A] -> A @@ -957,7 +957,7 @@ Fortunately a partial function can be converted to a regular (or total) one. We // sum :: [Number] -> Number const sum = arr => arr.reduce((a, b) => a + b, 0) sum([1, 2, 3]) // 6 -sqrt([]) // 0 +sum([]) // 0 // example 2: get the first item in list // change result to Option From c6dc8487e565b291126769947eca1bb15068adba Mon Sep 17 00:00:00 2001 From: Amila Welihinda Date: Wed, 26 Dec 2018 18:25:45 -0800 Subject: [PATCH 41/43] Remove WIP statement from README This WIP statement was added 2 years ago. It seems like this project has reached a point of maturity I think it makes sense to remove this. --- readme.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/readme.md b/readme.md index c40fed8..0625dde 100644 --- a/readme.md +++ b/readme.md @@ -4,8 +4,6 @@ Functional programming (FP) provides many advantages, and its popularity has bee Examples are presented in JavaScript (ES2015). [Why JavaScript?](https://github.com/hemanth/functional-programming-jargon/wiki/Why-JavaScript%3F) -*This is a [WIP](https://github.com/hemanth/functional-programming-jargon/issues/20); please feel free to send a PR ;)* - Where applicable, this document uses terms defined in the [Fantasy Land spec](https://github.com/fantasyland/fantasy-land) __Translations__ From b593d7c1ca70711c31d723006d8522eaac50d329 Mon Sep 17 00:00:00 2001 From: Edgar Date: Wed, 6 Feb 2019 12:47:20 +0400 Subject: [PATCH 42/43] fix contract function return type --- readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.md b/readme.md index c40fed8..939540c 100644 --- a/readme.md +++ b/readme.md @@ -343,7 +343,7 @@ const predicate = (a) => a > 2 A contract specifies the obligations and guarantees of the behavior from a function or expression at runtime. This acts as a set of rules that are expected from the input and output of a function or expression, and errors are generally reported whenever a contract is violated. ```js -// Define our contract : int -> int +// Define our contract : int -> boolean const contract = (input) => { if (typeof input === 'number') return true throw new Error('Contract violated: expected int -> int') From 62bc8a59f564d3efb2cc615376af2afd47d6e02e Mon Sep 17 00:00:00 2001 From: Edgar Date: Wed, 6 Feb 2019 12:49:39 +0400 Subject: [PATCH 43/43] fix contract function type --- readme.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/readme.md b/readme.md index 939540c..a4d411b 100644 --- a/readme.md +++ b/readme.md @@ -346,13 +346,13 @@ A contract specifies the obligations and guarantees of the behavior from a funct // Define our contract : int -> boolean const contract = (input) => { if (typeof input === 'number') return true - throw new Error('Contract violated: expected int -> int') + throw new Error('Contract violated: expected int -> boolean') } const addOne = (num) => contract(num) && num + 1 addOne(2) // 3 -addOne('some string') // Contract violated: expected int -> int +addOne('some string') // Contract violated: expected int -> boolean ``` ## Category