<<

M U F I

Functional Programming in JavaScript

B’

Oliver ˝dzi

Brno, Fall 2017

Declaration

Hereby I declare that this paper is my original authorial work, which I have worked out on my own. All sources, references, and literature used or excerpted during elaboration of this work are properly cited and listed in complete reference to the due source.

Oliver R˝dzi

Advisor: prof. RNDr. Jií Barnat Ph..

i

Acknowledgement

First, I would like to express my deepest appreciation to my thesis advisor prof. RNDr. Jií Barnat, Ph. D. - without his guidance and persistent help, this bachelor thesis would not have been possible. I would also like to acknowledge all my friends and colleagues at Webscope, for their valuable inputs and whenever I was struggling. Finally, I must express my very profound gratitude to my parents and to my amazing girlfriend for providing me with unfailing support and continuous encouragement throughout my years of study and through the process of researching and writing this thesis. This accomplishment would not have been possible without them. Thank you.

iii Abstract

The objective of this thesis is to compare and analyze the libraries for in JavaScript, how they dier from Haskell language, and what are the benefits they provide for JavaScript. To further evaluate usage and advantages of these libraries, appli- cation/game was created, which focuses on the advantages of using functional programming, while also teaching the player functional programming principles and how to use them ectively in JavaScript.

iv Keywords

JavaScript, Ramda.js, Folktale, Haskell, Elm, Lodash, Lazy.js, Under- score

v

Contents

1 Introduction 1 1.1 Thesis structure ...... 1

2 Functional and 3

3 Haskell compared to Elm 7 3.1 Haskell ...... 8 3.2 Elm ...... 9 3.3 Conclusion ...... 11

4 Functional libraries in JavaScript 13 4.1 Underscore.js ...... 14 4.2 Lodash ...... 15 4.3 Lazy.js ...... 15 4.4 Ramda.js ...... 17 4.5 Immutable.js ...... 20 4.6 Folktale ...... 21

5 Practical segment 23 5.1 Implementation technologies and processes ...... 23 5.1.1 HTML and CSS ...... 23 5.1.2 React ...... 23 5.1.3 Yarn ...... 27 5.2 First concept of the application ...... 28 5.3 Implementation of the application ...... 29 5.4 Testing ...... 31

6 Conclusion 35

Bibliography 37

A How to install and run the application 39

B Source codes 41

vii

1 Introduction

In recent years, the world of JavaScript has changed a lot. New frame- works and libraries emerged and ECMAScript2015 definitely changed the way web developers write their applications. Functional programming in JavaScript also saw an increase in popularity. Functional-like libraries, such as Underscore.js or Lodash, made it easier to work with arrays, objects, strings, numbers, et cetera. However, they still lacked some of the truly functional features, most noticeably of functions. On the other hand, Ramda.js strongly resembles some of the Haskell functionality. Designed specifically for a functional programming style1, it provides automatically curried functions, making composition easier. Moreover, since Ramda.js does not mutate its data, it works well with JavaScript frameworks that depend on immutability, such as Redux. To explore all possibilities of functional JavaScript, we will also have a look at Elm. Even though Elm is not a library, but a complete language on its own, Elm compiles to JavaScript and can showcase what might be possible to do with JavaScript in the future. The objective of this thesis is to present advantages of above- mentioned approaches to JavaScript programming and to research aspects in which it is better than more common imperative program- ming.

1.1 Thesis structure

In the first part, we will focus on defining both functional program- ming and imperative programming. Also, this chapter points out key dierences between imperative and functional programming. After we establish these core concepts, we can progress further to examine functional programming by inspecting the most popular functional language at present, Haskell, and compare it to another , Elm, which compiles to JavaScript. We will

1. See http://ramdajs.com/.

1 .I then continue to explore what Elm has in common with Haskell and what are its shortcomings. The next part of this thesis is going to explore the world of JavaScript libraries with the focus on their usage and similarities. Afterwards, we will examine the performance, code readability and shortcomings of those libraries. This will be followed by a summary stating the reasons why to use or not to use some of them. In the practical segment, we are going to evaluate the application that was programmed as a part of this thesis, describing technologies used and its design. We will go through the first concept, summa- rizing what the requirements for this application were, then we will progress to further examine the implementation itself. Afterwards, we will check whether the application satisfies the functional and non-functional requirements. Finally, we are going to summarize what we have learned in this thesis and assess where there is an opportunity to dig deeper in both theoretical and practical segments.

2 2 Functional and imperative programming

In this chapter, we are going to establish the terms functional and im- perative programming. Then we are going to focus on how functional programming diers from imperative programming. Definition 2.0.1. Functional programming In functional programming, programs are executed by evaluating expressions, in contrast with imperative programming where pro- grams are composed of statements which change global state when executed. Functional programming typically avoids using mutable state.[1] Definition 2.0.2. Imperative programming Imperative programming is a paradigm of in which a program describes a sequence of steps that change the state of the computer. Unlike , which describes "what" a program should accomplish, imperative programming ex- plicitly tells the computer "how" to accomplish it. Programs written this way often compile to binary executables that run more eciently since all CPU instructions are themselves imperative statements.[2]

Dierences between the imperative and functional programming With the imperative approach, the programmer is writing exact steps that computer needs to do in order to meet the goal. This is sometimes referred to as algorithmic programming. On the other hand, functional approach involves composing the problem in a set of functions to be executed1.

Changes of state through functions In imperative programming, the state of an application is changed with commands in the source code, i.e. through an assignment. Functions in imperative programming often have side eects that may change the state of the application. Because of this, functions that do not have return make sense.

1. See https://msdn.microsoft.com/en-us/library/mt693186.aspx

3 .F

In contrast to imperative programming, functional programming functions are pure - they do not have side eects. This means that the output of the function is dependent only on the arguments provided to the function, so calling the same function twice with the same arguments always results in the same output. This is often not the case for functions in imperative programming, where functions can depend on the local or global state. Removing side eects from functions makes it easier to track and understand the behavior of an application, which is one of the key advantages of the functional programming.

Programmer approach In imperative programming, the developer thinks how to write algo- rithms and how to track any changes of the state. To control the flow of an application, the developer is using loops, conditions and function calls. Those functions are often impure, therefore can change the state of the application. On the other hand, in functional programming, the developer is trying to compose the problem as a set of functions to execute. In other words, the developer thinks about what state is desired, and what transformations are needed to get into that state. To control the flow of the application, the programmer uses pure functions and .

Order of execution and primary manipulation unit In imperative programming, variables are assigned values, which are changed as the program executes. Because of this, other expressions in program depend on these variable values. If the order of execution should change, and variables are not assigned values in correct order, then expressions which use those variables may not be correct as a side eect. As a consequence of this, the order of execution has high importance. Contrary to this, functional programming uses pure functions and immutable variables so there is no side eect of any changes done to the variables elsewhere in the code. Because of this, the execution order has little importance. Moreover, functional languages often use this flexibility in execution to achieve the best performance.

4 .F

In functional programming, the developer uses functions mainly as first-class objects and data collections, while instances of classes are used in imperative programming.

5

3 Haskell compared to Elm

This chapter is going to investigate similarities and dierences between Haskell, currently most popular functional programming language, and Elm, functional programming language compiled to JavaScript. Firstly, we will summarize how each of them works and what their core principles are; secondly, we will compare their similarities and dierences.

Definition 3.0.1. A pure function is a function that depends only on its declared input and its to produce its output. It does not read any other value from “the outside world” — the world outside of the function’s — and it does not modify any values in the outside world.[3]

Definition 3.0.2. Purely functional language Programing language is purely functional when every function’s outcome depends only on its arguments, not on the global or local state of the application. In other words, a programming language is purely functional when all of its functions are pure.1

Definition 3.0.3. In programming language theory, lazy evaluation is an which delays the evaluation of an until its value is needed and which also avoids repeated evaluations (sharing).[5]

Definition 3.0.4. Strict evaluation In programming language theory, strict evaluation or eager - uation is an evaluation strategy where all expressions are evaluated as soon as they are bound to a variable. In the strict evaluation, each argument is evaluated exactly once.

1. For the purpose of this thesis, I decided to use this definition, but it is important to note that the exact dierence between pure and impure functional programming is a matter of controversy.[4]

7 .H E 3.1 Haskell

Haskell is a standardized, general-purpose, purely functional pro- gramming language, with non-strict semantics and strong static typ- ing.[6]

Purely functional with lazy evaluation

In Haskell, every function is pure, therefore Haskell satisfies definition 3.0.2., and we can say that Haskell language is purely functional. Haskell is also using lazy evaluation, which means that programs can compose together very well, with an ability to write control con- structs by writing normal functions. The purity of Haskell code makes it easy to fuse chains of functions together, allowing performance benefits2.

Statically typed with

Every Haskell expression has a type, determined at the time when it compiles. If the expression does not match up at the time of compi- lation, the will reject it. Therefore, it is always certain that expressions have correct types, otherwise the program will not com- pile. As mentioned above, every Haskell expression has a type. However, the programmer does not have to explicitly type them. The types are inferred by unifying every type bidirectionally. Furthermore, the programmer can ask compiler for the types of expressions if needed.

Concurrent

Haskell comes with GHC compiler which provides support for par- allel and concurrent programming. The programmer just needs to import library Control.Concurrent and he has all tools he needs. Syn- chronization of the tasks is possible via various options.

2. See https://www.haskell.org/

8 .H E 3.2 Elm

Elm is a functional language that compiles to JavaScript. Elm purpose is to make the maintainability of an application easier while keeping a very strong emphasis on simplicity, ease-of-use and quality tooling3.

Purely functional with strict evaluation Every function in Elm is pure, therefore it satisfies definition 3.0.2., and we can say that Elm language is purely functional. In contrast to Haskell, and similarly to JavaScript, Elm is using strict evaluation. In a thesis written by Evan Czaplicki, creator of Elm, he mentions the two main reasons for choosing strict instead of lazy evaluation. First, JavaScript itself is strict, and since Elm compiles to JavaScript, it makes more sense to use the same evaluation. Second, the main one, is that functional and laziness do not work well together. It adds a lot of complexity to fix time and space leaks[7].

Figure 3.2.1: Elm provides very helpful hints why the program did not compile. This can be especially useful for people with writing disabilities, for example, dyslectics or dysgraphics.

Statically typed with type inference and enforced semantic versioning Unlike JavaScript, Elm is typed statically. Type annotations are not nec- essary, but strongly encouraged. Similarly to Haskell, type annotations are placed on the line above the definition. Types include primitives like integers and strings, and basic data structures such as lists, tuples,

3. See http://elm-lang.org/

9 .H E and records. Functions have types written with arrows, for example round : Float -> Int. Union types allow the programmer to create custom types to represent data in a way that matches the problem domain[8]. Similarly to Haskell, Elm uses type inference to detect problems during compilation and reports if anything goes wrong. This way, no runtime exception will make it to the user and this makes refactoring easier. Furthermore, any errors found during compilation are very descriptive and the developer can often fix them with little eort. According to Elm language ocial web page, NoRedInk has 80k+ lines of Elm, and after more than a year in production, it still has not produced a single runtime exception4. Thanks to its enforced semantic versioning, Elm en- ables to easily identify any breaking API changes - see Figure 3.2.3.

Figure 3.2.2: Elm even ensure that if / then statements always return the same type, so the developer can always expect consistent data [9]

4. See http://elm-lang.org/

10 .H E

Figure 3.2.3: Elm compilers even ensure that if / then statements always return the same type, so we can always expect consistent data [10]

Great performance

When Elm is compared to major JavaScript front-end frameworks and libraries, we will find out that it does an outstanding job in keeping the application fast. Elm has its own virtual DOM implementation and it has all values immutable which makes it easier to generate fast JavaScript code.

3.3 Conclusion

After breaking down properties of both Elm and Haskell, we can conclude that they are similar in many aspects, but they also have a lot of dierences. Both are purely functional languages with strong statical typing and typing inference. Haskell enables the developer to use parallel and concurrent programming, whereas Elm is limited because in

11 .H E

JavaScript there are not many options to do this. There is a possibility to use an async construct in Elm, which can potentially make part of the program run separately, but in Haskell, it is much easier, since there is an entire library designed for this purpose. Each language evaluates expressions dierently. Elm uses strict evaluation, while Haskell uses lazy evaluation. Elm also comes with some features that are really handy in front- end development. Semantic versioning ensures that breaking changes in API will not break your application and provides very helpful hints why the program did not compile. Overall, the maintainability of Elm application is really high.

12 4 Functional libraries in JavaScript

In the previous chapter, we discussed what the properties of the purely functional language compiled to JavaScript are compared to Haskell. In this chapter, we are going to examine libraries that provide tools to write functional code directly in JavaScript. First, we will discuss what exactly each of the libraries does and what are pros and of using that library.

Definition 4.0.1. Currying In mathematics and , currying is the technique of translating the evaluation of a function that takes multiple arguments (or a tuple of arguments) into evaluating a sequence of functions, each with a single argument. [11]

Definition 4.0.2. Fantasy land Fantasy land is JavaScript library that provides a specification for interoperability of common algebraic structures in JavaScript.

Figure 4.1: Algebraic structures that Fantasy land specifies[12].

Definition 4.0.3. Shallow comparison When comparing values, shallow comparison for scalar values checks whether they are equal, however, for more complex values, it just checks by reference.

Definition 4.0.4. Monads Monad is a design pattern that defines how functions, actions, inputs, and outputs can be used together to build generic types, with the following organization:

13 .F S

1. Define a , and how values of that data type are com- bined. 2. Create functions that use the data type, and compose them together into actions, following the rules defined in the first step.[13] Example of a monad are data types Maybe or Just. Definition 4.0.5. Kleisli composition Kleisli composition is an advanced type of function composition, designed to function as a composition operator for functions that return monad.

4.1 Underscore.js

Underscore.js provides a set of utility functions for common program- ming tasks. However, instead of extending object prototypes, it opts for functional design. Underscore.js contains more than 100 functions that enable the developer to manipulate objects, arrays and functions. Underscore.js does not provide support for currying of functions.

Listing 4.1: Chained functions that return first five people in an array with first name Oliver in Underscore.js 1 // For purposes of this example , we will assume -

that people is an array filled with objects -

with property firstName. 2 const fivePeople = _.chain(people) 3 .pluck(firstName) 4 .filter(function(name) { 5 return name === Oliver; 6 }) 7 .take(5) 8 .value();

As we can see in Listing 4.1., Underscore also enables to chain functions together in case the developer wants to do multiple trans- formations on a variable. Chain function will return a wrapped object

14 .F J S

and each subsequent function call on this object will continue to return wrapped objects until value() function is called.

4.2 Lodash

Lodash was originally created to provide more consistent cross-environment iteration support for arrays, strings, objects, and arguments objects than Underscore.js. It has since become the superset of Underscore, providing more consistent API behavior and more features.[14] Furthermore, lodash/fp module promotes a more functional pro- gramming (FP) friendly style by exporting an instance of lodash with its methods wrapped to produce immutable auto-curried -first data-last methods.[15] Being forked from Underscore.js, we can see that that dierence in code between Listing 4.1 and 4.2 is insignificant.

Listing 4.2: Chained functions that return first five people in an array with first name Oliver in Lazy.js 1 // For purposes of this example , we will assume -

that people is an array filled with objects -

with property firstName. 2 Lodash.chain(people) 3 .map(firstName) 4 .filter(function(name) { 5 return name === Oliver; 6 }) 7 .take(5) 8 .value();

4.3 Lazy.js

As the name of the library suggests, Lazy.js main dierence from other functional JavaScript libraries is that it uses lazy evaluation1. Similarly to Lodash and Underscore.js, Lazy.js is functional utility library that

1. See definition 3.0.3

15 .F JS

provides set of functions for manipulating with object, arrays and functions. Lazy.js claims to have a comparable or a superior performance to Underscore.js or Lodash in most scenarios2, which is true based on performance test on Figure 4.1. The idea behind Lazy.js is to have almost an identical syntax to Underscore, so JavaScript developers are familiar with it, but instead of returning a fully populated array on every call, a sequence object is created with each method. Most importantly, no iteration takes place until developer calls each, and no intermediate arrays are created. If we compare code in listings 4.1 and 4.3, we can see that syntax is indeed very similar.

Listing 4.3: Chained functions that return first five people in an array with first name Oliver in Lazy.js

1 // For purposes of this example , we will assume -

that people is an array filled with objects -

with property firstName. 2 const fivePeople = Lazy(people) 3 .pluck(firstName) 4 .filter(function(name) { 5 return name === Oliver; 6 }) 7 .take(5) 8 .toArray();

Unfortunately, it looks like the development of Lazy.js is stagnating.

2. See https://github.com/dtao/lazy.js/

16 .F J S

Figure 4.2: Operations per second (OPS) of selected functional JavaScript libraries, with the code used for testing3. For each frame- work, the information about the code used for testing and how many OPS could be executed is given, with deviation percentage.

4.4 Ramda.js

JavaScript library Ramda.js is built to be a functional library. It provides the developer with pure, side-eect free functions. Functions in Ramda are automatically curried, therefore the devel- oper can easily build a new function just by not providing the final . Also, Ramda was designed to be convenient for function composition and currying - the data to be operated are generally sup-

3. More details at https://jsperf.com/lodash-vs-underscore-vs-lazy-js

17 .F JS

plied last, in contrast to Underscore.js or Lodash, which take data as the first parameter. Because of this, it is much easier to build functions using either compose or pipe functions that will build functions as sequences of simpler functions, each of which transforms the data and passes it along to the next.4 The dierence between using R.compose and R.pipe function is that R.compose performs right to left composition and R.pipe performs left to right function composition.

Listing 4.4: Composed function that returns first five people in an array with first name Oliver in Ramda.js. 1 // For purposes of this example , we will assume -

that people is an array filled with objects -

with property firstName. 2 const getFiveOlivers = R.compose( 3 R.take(5), 4 R.filter(name => name === Oliver), 5 R.pluck(firstName) 6 ); 7 const hints = getFiveOlivers(people);

Listing 4.5: Ramda also supports Kleisli composition of the provided functions through R.pipeK or R.composeK 1 // get :: String -> Object -> Maybe * 2 const get = 3 R.curry((prop, obj) => Maybe(obj[prop])) 4 // getStateCode :: Maybe String -> Maybe String 5 const getName = R.composeK( 6 R.compose(Maybe.of, R.toUpper), 7 get(name), 8 get(user), 9 ); 10 getName({user:{name: " oliver" }}); //=> Maybe. Just -

("OLIVER") 11 getName({}); //=> Maybe. Nothing()

4. See http://ramdajs.com/

18 .F J S

We can see on listing 4.4 that composing of functions indeed works really well in Ramda. Because the functions in Ramda are curried, we do not require data right away and we can easily create a function which can be later used with dierent data. On top of all that, Ramda.js can work with Monads, it supports Kleisli composition (Listing 4.5.) and has a great documentation.

Figure 4.3: More broad comparison of performances, with the focus on dierent functions. By looking at the figure, we can see that Ramda has a clear edge over other libraries in this particular scenario. It is interesting to note that by composing functions in Ramda, you will lose performance in order to gain readability and reusability.

4. More details at https://jsperf.com/performance-of-various-functional-js- libraries/1

19 .F JS 4.5 Immutable.js

Immutable.js provides the programmer with data structures that can- not be mutated, and every operation called on this will result in returning a new, changed instance. This library is inspired by functional programming environments, where the developer cannot mutate data structures.

Listing 4.6: Working with data type List from Immutable.js - any oper- ation in Immutable.js creates returns new value instead of mutating the old one. 1 const {List}=require(immutable); 2 const list1 = List([0, 1]); // list1 = [0, 1] 3 const list2 = list1.push(2,3); 4 // list2 = [0, 1, 2, 3], list1 = [0,1]

If the developer can be certain that data cannot be changed, it is possi- ble to make use of the following advantages:

• Value comparison can be optimized, deep object comparisons can become reference comparisons. Multiple front-end view libraries5 take advantage of this by performing a shallow com- parison on data, to determine which component needs to be updated.

• Copying items becomes a constant time operation.

• Because it is not possible to change state, writing pure functions with immutable data structures is more natural.

• Operations on Immutable.Seq data structure enables developer to optimize performance in certain scenarios by using lazy eval- uation. Advantages of working with Immutable.Seq are very similar to the ones library Lazy.js provides.

5. React.js even has class PureComponent which implements a shallow compare by default, to prevent unnecessary rerenders

20 .F J S 4.6 Folktale

Folktale is a library to support functional style of programming in JavaScript. Currently, Folktale provides utilities for combining func- tions, transforming objects, modeling data, handling errors, and con- currency6. Folktale provides three data types to help with error handling:

1. Maybe, for handling values that might not exist7. This can be a very useful feature when waiting for data to be fetched, since you can render a loader component until you get the correct data. See Listing 4.7.

2. Result, to represent the return values of functions that might fail.8

3. Validation is a structure that helps with validations9. Valida- tion function may succeed or fail and then help aggregate all failures.

6. See http://folktale.origamitower.com/docs/v2.0.0/overview/ 7. For example for Array.find 8. For example JSON.parse 9. Mainly form validations

21 .F JS

Listing 4.7: Folktale can use Maybe container for a value that might not be present instead of checking if names variable is empty or undefined. 1 import {Just, Nothing} from folktale/ data/ maybe; 2 import React from react; 3 class App extends React.Component { 4 this.state = { names: Nothing() }; 5 componentDidMount() { 6 this.setState({ 7 names: Just([Oliver, Filip, Hung]) 8 }); 9 } 10 render() { 11 return ( 12

13 { 14 this.state.items.cata({ 15 Just: ({ value }) => value, 16 Nothing: () => Loading ... 17 }) 18 } 19
20 ) 21 } 22 }

22 5 Practical segment

The main idea for this front-end application is to educate the user how to work in a functional-like manner in Ramda.js library. In this part of the thesis, we are going to discuss the practical as- pects of implementing an application and the process of its creation. Because the application needs to introduce the user to new technol- ogy, there are some key elements to consider before developing such application.

5.1 Implementation technologies and processes

5.1.1 HTML and CSS The triad of HTML, CSS and JavaScript are the cornerstone technolo- gies for the World Wide Web. Together, web pages use them to create visually attractive and responsive user interfaces for web pages, web applications or mobile applications. Abbreviation HTML stands for HyperText Markup Language, which is primarily dedicated to building web pages. HTML elements are described by tags which represent text, images, videos or other content, and Internet browsers use them to interpret the content of web page. HTML can embed programs written in JavaScript to add dynamic behavior to the page. Current version is HTML5[16]. Cascading Style Sheets (CSS) are used to describe the presentation of documents written in a markup language. It defines how elements of markup language should look like on a selected medium. Most often, it is used to style elements of HTML in front-end web development. CSS is designed to separate presentation and content. Each HTML element can be selected via selector1. Currently used version is CSS3[16].

5.1.2 React Because the goal of this implementation was to create a web applica- tion, choosing the right technology for its front-end was crucial. With recent trends and quick development in JavaScript, there were a lot of

1. Selector - the rule that chooses which HTML elements to choose.

23 .P options to choose from. When I was picking the right tool, I needed to consider the quality of documentation, performance, simplicity and maturity of the library/framework. I considered React, Vue, and even Elm or ReasonML (both functional languages compiled into JavaScript). However, in the end I reached the conclusion that both Elm and ReasonML would not be such great choices, simply because Ramda.js is not available for them. After considering other available options, I decided to choose React because of its simplicity, implementation of shadow DOM and my personal abilities to code in this library. React is a JavaScript library for building user interfaces. It was developed by in 2013 and it is currently used by major com- panies for their front-end solutions, i.e. Facebook, Skype, Netflix, Kiwi et cetera. React was designed to ease the development of interactive and reusable components[17]. Before we dive deeper into React advantages and structure, we should clarify that React is not a framework. Classic software architec- tural pattern for graphical user interfaces called Model-view-controller (MVC), describes three basic layers, that GUI application should con- tain. Model handles data, rules and behavior of an application. View represents visualized data and information and controller handles inputs and transforms them into data for model and view. React is handling the "view" part in MVC, therefore its main purpose is to visualize data and information. The main concepts of React are the components that represent dierent visual parts of the website, and one-way data binding, or uni-directional data flow. React claimed that one-way data binding is a feature of React, while two-way data binding is wrong and can produce a hard-to-understand and error-prone code. This was controversial at the time, because until then, MVC framework Angular 1, which was the most popular front-end JavaScript framework at the time, claimed that its two-way data binding is one of the main features of the framework.

24 .P

Figure 5.1.1: Basic component written in ES6 that displays text "Hello world" to the user.

The components used in React are JavaScript classes or functions returning other components. Their function could be described as building elements of the web page, they can have state and can be used within each other to build complex user interfaces. Components can be also written in the JSX syntax (Figure 5.1.2), what is the preferred solution in most cases as well. JSX is a syntactic extension to JavaScript. It looks like HTML and enables writing HTML into the JavaScript rather easily. As mentioned above, it is not necessary, but it is one of the React’s main advantages2. Because of the way React is designed, it forces the developer to declare simple view for each state of the application. The core of React then takes care of re-rendering and redrawing components that received this changed state. Thanks to this, only those components that were changed are re-rendered. Due to this declarative nature of React, it is easier to expect the correct system state and to debug errors in code.

2. See figures 5.1.1 and 5.1.2.

25 .P

Figure 5.1.2: Basic component written in ES6 + JSX that displays text "Hello world" to the user.

Create React App The significant element in this project was using another library of Facebook, called Create React App (CRA). This library helps with the correct setup of any projects written in React. CRA takes care of configuring the project bundler Webpack, transpiler babel and ESLint. No configuration by the user is required. Out of the box, the developer gets:

• React, JSX, ES6, Flow syntax support and syntax extras beyond ES6 (i.e. spread operator)

• A development server that lints for common errors

• Automatically adds prefixes to CSS for cross-browser support

• A build script, to bundle JS, CSS and images for production

26 .P

• An oine-first service worker and a web app manifest, meeting all the Progressive Web App criteria.

5.1.3 Yarn Yarn is a package manager for JavaScript that provides fast, reliable and secure dependency management.[18] Similar to (Node Pack- age Manager)3, Yarn provides packages of reusable code that the developer can combine together as needed. Because Yarn parallelizes operations, it is in some aspects significantly faster than NPM 4. It also uses checksums to verify the integrity of packages it runs. On the top of all that, Yarn provides a -file which ensures deterministic for package installation. The lock-file also ensures that everyone on the team has the same package version. Mainly because of the above-mentioned reasons, I decided to choose Yarn over NPM for this project.

Figure 5.1.3: Performance comparison between Yarn and NPM, tested on the project with over 2000 packages. The point of the test was to find out whether it is Yarn or NPM that can install the packages faster. The result was 69.67 seconds for Yarn, and 123.617 seconds for NPM. Due to many logs after running npm install, I removed it and used "..." as a placeholder instead.

3. See https://www.npmjs.com/ 4. I.e. package installation, see figure 5.1.3

27 .P 5.2 First concept of the application

In the first phase of application design, I created functional and non- functional requirements. Most of the requirements were known before I started working on this project, some of them were created as I implemented the application.

Functional requirements • Each level should have entry data, which will be visualized for the user.

• The application should show user desired output data for each level.

• There should be a guide on how to complete each level,

• Practice levels should be available to provide the user with the training of his newly acquired skill.

• The input of functions needs to be able to handle more than one function, to enable function composition in more dicult levels.

• The input of functions needs to have an auto-complete feature, to advise user which functions are available. Not all of Ramda.js functions need to be included as a data set to the auto-complete.

• The input of functions needs to transform entry data in real time and to provide the user with an instant response. An output of the currently entered user input will be shown.

• In each level, there should be a possibility to display a solution for it.

• After successful completion of the level, a button prompting the user to try the next level should appear.

• The user should be able to skip levels by selecting any level he desires in the menu.

28 .P

Non-functional requirements • The application should be visually appealing to the user.

• The user interface should be straightforward and easy to navi- gate.

• The application should be able to run on dierent platforms and browsers.

• The application should not stop working if the user loses con- nection to the Internet.

• The application should be responsive and work on mobile de- vices.

5.3 Implementation of the application

The web application was implemented by using tools listed in section 5.1. The core of the implementation was written in JavaScript5, with Create React App package, described in 5.1.2. subsection. In devel- opment, I used a lot of features of this standard, i.e. functions, classes, constants and other. For version control, I used a GitHub repository6. During the devel- opment of this application, the repository was private, however now the repository is public so anyone can potentially contribute. To have a better understanding of the implementation of this project, we will have a look at the file structure of the project (Fig- ure 5.3.1.). Source code of project 7 is located inside src folder. The project is then organized into three main folders:

• Components - this folder contains components that are display- ing data from Constants folder and also contain a logic which level should be displayed.

5. Using ES6 standard, see http://es6-features.org 6. Repository available at https://github.com/webscopeio/ramda-game 7. Omitting configuration files and .git, node_modules and public folders

29 .P

• Constants - in this folder, there are constants that are used in various components. Also, the functions for user input auto- complete are located inside this folder.

• Helpers - various helper functions are placed there8.

Figure 5.3.1: File structure of the Ramda-game project.

8. I.e. syntax highlighting

30 .P

Configuration files in the root directory of the project with names .firebaserc and firebase.json are files that configure deployment to the firebase hosting9. File package.json contains information about the application and specifies which dependencies are needed so the application can work correctly. After executing yarn10 command, those dependencies are installed into node_modules folder.

5.4 Testing

Functionality testing was done continuously, testing each level thor- oughly. After the development was over, approximately ten people started using it and reported bugs. The main issue to tackle here was probably the user interface and layout, especially on smaller displays and mobile devices. Functional and non-functional requirements also needed to be tested. Here are the selected requirements that were successfully im- plemented - the application should be responsive (Figure 5.4.1.), it should run on dierent browsers (Figure 5.4.1. - 5.4.4.) and the appli- cation should have some suggestion for functions (Figure 5.4.2).

9. Application is currently running on https://ramda-d18a8.firebaseapp.com/ 10. By running yarn command, Yarn will install all packages in the -dependencies, as was described in the 5.1.3. subsection

31 .P

Figure 5.4.1. - The application on the mobile phone.

32 .P

Figure 5.4.2. - Landing page of the application in Google Chrome browser.

Figure 5.4.3. - The application with correct solution in Google Chrome browser.

33 .P

Figure 5.4.4. - The application with opened suggestions in Safari browser.

34 6 Conclusion

The goal of this bachelor thesis was to explore the usage of functional programming in JavaScript and what dierent JavaScript libraries provide in that aspect. After careful examination of some of the libraries, we can divide them into two main groups. The first group that focuses on manipu- lation with data types1, and a second group that, besides manipula- tion with data types, provides new data structures2. Folktale library enriches JavaScript by implementing some of the data structures in Fantasy land specification3, such as Maybe and Just data structure, which can provide a clean solution to common JavaScript problems, as was shown in Listing 4.5. When comparing Elm to Haskell, we could see that even a language that is compiled into another language can have its benefits and its specific value and use. To evaluate this further, there is a possibility to dive deeper in this topic by comparing these two languages with ReasonML, which is also a language that compiles to JavaScript and should be similar to OCaml. The application developed as a part of this thesis provides the user with opportunities to explore one of the libraries, with guides to teach the user new options to write a JavaScript code. There are multiple levels focused on working with objects and arrays. There are also a couple of levels focused on function composition through R.compose and R.pipe functions in Ramda.js. In some of the levels, the user can click on a symbol next to the level name to start exercise on given topic. In the future, there is a possibility to add new levels dedicated to function composition and advanced topics such as lenses, R.converge or R.traverse.

1. Underscore.js, Lodash... 2. Immutable.js, Folktale... 3. Fantasy land - definition 4.0.2

35

Bibliography

1. KHAN, Aslam. Grokking Functional Programming. Manning Publica- tions, 2015. ISBN 9781617291838. 2. Definition of imperative programming [online]. Computer hope [visited on 2017-05-22]. Available from: http://www.computerhope.com/ jargon/i/imp-programming.htm. 3. ALEXANDER, Alvin. Functional Programming, Simplified. Kindle, 2017. 4. SABRY, A. M. R. What is a purely functional language? Journal of Func- tional Programming, Cambridge University Press, 1998. 5. REYNOLDS, John . Theories of programming languages. Cambridge University Press, 1998. ISBN 9780521594141. 6. PEYTON JONES, Simon. Haskell 98 Language and Libraries: The Revised Report. Cambridge University Press, 2003. ISBN 0521826144. 7. CZAPLICKI, Evan. Elm: Concurrent FRP for Functional GUIs. DLib Magazine [online]. 2005, vol. 11, no. 7/8 [visited on 2012-03-30]. ISSN 1082-9873. Available from: https://www.seas.harvard.edu/ sites/default/files/files/archived/Czaplicki.pdf. 8. Model The Problem [online]. Ocial Website of Elm language [visited on 2016-04-05]. Available from: http : / / elm - lang . org / blog / compilers-as-assistants. 9. Compilers as assistants [online]. Ocial Website of Elm language [vis- ited on 2015-11-19]. Available from: http://elm-lang.org/blog/ compilers-as-assistants. 10. Elm benchmark times [online]. Ocial Website of Elm language [visited on 2017-05-22]. Available from: http://elm-lang.org/. 11. Currying. Wikipedia. Available also from: https://en.wikipedia. org/wiki/Currying. 12. Fantasy Land Specification [online]. Fantasy Land ocial GitHub page [visited on 2017-04-12]. Available from: https : / / github . com / fantasyland/fantasy-land. 13. Monad (Functional programming) [online]. Wikipedia [visited on 2017-04-12]. Available from: https://en.wikipedia.org/wiki/Monad_(functional_ programming).

37 BIBLIOGRAPHY

14. Response on Lodash [online]. John Dalton and Michael Laargue [vis- ited on 2017-05-22]. Available from: http://stackoverflow.com/ questions/13789618/differences-between-lodash-and-underscore. 15. FP-Guide [online]. Lodash ocial GitHub page [visited on 2017-30-11]. Available from: https://github.com/lodash/lodash/wiki/FP- Guide. 16. DUCKETT, Jon. HTML and CSS: design and build websites. John Wiley & Sons, 2011. 17. A JavaScript library for building user interfaces - React [online]. Ocial React web site [visited on 2017-10-12]. Available from: https:// reactjs.org. 18. [online]. Ocial Yarn web site [visited on 2017-12-12]. Available from: https://yarnpkg.com/lang/en/.

38 A How to install and run the application

First, you are going to navigate to the application by placing source code into a folder and then in the terminal, in the same folder as application lies, call:

$cdramda-game

Make sure you already have Node.js1 and globally installed Yarn2. Afterwards, you can install the dependencies by running:

$sudoyarn

Then, simply call in the terminal:

$yarnstart

and if no error appears, the application should open in the browser at the URL http://localhost:3000/. You can also choose to go to the URL https://ramda-d18a8.firebaseapp.com/, where the application is already running. This was done by setting up the project in the Firebase, and calling:

$yarndeploy

1. Guide to Node.js installation can be found here https://nodejs.org/en/download/package-manager/ 2. Guide to Yarn installation is here https://yarnpkg.com/lang/en/docs/install/

39

B Source codes

Source codes are available inside the Information System of Masaryk university. Repository for this application is also available on GitHub1.

1. https://github.com/webscopeio/ramda-game

41