<<

DEGREE PROJECT IN COMPUTER ENGINEERING, FIRST CYCLE, 15 CREDITS STOCKHOLM, SWEDEN 2020

Investigating Reason as a substitute for JavaScript

AXEL PETTERSSON

KTH ROYAL INSTITUTE OF TECHNOLOGY SCHOOL OF ELECTRICAL ENGINEERING AND COMPUTER SCIENCE Investigation of Reason as a substitute for JavaScript

AXEL PETTERSSON

Degree Programme in Information and Communication Technology Date: June 4, 2020 Supervisor: Thomas Sjöland Examiner: Johan Montelius School of Electrical Engineering and Computer Science Host company: Slagkryssaren AB Swedish title: Undersökning av Reason som ett substitut till JavaScript Investigation of Reason as a substitute for JavaScript / Undersökning av Reason som ett substitut till JavaScript

c 2020 Axel Pettersson Abstract | i

Abstract

JavaScript has in recent years become one of the most utilized programming languages for developing different kinds of applications. However, even though it has received a lot of praise for its simplicity, versatility and highly active community, it lacks some functionalities and features that a lot of programmers highly value, like static and strict typing, compile-time debugging, and to not be required to make use of third-party libraries to integrate crucial functionality. However, several new languages built on top of JavaScript have been developed to address and resolve these issues developers find with JavaScript without losing the benefits that come with it. One of these super- set languages is Reason, the new syntax and toolchain powered by the OCaml compiler. This thesis aims to address whether there are scenarios where Reason could act as a reasonable substitute of JavaScript by investigating how the languages compare in regards to different criteria. The criteria examined are writability, data structures and typing, reliability and testing, community support, market demand, portability, and performance. The findings show that using Reason over JavaScript could result in higher reliability and robustness due to static type checking, compile-time debugging, and other usable feature like pattern matching and explicitly defined custom data structures, which is convenient when dealing with advanced data. On the other hand, Reason’s interoperability with JavaScript is something that is not very straight-forward and makes it difficult to integrate Reason into an existing JavaScript codebase or include one of the thousand of JavaScript- written dependencies available on . Furthermore, with Reason being a rather young language yet to be used by a larger audience, both the community support and market demand are a lot smaller than that of JavaScript and have yet to see a significant growth, which leads to questions about the overall survival of the language. Both of the languages have a significant role and contribute with different kind of functionality. However, with the non-straightforward interoperability, Reason loses a lot of potential benefits to be gained from JavaScript, which could be problematic in the long run and could impact the future of Reason.

Keywords Programming languages, Computer Science, JavaScript, Comparative Study, Reason ii | Abstract Sammanfattning | iii

Sammanfattning

JavaScript har under senare år blivit ett av de mest använda programmeringsspråken för att utveckla olika typer av applikationer. Men även om det har fått mycket beröm för sin enkelhet, mångsidighet och mycket aktivt nätgemenskap, saknar det vissa funktioner och egenskaper som många programmerare uppskattar mycket, som statisk och strikt typning, felsökning under kompilering och att inte vara I behov av tredjepartsbibliotek för att integrera grundläggande funktionalitet. Flera nya språk som är byggda ovanpå JavaScript har utvecklats för att lösa de problem som utvecklare har med JavaScript, utan att förlora fördelarna med det. Ett av dessa supersetsspråk är Reason, den nya syntaxen och verktygskedjan som drivs av OCaml-kompilatorn. Denna avhandling syfte är att utvärdera om det finns scenarier där Reason kan fungera som en rimlig ersättare för JavaScript, detta kommer genomföras genom att undersöka hur språken jämförs med varandra med avseende på olika kriterier. Kriterierna som undersöks är skrivbarhet, datastrukturer och typning, tillförlitlighet och testning, nätgemenskap, marknadsförfrågan, portabilitet, och prestanda. Resultaten visar att användning av Reason över JavaScript kan leda till högre tillförlitlighet på grund av statisk typkontroll, felsökning under kompilering och andra användbara funktioner som mönstermatchning och anpassade datastrukturer, båda underlättar vid hantering avancerade och komplexa datastrukturer. Däremot är Reasons kompabilitet med JavaScript komplicerad, vilket gör det svårt att integrera Reason i en befintlig JavaScript- kodbas eller inkludera ett av de tusentals JavaScript-skrivna biblioteken som finns tillgängliga på npm. Eftersom Reason är ett ganska ungt språk som ännu inte används på en större skala, så är både nätgemenskapen och marknadens efterfrågan mycket mindre än JavaScript och har ännu inte sett en betydande tillväxt, vilket leder till frågor om den långsiktiga överlevnaden av språket. Båda språken har en betydande roll och bidrar med olika slags funktioner. Men med den komplicerade kompatibiliteten med JavaScript så förlorar Reason en hel del potentiella fördelar som kan uppnås genom JavaScript, vilket kan vara problematiskt på lång sikt och kan påverka Reasons framtid.

Nyckelord Programmeringsspråk, datavetenskap, JavaScript, jämförande studie, Reaasn iv | Sammanfattning Acknowledgments | v

Acknowledgments

I would like to thank Simone Stefani for introducing me to Slagkryssaren and given me the opportunity to do this thesis. You are a great inspiration, thank you! I would also want to thank David Broman for helping me understand the Reason and always being there for helping me out. Lastly, I would like to thank Thomas Sjöland and Johan Montelius for the great support they have provided throughout this project.

Stockholm, June 2020 Axel Pettersson vi | Acknowledgments CONTENTS | vii

Contents

1 Introduction1 1.1 Background...... 1 1.2 Problem...... 2 1.3 Purpose...... 3 1.4 Goals...... 3 1.5 Research Methodology...... 3 1.6 Delimiters...... 4 1.7 Outline...... 4

2 Background5 2.1 JavaScript...... 5 2.2 Reason...... 8

3 Methodology 11 3.1 Research process...... 12 3.2 Test environment...... 14 3.3 Validity and reliability...... 15

4 Results and implementation 17 4.1 Writability...... 17 4.2 Data structures and typing...... 23 4.3 Reliability and testing...... 24 4.4 Community support...... 28 4.5 Market demand...... 32 4.6 Portability...... 33 4.7 Performance...... 35

5 Discussion 39 5.1 Flexibility and paradigms...... 39 5.2 Data structures and typing...... 40 viii | Contents

5.3 Reliability and testing...... 40 5.4 Community support and engagement...... 41 5.5 Job openings and market demand...... 42 5.6 Portability and interoperability...... 43 5.7 Performance...... 43

6 Conclusion 45 6.1 Why should someone use Reason?...... 45 6.2 Why should not someone use Reason?...... 46 6.3 When should or should not someone use Reason instead of JavaScript?...... 47 6.4 Final thoughts...... 48 6.5 Limitations and future research...... 48

References 51

A Faulty code and output 55 A.I Faulty JavaScript Code...... 55 A.II Faulty Reason Code...... 57

B Code for fetching community support data 61

C Code for performance testing 63 C.I JavaScript performance code...... 63 C.II Reason performance code...... 64 LIST OF FIGURES | ix

List of Figures

4.1 Created GitHub repositories with a minimum of 10 stars... 29 4.2 Created Stack Overflow questions...... 30 4.3 Average Stack Overflow views per questions as of today.... 30 4.4 Average Stack Overflow answers per questions as of today.. 31 4.5 Reason packages...... 32 4.6 npm packages registry growth...... 33 4.7 Mean time to render user list of 10 runs...... 36 4.8 Mean time to remove user of 10 runs...... 37 4.9 Mean time to add user in a sorted user list of 10 runs..... 38 x | LIST OF FIGURES LISTINGS | xi

Listings

2.1 Usage example of the typeof function...... 7 2.2 Type example in Reason...... 9 4.1 Example of inheritance in JavaScript...... 18 4.2 Example of Lambda syntax in JavaScript...... 18 4.3 Example on anonymous and non-anonymous functions.... 19 4.4 Example of class declaration...... 19 4.5 Example of whitespace handling in JavaScript...... 20 4.6 Example of operators in JavaScript...... 20 4.7 Variable declaration in Reason...... 21 4.8 Example of recursive function declaration in Reason..... 21 4.9 Example of broken function declaration in Reason...... 22 4.10 Example of operators in Reason...... 22 4.11 Example of pattern matching on arrays in Reason...... 22 4.12 Example of pattern matching with variants in Reason..... 24 4.13 Dumping raw JavaScript in Reason...... 34 4.14 JavaScript function interoperability in Reason...... 34 4.15 JavaScript standard library interoperability in Reason..... 34 4.16 Reason wrapper for name.findName in npm package faker... 35 4.17 ./Profiler.js...... 36 4.18 Reason wrapper for React Profiler...... 36 A.1 assignment.js...... 55 A.2 broken-return.js...... 55 A.3 equals.js...... 56 A.4 floats.js...... 56 A.5 named-index.js...... 56 A.6 semicolons.js...... 57 A.7 assignment.re...... 57 A.8 brokenReturn.re...... 57 A.9 equals.re...... 58 A.10 floats.re...... 58 xii | LISTINGS

A.11 namedIndex.re...... 59 A.12 semicolons.re...... 59 B.1 Program for fetching data from GitHub...... 61 B.2 Query used for getting data from Stack Overflow...... 62 C.1 JavaScript code for testing time to render user list...... 63 C.2 JavaScript code for testing time to remove user entry..... 63 C.3 JavaScript code for testing time add entry in sorted user list.. 64 C.4 Reason code for testing time to render user list...... 65 C.5 Reason code for testing time to remove user entry...... 65 C.6 Reason code for testing time add entry in sorted user list... 66 List of acronyms and abbreviations | xiii

List of acronyms and abbreviations

API Application Programming Interface

APJ Asia Pacific and Japan

EEA European Economic Area

JIT Just In Time

JSC JavaScriptCore npm Node Package Manager

Redex Reason Package Index

REST Representational State Transfer xiv | List of acronyms and abbreviations Introduction | 1

Chapter 1

Introduction

This chapter provides information about the problem being addressed in this thesis, background information about the relevant topics is provided, as well as the general structure of the thesis.

1.1 Background

The JavaScript programming language has in the recent years become one of the most widely used programming languages [1], and while it is primarily used for web development, it has also seen increased usage in other areas, such as server applications using Node [2], desktop applications using Electron [3], and on mobile applications using React Native [4]. Because of its vast popularity and usefulness, JavaScript has received a lot of praise, but also some critiques. Due to these, new programming languages that try to solve the flaws some find in JavaScript have emerged, including as TypeScript, a statically typed superset of JavaScript developed by ; Dart, a language for developing cross-platform applications, developed by ; and Reason, an extension to the OCaml toolchain developed by Facebook [5]. The main issues that these new languages try to address and solve are data types and debugging, however, these languages often try to introduce new features which some developers consider highly valuable. By having a language compiling to JavaScript also creates the opportunity to introduce new concepts and constructs to use when developing web applications, something that was previously only possible through raw JavaScript and PHP. One of the most recent of these languages is Reason, which integrates features from the OCaml language to solve the problems with JavaScript. Because of the heavy background influence from OCaml, it is one of the 2 | Introduction

language that builds upon JavaScript which makes a lot of aggressive changes, such as including static typing, immutability, and soundness, which are a part of the functional programming paradigm, which Reason heavily push towards [6].

1.2 Problem

For a developer, it is crucial to decide a proper toolset when developing a solution for a problem, and one of the most critical decision to take is which programming language to choose. But depending on the problem at hand, it can be hard to know if a specific programming language would be more effective to use than another. With a large and continuously growing popularity, JavaScript has become one of the main tools used when developing software. However, JavaScript has received critiques when developing complex applications due to its dynamic typing and its lack of central debugging facility. Hence, developers may ask if the new JavaScript-compiled languages could be beneficial when developing more advanced systems rather than relying solely of JavaScript. A lot of the common JavaScript supersets has been examined a lot throughout the years, and some are currently used at a large scale, for example TypeScript has been largely accepted by the JavaScript community [7] and Dart has been popular by developers to create cross-platform mobile applications [8]. However, one superset that has not seen a thorough investigation yet is the Facebook-developed syntax extension and toolchain Reason (also known as ReasonML). It is one of the younger additions to this category of JavaScript supersets, yet, it is one that introduces a lot of aggressive changes to the language. This brings up the question, could Reason be used as a viable option over JavaScript? This is the question that this thesis aims to answer. With these new tools that are becoming available for developers, there can also emerge difficulties from the industry perspective in the sense that companies do not know what competence to invest in and what to look for in new employees. A company will need to be up to date with the latest and most relevant technologies to be able to recruit employees that can contribute to creating modern and relevant solutions. Introduction | 3

1.3 Purpose

The purpose of this thesis is to provided developers of any kind with guidance on whether Reason could be a valid tool when developing software where JavaScript or other JavaScript-compiled languages would be used. With the large number of choices at a fingertip of a developer, it is desirable to have some sort of guidance to choose the right tool depending on what the problem is at hand. And also finding the correct tool that suits the developers own priorities and preferences.

1.4 Goals

The main goal of this investigation is to be able to derive whether Reason is a valid substitute for JavaScript in specific scenarios. This goal has been divided into the following sub-goals:

1. Determine the criteria to use when comparing the languages

2. Execute unbiased tests or find other ways of measuring the criteria

3. Determine scenarios where each language could be more beneficial than the other, and cases when it is not.

By determining the scenarios of which Reasons functionality could be more desirable and when it is not, a developer will hopefully be able to determine whether Reason is a valid tool for the problem that is being faced. Furthermore, a summarized description of the overall usability and potential downsides of Reason will be derived to be able to make assumptions about the future of the language.

1.5 Research Methodology

This thesis will make use of the comparative research elements, meaning that, through comparisons and tests, relevant data that can be used for analysis, can be obtained. More concretely, this investigation will make use of both qualitative and quantitative methodologies for obtaining the data that will be compared. This is due to the fact that some major differences between programming languages can only be examined using one of this methodologies exclusively. For example, measuring performance requires a sole quantitative 4 | Introduction

method while investigating writability or reliability are mainly a part of the qualitative methodology. When choosing the appropriate methods for deriving the investigations, it is crucial to be as little biased as possible to be able to obtain a fair results to conclude with. Therefore, some basic criteria that the results on the methods should produce are:

1. To not be based on subjective opinions that do not apply to the general crowd

2. The method should produce information or data worth analysing

More concrete information about the methods that are used to execute the investigation will be presented in future sections.

1.6 Delimiters

Investigating how Reason compares to other languages that try to solve similar problems, like TypeScript, could be aligned with the overall intention of this investigation. However, in this investigation, the main goal is when and if it makes sense to use a language like Reason instead of JavaScript, but further investigation in how it compares to other solutions is a possibility for future work. Since the focus is scenarios where JavaScript would normally be used as the developers’ choice of programming language, the Reason native implementation will not be tested as thoroughly as the JavaScript implementation.

1.7 Outline

The thesis is divided into six chapters. In chapter 2, detailed insight into the technologies that will be investigated. In chapter 3, a more detailed description of the research methodology and the concrete methods that will be used in the investigation. In chapter 4, the results from implementing the methods will be presented, as well as findings from related works. In chapter 5, the results presented inchapter 4 will be discussed and analyzed. In chapter 6, the conclusions from the investigations will be presented, as well as some final thoughts and suggestions for future research. Background | 5

Chapter 2

Background

This chapter will introduce and describe the concepts that are foundational to the investigation. The goal is to provide an in-depth understanding of these concepts.

2.1 JavaScript

In a nutshell, JavaScript is a high-level interpreted language, originally designed by Netscape to provide a technology for building dynamic web pages [9]. Along with HTML and CSS, it became one of the fundamental technologies behind the Web, and nowadays, with about 95% of the available website implementing JavaScript it is very difficult to find a website that does not make use of it in one form or another [10]. During the mid to late 2000s, a lot of frameworks and libraries for JavaScript were built, which would make it easier for developers to create applications of good quality. This further made JavaScript into an appealing language for many developers to learn. Some of the frameworks and libraries introduced were , jQuery, along with the JavaScript runtime Node.js [9]. During the 2010s was when JavaScript started getting another wave of attention due to it becoming more versatile as it started broadening its usage areas to desktop and mobile applications as well as server applications and video games. With Stack Overflows Developer Survey from 2019, it was presented that JavaScript was the number one popular programming language, that the top three web frameworks (jQuery, React and ) being JavaScript frameworks, and that the number one most popular non-web framework, with 49.9% of the votes, being Node.js [11]. 6 | Background

2.1.1 ECMAScript ECMAScript is a scripting-language specification created for standardization of the scripting languages used on the Web, with JavaScript being the major language implementing such specifications and it is created by . The proposal of a standardization was initially advanced by Netscape when Microsoft presented their scripting language JScript back in 1997 [9]. There are currently ten editions of the language specifications, and since 2015, yearly editions are released. The next edition of ECMAScript is the 2020 edition, which is expected to be released in June 2020, open-source drafts of this edition from Ecma International can be found online [12][13].

2.1.2 Features and nature The features of JavaScript can be summarized as follows:

Dynamic JavaScript translates the source code to machine-readable code "on the fly" during the execution of it. Like many other scripting languages, it implements an eval function that executes statements formatted as strings.

Data types According to Mozzila developer documentation [14], JavaScript implements six different primitive data types, as well as one special primitive and two non- data structure types.

• Primitive data types

– undefined – boolean – number – string – bigint (as of ECMAScript 2020) – symbol (as of ECMAScript 2015)

• Special primitive

– null Background | 7

• Non-data structure types

– object – function

Typing system Like many other scripting languages, it implements a dynamic and weak type system. The type of a variable can only be determined during runtime and can hold a value of any type at any specific moment in time. The typeof function is implemented to be able to determine which of the six data types the operand is at the time of execution. For more advanced type checking, like determining the structure of an object, type checking through Duck Typing would need to be implemented [15]. Listing 2.1: Usage example of the typeof function 1 const foo = 42; 2 const bar="42"; 3 4 typeof (foo);//"number" 5 typeof (bar);//"string"

2.1.3 JavaScript engine The JavaScript engine’s job is to translate the source code into machine- readable code. The fundamental parts of the engine are the parser, and optimizing compiler. These components are implemented in all of the relevant JavaScript engines, for example Google’s V8, used in Chrome and Node.js; Mozillaz SpiderMonkey, used in ; and Apples JSC, used in , even though the actual implementation and degree of optimization can differ between engines [16].

2.1.4 Package management The primary package manager for JavaScript is npm, a package manager built using the Node.js runtime. Nowadays, npm is bundled when installing Node.js.

2.1.5 Linters A common tool used by JavaScript developers are linters. A linter is a tool which analyzes the source code of a program and flags errors, bugs, or style 8 | Background

errors. It is especially useful for JavaScript developers due to the code not being compiled until run-time, meaning that this enables the developers to detect bugs or errors before testing the program. The most common lint tool available for JavaScript developers is ESLint [17].

2.2 Reason

Reason is a syntax extension and toolchain built upon OCaml. It aims to introduce a familiar syntax adapted for JavaScript programmers. Using its partner project, BuckleScript, Reason can get compiled into JavaScript, and using the native OCaml compiler, it can be compiled into machine code [6].

2.2.1 Features and nature According to the documentation [6], Reason provides:

• A solid static type system with 100% coverage

• A pure, fully immutable and functional language

• Small and fast build output

• Incremental learning and codebase conversion

• A good ecosystem and tooling with interchangeability with many pure JavaScript npm packages

Data types As expected from a statically typed language, a lot of different types are included. The Reason syntax inherits all of the types used in OCaml, with some of these including:

• Integers

• Floating-Point Numbers

• Tuples (pairs of values)

• Records (object-like type)

• Lists and Arrays Background | 9

• Much more, including user-defined types

[6][18]

Type system Reason implements a static type system, meaning that each variable is bound to a specific type and guarantees that a variable can only hold values you explicitly told it can hold.

Listing 2.2: Type example in Reason 1 let foo= ref(42);// Assign fooa mutable integer 2 foo :="bar";// Try to change the integer toa string 3 4 /* 5 Output: 6 2:16 -51 7 This has type: string 8 But somewhere wanted: int 9 */

Package manager Reason implements its package manager, esy, for packages meant for native development. The package manager is built upon JavaScript npm, because of this, its usage is very similar to the one of npm. When it comes to Reason code compiled using BuckleScript, the packages are distributed through npm and the packages compatible with Reason usually include the prefix bs-.

OCaml As aforementioned, Reason is built upon the OCaml ecosystem. OCaml is a 20 year old general purpose language with emphasis on expressiveness and safety, developed at Inria. It has been widely used within the research community and has an active community making use of it. Reason inherits a lot of its features directly from OCaml, such as its typing system, pattern matching and functional paradigm implementations [19]. 10 | Background Methodology | 11

Chapter 3

Methodology

The methods used for the investigation should give us a clear view of how the programming languages compare to each other according to the following criteria:

• Writability

– How can the developer utilize the language to develop solutions? – What paradigm does the language implement?

• Data structures and typing

– What data structures can the developer use? What data structures are not available? – What typing paradigm does the language implement? What is the benefit or disadvantage of it?

• Reliability and testing

– Are there good ways of ensuring that developers write good and robust code?

• Community support

– Are there a large community of developers using the language? – Are there many available packages for developers to use?

• Market demand

– Is the language widely used in the industry? How does the future look like? 12 | Methodology

• Portability

– How well can a program be translated to the other language?

• Performance

– How well do the languages perform against one another?

By examining the languages with the aforementioned criteria in mind, a thorough view on how these languages compare to one another will be achieved.

3.1 Research process

To investigate the criteria, the different criterion will use different underlying research processes, due to some areas requiring a quantitative methodology while some requiring a qualitative methodology.

3.1.1 Writability Writability of a programming language can in this sense be regarded as, "the ease of writing a program given a problem". Each language got their set of constructs which are to be used to create comprehensive code. If too many complex constructs are presented to the developer it can be hard to make use of each of them in the intended way, and also can lead to overly complicated code which results in more bugs and errors. To compare the writability of the language, the focus will be on how the syntax abstracts different programming concepts as well as comparing the expressiveness of the syntax. This will be done through a thorough comparison of the syntax and the fundamental design decisions of the languages. Differences between the languages will be commented on and discussed.

3.1.2 Data structures and typing As mentioned before, both the languages implement different data structures and typing systems. Here, a further investigation on their typing systems and data structures will be conducted to be able to conclude the benefits or flaws of implementing a strictly static type system with a large variety of data structures, or a weak dynamic type system with a small variety of data structures. Methodology | 13

3.1.3 Reliability and testing For this criterion, the main ways of finding bugs or errors in software developed in either one of the languages will be examined. To examine how well the languages compare in terms of this, an investigation of tools that can detect bugs and errors in the code available for either language will be conducted. And since linters are becoming a widely used tool for JavaScript developers, the number of errors found by the most common JavaScript linter, ESlint, in comparison with the Reason compiler, will be examined [17]. For testing this, faulty JavaScript code that implements the Common JavaScript mistakes presented by w3schools will be written [20]. The code will then be translated to Reason and tested.

3.1.4 Community support Community support will be examined through the open statistics released by GitHub, Stack Overflow, the npm registry, and the Redex index. The data available through the GitHub REST API can be used to obtain a perspective on how many active projects are being developed using each language. Through Stack Overflow’s developer survey, data on how many active and answered questions are published on the platform can be achieved. Through the npm registry data, a perception on the amount of available JavaScript packages and their usage, can be achieved. The data gained from npm will be compared to that of the Reason Package Index(Redex), which contains an indexed and categorized view of the available Reason packages. With the examined data, a full view of how active each of the languages’ communities are, can be achieved.

3.1.5 Market demand This criterion has a lot of ties with the criterion about examining community support. While the community support criterion aims to conclude the overall activity of the technologies around their communities, this criterion aims to conclude how active the technologies are in the software development industry. An investigation of the current job openings for each technology will be conducted to get a perceptions of their overall activity within the industry. The source for the available job openings will be Indeed and LinkedIn, some of the most common platforms to advertise job openings. 14 | Methodology

3.1.6 Portability Here, the focus will be on creating an empirical research study by examining how well Reason implements interoperability with JavaScript. This will be done by examining how JavaScript code can be implemented in Reason to write a partial Reason and partial JavaScript applications, as well as examining how well some of the common JavaScript npm packages can be used to create pure or partially Reason written application.

3.1.7 Performance To create a performance comparison running under real-world circumstances, a web application in the form of a large user list will be created. The application will contain a large list of randomly generated user entries, with an adjustable setting to decide how many users to render. The benchmark will be performed on different sorts of operations, these include constructing the list with different amount of users; adding entries to the list; and deleting entries from the list. The pure JavaScript application will be written using the React framework, and the Reason application will be written using the Reason adaption of the React framework, ReasonReact [21]. The application benchmarks will be done using the official React Profiler component, developed by the developers behind React [22].

3.2 Test environment

In this section the different environments and tools used when writing and executing the programs will be stated, as well as the specific version of them is being used.

3.2.1 Reason and BuckleScript The Reason code will be compiled to JavaScript using Reason version 3.6.0, alongside BuckleScript version 7.2.2.

3.2.2 React and ReasonReact The benchmarks will use the latest versions available of both React and ReasonReact. The most recent React version is 16.13.1 and will be used when Methodology | 15

writing the pure JavaScripts tests. The version of ReasonReact that will be used is the version 0.7.0.

3.2.3 ESLint The ESLint version used for detecting errors within the faulty JavaScript code will be version 6.8.0.

3.2.4 JavaScript runtime and engine Command-line programs will be written for and be executed from Node runtime version 12.6.3, which is using the V8 JavaScript engine version 7.8. Programs being executed in the browser will use version 81.0 as runtime, which is using the V8 JavaScript engine version 8.1.

3.2.5 Hardware and operating system The tests will be developed and executed on a computer running Mac OS version 10.14.6 with a 2.4-GHz Intel Core i5 processor and 8GB of RAM.

3.3 Validity and reliability

These criteria will give a broad view and indications on how these languages compare. However, since we only have a few test cases for each criterion there is a risk that some specific issues will not be addressed. Therefore, for deep knowledge in how these languages would compare with respect to specific criterion, a more in-depth investigation could be required. 16 | Methodology Results and implementation | 17

Chapter 4

Results and implementation

In this chapter, the results from executing the methodology discussed in the previous chapter will be presented, the quantifiable data will be visualized through graphs or tables.

4.1 Writability

In this section, the results from investigating how the languages implements programming paradigms the syntax, and the fundamental constructs of the languages.

4.1.1 JavaScript In this section, the results from investigating JavaScript’s syntax and constructs will be presented.

Programming paradigms JavaScript implements elements from the object-oriented and functional programming paradigms. It inherits a prototype-based object-oriented with the ability to create a program as a collection of classes and objects, as well as implementing inheritance through reusing objects through prototypal inheritance. The objects in JavaScript, as with all other variables declared with the let or var keywords, are mutable, a feature also often seen in object-oriented languages. A simple example of how simple object orientation with inheritance and working with prototype objects in JavaScript can be observed in Listing 4.1. 18 | Results and implementation

Listing 4.1: Example of inheritance in JavaScript 1 class Person{ 2 type="human"; 3 constructor(name){ 4 this .name= name; 5 } 6 } 7 class Robot extends Person{ 8 type="machine"; 9 } 10 Person.prototype.getInfo= function (){ 11 console.log(‘${ this .name}-${ this .type}‘); 12 }; 13 14 const bob= new Person("Bob"); 15 const terminator= new Robot("Termintaor"); 16 17 bob.getInfo();// Bob- human 18 terminator.getInfo();// Terminator- machine

JavaScript inherits some functional programming elements like first-class functions, meaning that you can assign a function to variables, pass them as arguments, return functions from a function. It also implements a lambda syntax, which is used to pass around functions as data, it uses the arrow notation => as a lambda operator. The code in Listing 4.2 demonstrates some of this in action.

Listing 4.2: Example of Lambda syntax in JavaScript 1 const hello= function (f){ 2 return () => { 3 f("hello world"); 4 }; 5 }; 6 hello(console.log)();

Variable declaration

JavaScript uses three different keywords for creating variables, var, let, and const. With the two first-mentioned used to declare reassignable variables, while const declares a non reassignable variable, a constant. Results and implementation | 19

Function declaration

JavaScript allows you to declare functions either by using the keyword function or by declaring a lambda function through the arrow notation =>. The key difference between the two is that the latter-mentioned declares a non-named, anonymous function, which is not bound to any specific context of when and where it is executed. When using the function declaration, the function is bound to the context of where it is executed from. An example of the difference is shown in Listing 4.3. Listing 4.3: Example on anonymous and non-anonymous functions 1 const cat={ 2 lives: 9, 3 jump: function (){ 4 this .lives--; 5 }, 6 jumpAnon: () => { 7 this .lives--; 8 } 9 }; 10 cat.jumpAnon(); 11 console.log(cat.lives);//9 12 cat.jump(); 13 console.log(cat.lives);//8

Class declaration In JavaScript, a class is a special type of function which is created using the class keyword. The class can include a constructor, methods and properties. An example of its usage is shown in Listing 4.4. Listing 4.4: Example of class declaration 1 class Cat{ 2 constructor(lives){ 3 this .lives= lives;// lives isa class property 4 } 5 jump(){// Jump isa class method 6 this .lives--; 7 } 8 } 9 const cat= new Cat(9); 10 cat.jump(); 11 console.log(cat.lives);//8 20 | Results and implementation

Whitespaces To a large degree, JavaScript ignores white spaces, meaning you can break any expression up with line breaks and spaces, with one exception for return statements, which needs to be written entirely on the same line, as demonstrated in Listing 4.5.

Listing 4.5: Example of whitespace handling in JavaScript 1 let 2 x 3 = 2; let y = 3; 4 return 5 let z = 3;// This will never execute

Operators

JavaScript implements arithmetic operators like + (addition), - (subtraction), * (multiplication), \% (modulus), ++ (increment), to name a few. It also implements assignment operators like *=, \%=, and so on. However, operators can behave differently if applied to different data types, like +, if applied to a string, means concatenation, as demonstrated in Listing 4.6.

Listing 4.6: Example of operators in JavaScript 1 console.log(1 + 2);//3 2 console.log(’foo’+’bar’)//’foobar’

4.1.2 Reason In this section, the results from investigating Reason’s syntax and constructs will be presented.

Programming paradigms Reason primarily implements the functional programming paradigm and encourages developers to use it as much as possible. When binding a value to a variable in Reason, that variable cannot be reassigned and are therefore immutable by default. This leads to fewer side effects when writing code, that is, data in the surrounding state of a program being manipulated. Furthermore, all of the functions are first-class and can higher-order, like JavaScript. However, Reason still implements some elements from the imperative programming paradigm, which includes mutation of variables Results and implementation | 21

declared using the ref wrappers (which creates a Reason record with the mutable property contents), and imperative loops (for- and while loops).

Variable declaration

All variables declared using the let keyword, which declares an immutable binding, which means it will not be able to be reassigned. However, if you wrap the value with the ref wrapper, it will create a mutable record (Reason’s equivalent to a JavaScript object) with the property content, which can be reassigned as wished using the := assignment operator. Listing 4.7: Variable declaration in Reason 1 let foo="foo";// Immutable 2 3 let bar= ref("bar");// Mutable 4 5 Js.log(bar);//"bar" 6 7 bar :="baaar"; 8 9 Js.log(bar);//"baaaar"

Function declaration

All functions in Reason are declared using the arrow syntax (=>) and inherits some of the properties from the arrow functions in JavaScript, but has some significant differences. Like JavaScript’s arrow functions, the functions in Reason does not have a context and does not act differently depending on where it is executed from. A difference is that all of the functions in Reason have a return value and the type must be consistent under all conditions. While JavaScript function can create recursive calls without any modification, but in Reason you have to explicitly use the rec keyword to declare a function allowed to use recursive calls, as shown in Listing 4.8. Listing 4.8: Example of recursive function declaration in Reason 1 let rec fibonacci=(num) => { 2 switch (num){ 3 |_ when(num <= 1) => 1; 4 |_ => fibonacci(num-1)+ fibonacci( num - 2); 5 } 6 } 22 | Results and implementation

Whitespaces

Just like JavaScript, Reason ignores whitespaces. However, since the return statement is not implemented within reason, and the functions instead returns the result of the last expression of the executed function. The function shown in Listing 4.9 is a valid Reason function that return the value 6. Listing 4.9: Example of broken function declaration in Reason 1 let broken= 2 () => 3 { 4 let 5 foo 6 = 2; let bar = 4; 7 foo 8 + 9 bar; 10 }

Operators Reason inherits all of the operators that are available in JavaScript, aside from the assignment operators. However, in contrast to JavaScript, operations on different data types require different operators, for example, for integer addition, + is used, but for floating-point numbers, +. is used. Examples of different operators can be seen in Listing 4.10. Listing 4.10: Example of operators in Reason 1 Js.log(1 + 2);//3 2 Js.log(1.5 +. 1.5);//3 3 Js.log(’foo’ ++’bar’)//’foobar’

Pattern matching One feature that Reason has that is not available in JavaScript, is a proper pattern matching-mechanic. It is used through the switch keyword and lets the developer destruct data and match it against different structures, for example, the program in Listing 4.11 shows how pattern matching can be done on lists. Listing 4.11: Example of pattern matching on arrays in Reason 1 let printHead= data => { 2 switch (data){ 3 | [head,...rest] => Js.log(head); Results and implementation | 23

4 | [] => Js.log("No data") 5 }; 6 }; 7 let foo=["f","o","o"]; 8 let bar = []; 9 10 printHead(foo);//"f" 11 printHead(bar);//"No data"

4.2 Data structures and typing

In this section, the results from investigating the different data structures and the available typing system for each of the languages.

4.2.1 JavaScript As described in Section 2.1.2, JavaScript implements a dynamic and weak typing system as well as just a handful of data structures. Types of data are only known during the execution of the program, in run time, as well as variables not being bound to any specific type but rather an arbitrary value. All of the different data structures are also described in Section 2.1.2, as well on how to determine the type of the value of a variable during a specific moment in time by using the typeof function.

4.2.2 Reason One of the main benefits of using Reason is, according to the developers themselves, is its "rock-solid type system", which includes 100% coverage, inference, and soundness [6]. Inference meaning that through written expressions, Reason can conclude what data type is being used, meaning that the developer does not need to explicitly write the data type for every variable being used. And soundness meaning that as long as the program compiles, the compilers ensures the developer that every type is guaranteed to only contain the value it is specified [23].

Variants Along with the data types shown in Section 2.2.1, Reason uses variants to configure your own custom data structures, which can be as complex or simple as one might wish. A variant type is declared with using the type keyword, 24 | Results and implementation

along with the bar separator | to specify the different structures of the variant. The variants are primarily used alongside the pattern matching technique, using the switch keyword, and therefore can destructure the variant and extract the data it is containing, as shown in Listing 4.12.

Listing 4.12: Example of pattern matching with variants in Reason 1 type payload= 2 | Message(string) 3 | ErrorCode(int) 4 | NoResult; 5 6 let outputData= data => { 7 switch (data){ 8 | Message(message) => Js.log("Message:" ++ message) 9 | ErrorCode(error) => Js.log("Error code:" ++ Js.Int.toString(error)) 10 | NoResult => Js.log("No data") 11 }; 12 }; 13 let foo= Message("foo"); 14 let bar= ErrorCode(42); 15 let baz= NoResult; 16 17 outputData(foo);//"Message: foo" 18 outputData(bar);//"Error code: 42" 19 outputData(baz);//"No data"

4.3 Reliability and testing

This section will present the result from running the React and ReasonReact performance tests. The source code that has been written for investigating reliability and testing, can be found in appendixA.

4.3.1 JavaScript results The faulty code written for pure JavaScript can be found appendix A.I. Along with the code, outputs from running the code as well as errors that ESLint caught while analyzing the source code. Results and implementation | 25

Assignment statement as conditional statement In the program shown in Listing A.1 demonstrates how an assignment statement is being used as a conditional statement. ESLint caught the error Unexpected constant condition when using an assignment statement as a conditional statement since an assignment statement will evaluate to the value that is being assigned. The program finishes execution and prints the message inside both if-statements.

Broken return statement The program shown in Listing A.2 demonstrates how JavaScript reacts to broken statements. ESLint caught the error Unreachable code since the last line of the function never executes. The program finishes execution and prints a message containing undefined, as the function does not return a value.

Equality between different types The program shown in Listing A.3 demonstrates how JavaScript reacts to equality comparisons between values of different types. In this case it compares a number of value 0 and a string of value "0". ESLint does not detect any errors and the program finishes execution with the output 0 is equal to "0", as the statement 0 == "0" returns a truthy value.

Float addition The program shown in Listing A.4 demonstrates how JavaScript handles the addition of the floating-point numbers. ESLint does not find any errors and the program finishes execution and print the result 0.1 + 0.2 is 0.30000000000000004, meaning that by adding 0.1 and 0.2 together does not result in a value equal to 0.3.

Named index for arrays The program shown in Listing A.5 demonstrates how JavaScript handles inputting named indices when populating an array. ESLint does not find any errors and the program finishes execution and prints the result 0 undefined , meaning that it does not detect the number of elements nor can get the element with index 0. This is because JavaScript redefines the array to be an object when introducing named indices, meaning that regular array operations will not work correctly. 26 | Results and implementation

Misplacing semicolons The program shown in Listing A.6 demonstrates how JavaScript reacts when misplacing a semicolon directly after an if-statement. ESLint does not detect any errors and the program finishes execution and print the result x is 19, meaning that the program executes the statement within the whether or not the if-statement is true or not.

4.3.2 Reason results The faulty code written for Reason can be found appendix A.II. Along with the code, outputs from running the code or errors thrown by the compiler when compiling the code is shown.

Assignment statement as conditional statement The program shown in Listing A.7 demonstrates how Reason handles using variable reassignment inside a conditional statement. Reason does not support reassignment of variables, a mutable variable using the ref wrapper is created, which in it creates an object with the mutable property contents. The program does not compile and the compiler throws the error This has type: unit; But somewhere wanted: bool at the reassignment expression, meaning that reassigning expression the value returns a non-defined value.

Broken return statement The program shown in Listing A.8 demonstrates how Reason handles broken up return statements. The program compiles and executes successfully with the output 1000, which is the expected output of running the application. This is because Reason does not implement a return keyword, and rather returns the value of the evaluated expression at the end of a function.

Equality between different types The program shown in Listing A.9 demonstrates how Reason handles equality between different types. The program does not compile successfully and the compiler throws the error This has type: string; But somewhere wanted: int, meaning that comparisons between different data types are strictly forbidden. Results and implementation | 27

Float addition The program shown in Listing A.10 demonstrates how Reason handles the addition of floating-point numbers. The program compiles and executes successfully and outputs 0.1 + 0.2 is 0.30000000000000004, meaning that by adding 0.1 and 0.2 together does not result in a value equal to 0.3, the same results as in the JavaScript code.

Named index for arrays The program shown in Listing A.11 demonstrates how Reason handles inputting named indices when populating an array. The program does not compile successfully and the compiler throws the error This has type: string; But somewhere wanted: int, meaning that it is not possible to use strings as keys to populate an array in Reason.

Misplacing semicolons The program shown in Listing A.12 demonstrates how Reason reacts when misplacing a semicolon directly after an if-statement. The program does not compile successfully and the compiler throws the error Syntax error at the position where the semicolon is placed. The summarized data can be seen in Table 4.1.

Table 4.1: Amount of errors caught or resolved out of six

ESLint Reason Caught 2 ( 33.3%) 4 ( 66.7%) Resolved 0 (0%) 1 ( 16.7%) Not caught nor resolved 4 ( 66.7%) 1 ( 16.7%)

4.3.3 Summary In summary, of the six common errors in JavaScript, ESLint managed to detect two out of the six errors, and Reason managed to detect four of the errors and resolved one of the errors (4.3.2), due to the syntax of Reason not being able to reproduce the scenario where the error occurred. 28 | Results and implementation

4.3.4 Prior findings In an empirical study conducted by Microsoft Research and University College London a conclusion that by using a static type system for writing JavaScript applications the total number of errors caught increase by 15% are made on average [24].

4.4 Community support

This section presents the results from examining the data available on GitHub, Stack Overflow, the npm registry, and the Redex index. The code written for fetching the relevant data that will be summarized and presented can be found in appendixB.

4.4.1 Active GitHub repositories The program shown in Listing B.1 fetch the number of repositories that match the given query on GitHub. The program takes two arguments, one for the minimum amounts of stars the repository has, and one for specifying the time-span when the repository was created. The program can be run through Node, with, for example, the command node./index.js ">10" "2019-01-01..2019-03-31" to get the count of Reason and JavaScript repositories with more than 10 stars and are created within the interval of January first 2019 and the 31 of March 2019. For the data fetched for analyzing, the amount of stars each repository would need to have is more than 10 stars. The data retrieved covers repositories created since Reason was introduced, July 2016, and up to the end of December 2019. Each request to GitHub covers two quarters of a year, that is, six months, and return the total number of repositories that fulfill the query request. The results from running the program for each of the intervals can be observed in Figure 4.1.

4.4.2 Stack Overflow The SQL-query shown in Listing B.2 is created and used within the Stack Overflow data explorer, where you can create queries to fetch data from their database [25]. The query results the total number of questions published that includes the tags reason, reasonml, or . It also outputs the total number of views the questions got combined, the total number of answers, Results and implementation | 29

JavaScript 104 Reason

103

102

101 Amount of repositories (logarithmic)

2016 2017 2017 2018 2018 2019 2019 Q3-Q4 Q1-Q2 Q3-Q4 Q1-Q2 Q3-Q4 Q1-Q2 Q3-Q4

Figure 4.1: Created GitHub repositories with a minimum of 10 stars as well as the average number of views and answers per post. The query can take two arguments that specify the interval of dates in which the questions where posted, because of this, a division of the query results in the same way as the GitHub results are made. In Figure 4.2 the results from querying the total number of questions posted to Stack Overflow are presented. Figure 4.3 shows the average amount of views the questions posted within the presented interval has today. Figure 4.4 the average amount of answers the questions posted within the presented interval has today.

4.4.3 npm packages The content on Redex is backed by a dataset available in the GitHub repository redex/data, where data can be extracted ad analyzed [26][27]. By examining the different Git revisions of this repository, an overview on the current number of packages as well as the growth can be examined. The data provided categorizes the packages into six different categories, published, packages that are available through the npm registry and that are generally well maintained; unpublished packages that are not published through the npm registry, but are generally well maintained; prematurely published, packages that are available 30 | Results and implementation

JavaScript 105 Reason

104

103

102

101 Amount of questions (logarithmic)

2016 2017 2017 2018 2018 2019 2019 Q3-Q4 Q1-Q2 Q3-Q4 Q1-Q2 Q3-Q4 Q1-Q2 Q3-Q4 Date created

Figure 4.2: Created Stack Overflow questions

JavaScript Reason 1,000

750

500

250 Average views per question

0 2016 2017 2017 2018 2018 2019 2019 Q3-Q4 Q1-Q2 Q3-Q4 Q1-Q2 Q3-Q4 Q1-Q2 Q3-Q4 Date created

Figure 4.3: Average Stack Overflow views per questions as of today Results and implementation | 31

JavaScript 3 Reason

2 Average answers per questions 1

2016 2017 2017 2018 2018 2019 2019 Q3-Q4 Q1-Q2 Q3-Q4 Q1-Q2 Q3-Q4 Q1-Q2 Q3-Q4 Date created

Figure 4.4: Average Stack Overflow answers per questions as of today through the npm registry but lack in quality or maintenance; prematurely unpublished, same as prematurely published but with packages not available through the npm registry; obsolete, deprecated or abandoned packages; and finally, rejected, packages that are not justified for general usage. For the data collection, the published and prematurely published packages will be combined, as well as the unpublished and prematurely unpublished. The number of obsolete packages will also be investigated. The result from taking analyzing different revisions in the git history of the data set, from the oldest and to the latest revision with evenly spread out intermediate revisions, are shown in Figure 4.5. Even though, not many other languages got a packaging index like Reason, an insight in the available JavaScript packages can be obtained from investigating the total amount of packages in the npm registry altogether, since its primary use is for JavaScript development. On the website Modulecounts, a historical view on the growth of the npm registry can be found and examined. The site has achieved this by web scraping the total counts of packages available and stored the number within a database [28]. The growth of the npm registry for the last 3 years is shown in Figure 4.6. Furthermore, according to an article about npm dependencies written by 32 | Results and implementation

300 Published Unpublished Obsolete 250

200

150

100 Amount of packages 50

0 01-20 04-30 08-08 11-16 02-24 06-04 09-12 12-21 03-30 2018 2018 2018 2018 2019 2019 2019 2019 2020

Figure 4.5: Reason packages

Michał Janaszek in 2018, the average number of dependencies used within a JavaScript project was around 20 at that time, and increasing every year [29].

4.5 Market demand

From examining the available job openings on Indeed and LinkedIn, the total number of job openings for Reason developer worldwide was 33, with 2 being from Indeed [30], and 31 being from LinkedIn [31]. Along with these job openings, there included some openings from larger companies like NVIDIA and CGI. Looking at the top 10 results from LinkedIn, 4 of the openings was explicitly looking for Reason developers, whilst the rest marked as a merit, but not necessary. 4 of the 10 job top openings also required the applicant to have good knowledge of JavaScript and where the job position primary languages would be JavaScript. From LinkedIn, 18 of the job openings were for jobs within the EEA; 2 within the United States; and 9 within the APJ (including Singapore). When using the same criterion for fetching the number of job openings for JavaScript developers, the total number of job openings was approximately 350,000, with about 43,000 from Indeed and 310,000 from LinkedIn. All of the top results were directly targeted against JavaScript developers and Results and implementation | 33

Figure 4.6: npm packages registry growth considered it to be a requirement for the job. From LinkedIn, about 97,000 of the jobs were located in the EEA; 83,000 located within the United States; and 77,000 within the APJ (including Singapore), with the rest being spread across different places in the world. The collected data can be observed in Table 4.2, along with the percentage of how much of the total is concentrated within a specific region.

Table 4.2: Current job openings

Reason JavaScript Total 31 307,386 EEA 18 ( 58.1%) 97,423 ( 31.7%) United States 2 ( 6.5%) 82,582 ( 26.9%) APJ (including Singapore) 9 ( 29.0%) 77,354 ( 25.2%) Rest of the world 4 ( 6.4%) 50,027 ( 16.3%)

4.6 Portability

This section presents the results from examining the interoperability between Reason and JavaScript, and showcase how to implement pure Reason code and 34 | Results and implementation

external JavaScript packages in a Reason codebase.

4.6.1 Pure JavaScript To be able to use pure JavaScript inside of Reason, you can insert it inside of a bs.raw expression, as shown in Listing 4.13

Listing 4.13: Dumping raw JavaScript in Reason 1 [%bs.raw {| console.log(’Hello World from JavaScript!’) |}];

To make the JavaScript more accessible for the rest of the Reason program, you can specify the equivalent Reason return type of the JavaScript code, and if a function, you can specify the input arguments as Reason types as well, as shown in Listing 4.14

Listing 4.14: JavaScript function interoperability in Reason 1 let jsReduceInt:(array(int),(int, int) => int) => int = [%bs.raw 2 {| 3 function (numbers, func){ 4 return numbers.reduce(func, 0); 5 } 6 |} 7 ]; 8 9 let numbers = [|1, 2, 3|]; 10 let func=(number, acc) => number*2+ acc; 11 Js.log(jsReduceInt(numbers, func));// 11

For making JavaScript standard libraries, like the Math library, accessible in Reason, it is possible to create a simple wrapper using the @bs.val keyword to define the function as a Reason function, as shown in Listing 4.15.

Listing 4.15: JavaScript standard library interoperability in Reason 1 [@bs.val] external sqrt: int => int="Math.sqrt "; 2 Js.log(sqrt(4));//2

4.6.2 npm packages and modules To be able to use JavaScript-written npm packages and JavaScript modules in Reason, a wrapper is required to be implemented that exposes the package as a Results and implementation | 35

module which Reason can use. To do this, you will need to manually convert the types the package is using to the equivalent Reason types. For example the function name.findName from the popular JavaScript package faker takes three optional arguments, for first name, last name, and gender. For any of the arguments that are not set, it will randomize the value of that argument and return a name, can implement a Reason wrapper as shown in Listing 4.16.

Listing 4.16: Reason wrapper for name.findName in npm package faker 1 // Name.re 2 /* Type definition of the functions we want to expose*/ 3 type t={ 4 findName:(option(string), option(string), option(string)) => string, 5 }; 6 7 /* Create Reason interface for the functions in the name export of faker*/ 8 [@bs.module"faker"] external name:t="name"; 9 10 /* Exposes findName function to module Name*/ 11 let findName = (~firstName=?, ~lastName=?, ~ gender=?, ()) => 12 name.findName(firstName, lastName, gender); 13 14 // Main.re 15 let randomName= Name.findName(); 16 Js.log(randomName);// Prints randomized name

4.7 Performance

Since ReasonReact does not include a wrapper for the native React Profiler, a custom wrapper was created to be able to use the same component for measuring the rendering time. The wrapper was created by constructing a simple JavaScript file which exports the Profiler, as shown in Listing 4.17, the Reason wrapper imports this and makes it into a usable ReasonReact component by using the @react.component keyword, as shown in Listing 4.18. Measurements were taken on both the development and production build of all of the different implementations. The development builds are executed by using a JIT code bundler which bundles the source code into a non-optimized output that is runnable in the browser. The production build bundles the code into an optimized and compressed output which is available to run in the 36 | Results and implementation

React (Development) 400 React (Production) ReasonReact (Development) ReasonReact (Production)

ms 200

0 102 103 104 Amount of users (logarithmic scale)

Figure 4.7: Mean time to render user list of 10 runs browser. Most of the debugging and profiling tools are ignored when creating a production, however, by adding the --profiler flag to the bundle command, the profiling tools persist. Listing 4.17: ./Profiler.js 1 exports .Profiler= require ("react").Profiler;

Listing 4.18: Reason wrapper for React Profiler 1 type onRender=(string, string, float) => unit; 2 3 [@bs.module"./Profiler.js"][@react.component] 4 external make: 5 (~id: string, ~onRender: onRender, ~children: React.element) => React.element= 6 "Profiler";

The Reason and JavaScript code written for executing the measurements for the time it takes to render different amounts of user elements can be observed in Listing C.4 and Listing C.1 in the appendix, respectively. The results from the measurements taken can be seen in Figure 4.7. The Reason and JavaScript code written for measuring the time it takes to render different time it takes to construct and render the deletion of user elements can be observed in Listing C.5 and Listing C.2 in the appendix, respectively. The results from the measurements taken can be seen in Figure 4.8. The Reason and JavaScript code written for measuring the time it takes to render different time it takes to construct and render the addition of user Results and implementation | 37

150 React (Development) React (Production) ReasonReact (Development) 100 ReasonReact (Production) ms 50

0 102 103 Amount of users (logarithmic scale)

Figure 4.8: Mean time to remove user of 10 runs elements in a sorted list can be observed in Listing C.6 and Listing C.3 in the appendix, respectively. The results from the measurements taken can be seen in Figure 4.9. 38 | Results and implementation

React (Development) React (Production) 100 ReasonReact (Development) ReasonReact (Production) ms 50

0 102 103 Amount of users (logarithmic scale)

Figure 4.9: Mean time to add user in a sorted user list of 10 runs Discussion | 39

Chapter 5

Discussion

The differences of the programming languages will be discussed in this chapter, with regards to the results as showcased in chapter 4. The differences between the languages do not need to be in favour of one another, but to demonstrate the impact of the difference, scenarios where the difference has an effect or is crucial will also be further discussed.

5.1 Flexibility and paradigms

JavaScript implements a lot of features that make development flexible, the developer is getting a lot of different ways to construct and implement the logic of a program. As shown in subsection 4.1.1, JavaScript introduces a lot of keywords that could more or less result in the same functionality. For example, the function keyword can be used instead of class to construct an object with properties and methods. By also exposing the developer to both use a lot of the object-oriented paradigm as well as the functional paradigm, the developer may choose which one of these that suits them the best. In contrast to this, Reason implements a more of a strict environment, where most of the flexibility comes in the form of a large variety of data structures, while the ways of solving a problem remains pretty linear by focusing more on the functional paradigm and encouraging developers to make use of immutable and pure programming, as shown in subsection 4.1.2. However, by including opt-in for side-effects, mutation and objects, more object-oriented programs could also be written. Both languages implement the functional programming paradigm in some way, but Reason does this to a larger extent, due to most of the constructs have been implemented with the functional programming paradigm in mind 40 | Discussion

and also the focus on immutability. Thus, Reason could be favourable for developers who desire to program according to the functional paradigm whereas JavaScript would be more reasonable for developers who aim to develop according to the object-oriented paradigm or make use of both paradigms. For a developer who wants to learn more about both the object-oriented and functional programming paradigms, JavaScript could be very useful. For example, exercises where a developer develop an object-oriented and a functional program that solves the exact same problem can be constructed to be able to learn the fundamental differences between the two. Since functional programming has become popular in academia [32] and also becoming more popular in the area of artificial intelligence [33], Reason has the potential to be more useful than JavaScript within those areas, and be able to attract more researchers and artificial intelligence developers that are coming from Haskell, Erlang, or even OCaml.

5.2 Data structures and typing

As shown in subsection 4.2.1, JavaScript has a limited amount of freedom when it comes to data structures, and combining that with the dynamic type system it implements, it can become difficult to define advanced types and keep it consistent throughout the execution of the program. On the contrary, Reason can make sure that a variable is always the value that it is expected to be using its static typing system. This, along with Reason’s amount of data structures and the ability to constructs variants, makes it easier to configure advanced data types. Thus, when working with advanced types and desires strict type checking, Reason could be beneficial. One scenario where it would be important to specify types explicitly would be when creating an API since it would be possible to type check the input from the clients using the API and make sure that the input is explicit as it is specified, and not going further with execution if it is not. Also, by explicitly telling the program what types it consists of, the ones implementing the API will know exactly how the response types will look like.

5.3 Reliability and testing

With the results achieved from the faulty programs, as seen in Table 4.1, we can see that Reason had a much higher frequency of catching errors that Discussion | 41

would normally not be caught in JavaScript, even when using a linter, like ESLint. This could mean that when writing a program using Reason, you could expect fewer errors when writing the program. Which could lead to being less reliant on writing test scenarios to ensure the program’s reliability, however, test scenarios for functionality would still need to be written. This could be beneficial in large and advanced applications where a lot of tests would normally be written as most of it will be caught by the compiler instead, which would mean a larger focus on writing a reliable program instead of tests cases; as a result, this could increase the efficiency of the development process. Also, considering that Reason provides soundness, the developer does not necessarily need to create test cases for each value that a variable can hold, because the compiler makes sure that the operations applied to that variable are in line with the possible values it might hold.

5.4 Community support and engagement

From the data gathered from GitHub, Stack Overflow, and npm, we can firstly see that JavaScript got a much larger and very active community. However, when it comes to active GitHub repositories with more than 10 stars, Reason has seen an increase in every measurement period that passed, whereas JavaScript decreased every year. The data gathered from Stack Overflow where rather fluctuating, where Reason questions, in general, received fewer views and answers on average compared to JavaScript, and while the created questions for JavaScript have been pretty static, Reason has had a fluctuating number of questions published. The spike seen in Figure 4.4 from the first measurements of Reason is caused by there only being one question published about Reason during that period that had three answers. Hence, the results from that measurement are non-representative of the actual activity on Reason questions on Stack Overflow during that period. From the results of the findings considering community-created packages, Reason has seen a lack of growth in the recent year, with it only grew around 60 packages in 2019, which is less than 2018, where it grew around 100 packages; however, due to the data being manually modified by developers, there might take a while for new packages to appear in the list, and some might not even get added. When looking at the whole npm registry, however, shown in Figure 4.6, it follows a rather fast growth, with it growing around 190.000 packages in 2018 and around 490.000. Though not all of the packages within npm are JavaScript packages, we can assume a large majority of them are. 42 | Discussion

Considering the lack of Reason libraries in comparison to JavaScript, it could be rather difficult for someone who is used to working with a lot of different packages and dependencies to choose from. Since Reason got support for using JavaScript packages by creating a wrapper for it, as shown in section 4.6.2, it is possible to make use of the regular npm packages; this could be a pretty tedious process for the developer if there is a large number of functions that are going to be used from the packages, making development and configuration time longer. It also makes maintenance harder since every time the packages gets an update, the wrapper needs to be reconfigured to adapt to the changes. Therefore, if a project required a large number of dependencies or specific dependencies where a wrapper does not exist and is hard to create, JavaScript might be a more viable choice. However, if one does not plan on using a large number of dependencies and want to develop most of the program by hand, both Reason and JavaScript are viable options. Furthermore, due to JavaScript projects containing around 20 dependencies, on average, it could therefore be difficult for a JavaScript developer to limit themselves to such a small number of available dependencies and not being able to use the dependencies as easily that they could do with JavaScript.

5.5 Job openings and market demand

By looking at the results from analyzing LinkedIn and Indeed in 4.5, we can observe that the available job openings for Reason development are rather low in comparison to JavaScript and that some of the job openings found for Reason also required JavaScript as a prerequisite. This probably has to do with that Reason has not yet reached the industry at a large scale, whilst JavaScript has become one of the most widely used languages in the whole industry. Considering this, it can be hard to enter the industry as a pure Reason developer and using it as your main programming language, however, it could still be a useful skill to have beside knowing JavaScript. Since the demand for Reason developers is so low, it could affect the overall survival of Reason and its community, since a higher market demand could interest new developers to start developing with it. Discussion | 43

5.6 Portability and interoperability

As shown at the investigation results in 4.6, Reason supports multiple ways to integrate regular JavaScript in Reason code, however, to do it properly there is extra complexity added through multiple new keywords from BuckleScript that need to be used, and some extra code needs to be written. The wrappers for JavaScript functions written in Reason must also be data type accurate according to the BuckleScript type conversion, if any type is converted wrongly, the error will only be caught during execution, since the compiler always assumes that the types written for the wrapper are always correct and up to date, this could lead to maintenance issues when dealing with dependencies that are updated frequently or that includes complex data. This, and the amount of code that needs to be written for the wrappers to behave correctly within Reason, could have an impact of the development efficiency and could add a lot of extra complexity to the code. Thus, it is hard to recommend using the Reason in combination with JavaScript in cases where there are not any existing well-maintained wrappers for the resource being used or if only simple wrappers need to be created, for example for JavaScript’s standard library functions. This, together with the limited number of dependencies available for Reason, as discussed in Section 5.4, could result in a difficult and time- consuming process for a JavaScript developer who desires to use the dependencies that they are used to in Reason. And since JavaScript projects usually contain a large number of dependencies it could become a very difficult task to recreate a JavaScript codebase using Reason.

5.7 Performance

The results from the performance test, shown in section 4.7, indications that there are not that much of a difference between the two, performance-wise. Some minor fluctuation can be observed between the different runs, however, a consistent and somewhat significant decrease in performance can be observed from the Reason tests when running the tests that test the time it takes to add users, which can be seen in Figure 4.9. One reason for this could be that Reason implements a custom JavaScript- written sorting function for sorting arrays using the Array.sort method, which uses the heapsort technique [34]. When it comes to pure JavaScript, the implemented sorting function for arrays, Array.prototype.sort, use 44 | Discussion

different implementations depending on the JavaScript-engine. Due to the sorting function being integrated within the engine, it could be optimized to a higher degree than the Reason method is. The engine used for the tests, the V8 engine, implements the Timsort technique, a mixture of mergesort and selection sort, optimized for real-world problems [35]. Although Timsort and heapsort both got an average and worst-case complexity of O(n log n), while Timsort achieves a best-case complexity of O(n) while heapsort still maintains a complexity of O(n log n). Hence, the algorithm choice and how the method is implemented could have affected the outcome of the tests; although, a further look into this need to be done to draw any clear conclusions. Conclusion | 45

Chapter 6

Conclusion

This chapter aims to conclude the thesis with a summary the findings to try to tie them together with the initial goals of the thesis. Some final thoughts along with a reflection on the limitations of this thesis and ideas of future research will also be presented.

6.1 Why should someone use Reason?

It is fair to say that Reason introduce new concepts and possibilities for developers that are available through regular JavaScript while also fixing a lot of the problems people have with it. An attempt to summarize some of the potential benefits one could achieve by using Reason are presented further in this section. However, it is worth noting that these points might not be considered true benefits and might prefer JavaScript implementation of it.

Static type system A static type system with full coverage of data types and soundness could relive the developer of an abundance of testing scenarios and usage errors.

No aggressive performance loss As shown by the results in Chapter 4.7, no major performance loss is seen when using Reason to create JavaScript applications. 46 | Conclusion

Compilation before runtime Errors is thrown during compile time instead of runtime, which means errors can be found faster and more efficiently which also could reduce the number of tests to be written.

Functional syntax and constructs Reason implement the functional paradigm in a more aggressive way than JavaScript, meaning that it could be beneficial for people who prefer or benefits from writing according to that paradigm or wants to learn it.

Advanced types With Reason’s Variant construct, it is possible to construct custom data types that can be configured to fit the developer’s needs.

Friendly for OCaml developers Reason inherits a lot of its elements from the OCaml language, which could make Reason newcomer-friendly for OCaml developers.

Pattern matching Reason introduces a pattern matching system to destruct data and execute different statements depending on the structure of the data.

6.2 Why should not someone use Reason?

Even though Reason introduces new features that JavaScript do not deliver on, there are some aspects of JavaScript features that could make it harder for the developer to build what needs to deliver. Some of the potential drawbacks from using Reason is listed in further in this section.

Less freedom with problem-solving With Reason’s strict nature you will need to solve in a more linear functional oriented way, in contrast to JavaScript where the developer has more possibilities to find solutions to problems. Conclusion | 47

Not utilizing all internal JavaScript functions As discussed in Chapter 5.7, Reason does not utilize all of the functionality integrated within the JavaScript engines, which could lead to the use of non- optimized results.

Low market demand When applying to jobs for Reason developing it can be hard to find any significant due to it not hitting the industry yet, and is debatable if it ever will.

A small community with small growth The Reason community has not seen a large community growth with the amount of community-supported packages growing in a slow pace and the activity on Stack Overflow and GitHub being pretty much static over the last 2 years.

Non-straightforward interoperability For JavaScript code to interact with Reason fully, wrappers that specifies the types of all the argument values and return values need to be written, which could be hard for more advanced types, like objects with a lot of properties.

Potentially steep learning curve With a more strict functional nature and less flexibility, it can hard for someone with little knowledge of the functional paradigm to learn the language in comparison to JavaScript.

Fragmented documentation Some BuckleScript functionality that Reason uses is not stated in the Reason documentation but rather the BuckleScript documentation, which might lead to confusion.

6.3 When should or should not someone use Reason instead of JavaScript?

Since these potential benefits and drawbacks could have different weight for each developer and scenario, it would not be accurate to objectively determine 48 | Conclusion

what is more important than the other. If the potential benefits of Reason outweigh the potential drawbacks, listed in the two previous sections, Reason might sound like an overall attractive alternative to JavaScript to the developer. And there are some scenarios where Reason really shine, like when building an advanced applications with complex data structures, or an API where the output can be clearly specified and throw error when the input does not have the correct type or structure. It also serves as a great tool for OCaml developers to get into web development. If the potential drawbacks outweigh the potential benefits of Reason, it would be hard to recommend the usage of Reason. And for existing JavaScript codebases, the transition from JavaScript to Reason could result in a lot of compromises to be made, especially with dependencies, which could result in a lot of time-consuming work and lower the overall efficiency of development.

6.4 Final thoughts

Due to the rather non-straightforward interoperability, it could be hard to integrate an existing JavaScript codebase with Reason, which affects the integration of the benefits of JavaScript to Reason, this could be a major flaw in its integration and could potentially be one of the more frustrating and major drawbacks of it. So, when a team intends to use Reason within a project, it could be a good idea to isolate the parts of the codebase that uses Reason and that is not using Reason, otherwise, it could lead to time-consuming tasks which require a lot of extra code to be written. And it is very important for a team to consider both the potential benefits and the potential drawbacks of implementing Reason and that its features are important for the projects development process. Another major thing that might be worthy of considerations is the general life span of Reason. The results gathered throughout this project shows that the engagement by the community has not changed drastically in the two recent years, which could be a bad sign for a language as young as Reason. If it does not get the recognition and usage that the developers desire, it might result in an abandonment of the project.

6.5 Limitations and future research

This section aims to suggest further research that could be conducted to contribute to more insight within the area covered in this thesis. Conclusion | 49

6.5.1 Investigation of other JavaScript alternatives This study only looks into Reason and JavaScript into account, and of course, other JavaScript-compiled languages could also be worth investigating, like for example TypeScript, Elm and Dart. Since TypeScript has grown a lot in the recent years it could be beneficial and interesting to investigate further how TypeScript and Reason try to solve the problems that come with JavaScript and the reasons why TypeScript have gained the amount of popularity and recognition it has, while Reason has yet to see the same amount of success. Elm would specifically be worth investigating since it has a lot of the features that Reason take pride in. But while Elm were in general very appreciated by the public when it was released, it has been on a decline in popularity in the recent years, it would be interesting to compare these two languages and see where Elm failed so that Reason could avoid going in the same direction.

6.5.2 Interoperability improvements Further research and investigation could be done in finding good solutions for solving the issue with JavaScript interoperability in a statically typed and functional language like Reason. A suggestion for areas to investigate in this topic would be how to be able to create binding between the two languages in a way which requires the least amount of code and complexity, alternatively, if it would possible to determine the types of data through the actions performed on it in JavaScript. 50 | Conclusion REFERENCES | 51

References

[1] S. Cass. (2019, Sep) IEEE Spectrum: Technology, Engineering, and Science News: The Top Programming Languages 2019. Accessed: 2020-03-16. [Online]. Available: https://spectrum.ieee.org/computing/ software/the-top-programming-languages-2019

[2] OpenJS Foundation. Node.js. Accessed: 2020-03-16. [Online]. Available: https://nodejs.org/en/about/

[3] GitHub. Electron. Accessed: 2020-03-16. [Online]. Available: https: //www.electronjs.org/

[4] Facebook. React Native. Accessed: 2020-03-16. [Online]. Available: https://reactnative.dev/

[5] J. Ashkenas. (2020, 03) List of languages that compile to JS. Accessed: 2020-03-16. [Online]. Available: https://github.com/ jashkenas/coffeescript/wiki/List-of-languages-that-compile-to-JS

[6] Facebook. Reason: What & Why. Accessed: 2020-03-30. [Online]. Available: https://reasonml.github.io/docs/en/what-and-why

[7] J. Tomaszewski. (2018, Dec) Why TypeScript is the best way to write Front-end in 2019–2020+. Accessed: 2020-06- 02. [Online]. Available: https://medium.com/@jtomaszewski/ why-typescript-is-the-best-way-to-write-front-end-in-2019-feb855f9b164

[8] inVerita. (2020, Jan) Why Flutter is the development trend of 2020. Accessed: 2020-06- 02. [Online]. Available: https://levelup.gitconnected.com/ why-flutter-is-a-development-trend-of-2020-d81ca0813a73

[9] A. Rauschmayer, Speaking JavaScript. Shroff Publishers & Distr, 2014. 52 | REFERENCES

[10] W3Techs. Usage statistics of JavaScript as client-side programming language on websites. Accessed: 2020-03-29. [Online]. Available: https://w3techs.com/technologies/details/cp-javascript

[11] Stack Overflow. Stack Overflow Developer Survey 2019. Accessed: 2020-03-29. [Online]. Available: https://insights.stackoverflow.com/ survey/2019

[12] . (2020, Mar) JavaScript language resources. Accessed: 2020- 03-30. [Online]. Available: https://developer.mozilla.org/en-US/docs/ Web/JavaScript/Language_Resources

[13] Ecma International. (2020, Mar) ECMAScript R 2020 Language Specification. Accessed: 2020-03-30. [Online]. Available: https: //tc39.es/ecma262/

[14] Mozilla. (2020, Mar) JavaScript data types and data structures. Accessed: 2020-03-30. [Online]. Available: https://developer.mozilla. org/en-US/docs/Web/JavaScript/Data_structures

[15] A. Rauschmayer. (2013, Sep) JavaScript’s type system. Accessed: 2020-05-11. [Online]. Available: https://2ality.com/2013/09/types.html

[16] M. Bynens. (2018, Jun) JavaScript engine fundamentals: Shapes and Inline Caches. Accessed: 2020-03-30. [Online]. Available: https: //mathiasbynens.be/notes/shapes-ics

[17] JS Foundation. ESLint. Accessed: 2020-04-08. [Online]. Available: https://eslint.org/

[18] K. Waclena. (2006, Jun) OCaml for the Skeptical: Built-In Data Types. Accessed: 2020-03-30. [Online]. Available: https://www2.lib.uchicago. edu/keith/ocaml-class/data.

[19] What is OCaml? Accessed: 2020-06-04. [Online]. Available: https://ocaml.org/learn/description.html

[20] w3schools. JavaScript Common Mistakes. Accessed: 2020-04-08. [Online]. Available: https://www.w3schools.com/js/js_mistakes.asp

[21] ReasonReact. Accessed: 2020-03-16. [Online]. Available: https: //reasonml.github.io/reason-react/ REFERENCES | 53

[22] Facebook. Profiling Components with the DevTools Profiler. Accessed: 2020-04-01. [Online]. Available: https://reactjs.org/docs/optimizing-performance.html# profiling-components-with-the-devtools-profiler

[23] ——. Type! Accessed: 2020-04-17. [Online]. Available: https: //reasonml.github.io/docs/en/type

[24] Z. Gao, C. Bird, and E. T. Barr, “To type or not to type: Quantifying detectable bugs in javascript,” 2017 IEEE/ACM 39th International Conference on Software Engineering (ICSE), 2017. doi: 10.1109/icse.2017.75

[25] Stack Overflow. Stack Overflow Data Explorer. Accessed: 2020-04-13. [Online]. Available: https://data.stackexchange.com/

[26] Redex. Reason Package Index. Accessed: 2020-04-14. [Online]. Available: https://redex.github.io/

[27] ——. GitHub: redex/data. Accessed: 2020-04-14. [Online]. Available: https://github.com/redex/data

[28] E. DeBill. Modulecounts. Accessed: 2020-04-14. [Online]. Available: http://www.modulecounts.com/

[29] M. Janaszek. (2018, Sep) State of package. dependencies. Accessed: 2020-05-12. [Online]. Available: https://medium.com/ warsawjs/state-of-package-json-dependencies-de99828b6c3f

[30] Indeed. ReasonML Jobs. Accessed: 2020-04-16. [Online]. Available: https://www.indeed.com/jobs?q=reasonml&vjk=5ab1385ec546a6fd

[31] LinkedIn. ReasonML Jobs. Accessed: 2020-04-16. [Online]. Available: https://www.linkedin.com/search/results/all/?keywords= reasonml&location=Worldwide

[32] P. Hudak, J. Hughes, S. P. Jones, and P. Wadler, “A history of haskell,” Proceedings of the third ACM SIGPLAN conference on History of programming languages - HOPL III, 2007. doi: 10.1145/1238844.1238856

[33] M. Priestley, “Ai and the origins of the functional programming language style,” Minds and Machines, vol. 27, no. 3, p. 449–472, Feb 2017. doi: 10.1007/s11023-017-9432-7 54 | REFERENCES

[34] Reason. Module Array. Accessed: 2020-04-29. [Online]. Available: https://reasonml.github.io/api/Array.html

[35] S. Zünd. (2018, Sep) Getting things sorted in V8. Accessed: 2020-04-29. [Online]. Available: https://v8.dev/blog/array-sort Appendix A: Faulty code and output | 55

Appendix A

Faulty code and output

A.I Faulty JavaScript Code

Listing A.1: assignment.js 1 let a = 3; 2 if ((a = 4)) {//() error Unexpected constant condition no-constant-condition 3 console.log("a is equal to 4!"); 4 } 5 if ((a = 3)) {//(eslint) error Unexpected constant condition no-constant-condition 6 console.log("a is equal to 3!"); 7 } 8 9 /* 10 Output: 11 a is equal to 4! 12 a is equal to 3! 13 */

Listing A.2: broken-return.js 1 const func=(a) => { 2 let 3 power = 10; 4 return 5 a* power;//(eslint) error Unreachable code no-unreachable 6 }; 7 console.log(func(10)); 8 9 /* 56 | Appendix A: Faulty code and output

10 Output: 11 undefined 12 */

Listing A.3: equals.js 1 const zeroInt = 0; 2 const zeroString="0"; 3 4 if (zeroInt == zeroString){ 5 console.log(‘${zeroInt} is equal to"${ zeroString}"‘); 6 } else { 7 console.log(‘${zeroInt} is not equal to${ zeroString}‘); 8 } 9 /* 10 Output: 11 0 is equal to "0" 12 */

Listing A.4: floats.js 1 const x = 0.1; 2 const y = 0.2; 3 const z=x+y; 4 if (z == 0.3) { 5 console.log(‘${x} +${y} is 0.3‘); 6 } else { 7 console.log(‘${x} +${y} is${z}‘); 8 } 9 10 /* 11 Output: 12 0.1+ 0.2 is 0.30000000000000004 13 */

Listing A.5: named-index.js 1 const person = []; 2 person["firstName"] ="John"; 3 person["lastName"] ="Doe"; 4 person["age"] = 46; 5 var x= person.length; 6 var y= person[0]; 7 8 console.log(x); 9 console.log(y); Appendix A: Faulty code and output | 57

10 /* 11 Output: 12 0 13 undefined 14 */

Listing A.6: semicolons.js 1 const x = 42; 2 if (x == 19); 3 { 4 console.log("x is 19"); 5 } 6 /* 7 Output: 8 x is 19 9 */ A.II Faulty Reason Code

Listing A.7: assignment.re 1 let a = 3; 2 if (a=4){ 3 Js.log("a is equal to4"); 4 }; 5 if (a=3){ 6 Js.log("a is equal to3"); 7 }; 8 /* 9 Compile output: 10 3| leta= ref(3); 11 4| 12 5| if(a.contents= 4){ 13 6| Js.log("a is equal to 4"); 14 7|}; 15 16 This has type: 17 unit 18 But somewhere wanted: 19 bool 20 */

Listing A.8: brokenReturn.re 1 let func=a => { 2 let power = 10; 58 | Appendix A: Faulty code and output

3 a* power; 4 }; 5 6 Js.log(func(100)); 7 /* 8 Output: 9 1000 10 */

Listing A.9: equals.re 1 let zeroInt = 0; 2 let zeroString="0"; 3 4 if (zeroInt == zeroString){ 5 Js.log(zeroInt+" is equal to"+ zeroString) ; 6 } else { 7 Js.log(zeroInt+" is not equal to"+ zeroString); 8 }; 9 /* 10 Compile output: 11 4| let zeroString= "0"; 12 5| 13 6| if(zeroInt == zeroString){ 14 7| Js.log(zeroInt+" is equal to"+ zeroString); 15 8|} else{ 16 17 This has type: 18 string 19 But somewhere wanted: 20 int 21 */

Listing A.10: floats.re 1 let x = 0.1; 2 let y = 0.2; 3 let z=x +.y; 4 5 if (z == 0.3) { 6 Js.log( 7 Js.Float.toString(x) ++"+" ++ Js.Float. toString(y) ++" is 0.3", 8 ); 9 } else { Appendix A: Faulty code and output | 59

10 Js.log( 11 Js.Float.toString(x) 12 ++"+" 13 ++ Js.Float.toString(y) 14 ++" is not 0.3, it is" 15 ++ Js.Float.toString(z), 16 ); 17 }; 18 /* 19 Output: 20 0.1+ 0.2 is not 0.3, it is 0.30000000000000004 21 */

Listing A.11: namedIndex.re 1 let person = [||]; 2 person["firstName"] ="John"; 3 person["lastName"] ="Doe"; 4 person["age"] = 46; 5 6 let x= person.length;// person.length will return0 7 let y= person[0];// person[0] will return undefined 8 9 Js.log(x); 10 Js.log(y); 11 /* 12 Compile output: 13 2| 14 3| let person= [||]; 15 4| person["firstName"]="John"; 16 5| person["lastName"]="Doe"; 17 6| person["age"]= 46; 18 19 This has type: 20 string 21 But somewhere wanted: 22 int 23 */

Listing A.12: semicolons.re 1 let x = 42; 2 if (x == 19); 3 { 4 Js.log("x is 19"); 60 | Appendix A: Faulty code and output

5 } 6 /* 7 Compile output: 8 Error: Syntax error 9 */ Appendix B: Code for fetching community support data | 61

Appendix B

Code for fetching community support data

Listing B.1: Program for fetching data from GitHub 1 const fetch= require ("node-fetch"); 2 const argv= process.argv.slice(2); 3 4 const stars= argv.length? argv[0] :"10"; 5 6 const created= argv.length >1&& argv[1]; 7 8 const starsQuery = ‘+stars:${stars}‘; 9 const createdQuery= created ? ‘+created:>${ created}‘:""; 10 11 const baseUrl="https://api.github.com/search/ repositories?"; 12 13 const fetchLanguageRepoCount=(language) => { 14 fetch( 15 ‘${baseUrl}q=language:${language.toLowerCase ()}${starsQuery}${createdQuery}&per_page =1 ‘ 16 ) 17 .then((res) => res.json()) 18 .then(({ total_count }) => { 19 console.log( 20 ‘Amount of${language} repos with${ stars} stars:${total_count}‘ 21 ); 22 }); 23 }; 62 | Appendix B: Code for fetching community support data

24 25 fetchLanguageRepoCount("JavaScript"); 26 fetchLanguageRepoCount("Reason");

Listing B.2: Query used for getting data from Stack Overflow 1 DECLARE @total float 2 SELECT @total= Sum ( Cast (ViewCount as bigint)) FROM Posts WHERE PostTypeId=1 3 4 SELECT 5 Tags.Tagname AS Tag, 6 Count (*) AS Questions, 7 Sum ( Cast (Posts.ViewCount as bigint)) AS Views, 8 Sum (Posts.AnswerCount) AS Answers, 9 Sum ( Cast (Posts.ViewCount as bigint))/ Count (*) AS AvgViews, 10 str( Sum (Posts.AnswerCount)/ Cast ( Count (*) AS Float ) ,6 ,2) AS AvgAnswers 11 FROM Posts 12 JOIN PostTags ON Posts.Id= PostTags.PostId 13 JOIN Tags ON PostTags.TagId= Tags.Id 14 WHERE Posts.PostTypeId=1 15 AND creationDate BETWEEN ##startDate: string?2020-01-01## AND ##endDate: string?2020-01-01## 16 AND (Tags.Tagname=’reason’ 17 OR Tags.Tagname=’reasonml’ 18 OR Tags.Tagname=’javascript’) 19 GROUPBY Tags.Tagname 20 ORDERBY Views DESC Appendix C: Code for performance testing | 63

Appendix C

Code for performance testing

C.I JavaScript performance code

Listing C.1: JavaScript code for testing time to render user list 1 const onRender=(_, phase, actualDuration) => { 2 if (phase ==="update"){ 3 if (state.iteration< iterations){ 4 results[index].times.push(actualDuration); 5 setState((prevState) => ({ 6 ...prevState, 7 iteration: prevState.iteration + 1, 8 })); 9 } else if (state.iteration === iterations){ 10 if (++index< testValues.length){ 11 setState({ 12 iteration: 0, 13 userAmount: testValues[index], 14 }); 15 } else { 16 // Done 17 calculateMean(); 18 } 19 } 20 } 21 };

Listing C.2: JavaScript code for testing time to remove user entry 1 const onRender=(_, phase, actualDuration) => { 2 if (phase ==="update"){ 3 if (iteration< iterations){ 4 if (iteration >= 0) { 64 | Appendix C: Code for performance testing

5 results[index].times.push(actualDuration ); 6 } 7 iteration++; 8 } else { 9 iteration = -1; 10 if (++index< testValues.length){ 11 setState({ 12 userAmount: testValues[index], 13 }); 14 } else { 15 // Done 16 calculateMean(); 17 } 18 } 19 } 20 };

Listing C.3: JavaScript code for testing time add entry in sorted user list 1 const onRender=(_, phase, actualDuration) => { 2 if (phase ==="update"){ 3 if (state.iteration< iterations){ 4 if (state.iteration >= 0) { 5 results[index].times.push(actualDuration ); 6 } 7 setState ((prevState) => ({ 8 ...prevState, 9 iteration: prevState.iteration + 1, 10 })); 11 } else { 12 if (++index< testValues.length){ 13 setState ({ 14 iteration: -1, 15 userAmount: testValues[index], 16 }); 17 } else { 18 // Done 19 calculateMean(); 20 } 21 } 22 } 23 }; C.II Reason performance code Appendix C: Code for performance testing | 65

Listing C.4: Reason code for testing time to render user list 1 let onRenderCallback=(_, phase, actualDuration ) => 2 if (phase ==="update"){ 3 if (state.iteration< iterations){ 4 results[index.contents].times 5 ->Array.set(state.iteration, actualDuration); 6 setState (prevState => 7 {...prevState, iteration: prevState. iteration + 1} 8 ); 9 } else if (state.iteration === iterations) { 10 incr (index); 11 if (index.contents< results->Array.length ){ 12 setState (_ => 13 {iteration: 0, userAmount: testValues[ index.contents]} 14 ); 15 } else { 16 // Done 17 calculateMean(); 18 }; 19 }; 20 };

Listing C.5: Reason code for testing time to remove user entry 1 let onRenderCallback=(_, phase, actualDuration ) => 2 if (phase ==="update"){ 3 if (iteration.contents< iterations){ 4 if (iteration.contents >= 0) { 5 results[index.contents].times 6 ->Array.set(iteration.contents, actualDuration); 7 }; 8 incr (iteration); 9 } else { 10 iteration := (-1); 11 incr (index); 12 if (index.contents< results->Array.length ){ 13 setState (_ => {userAmount: testValues[ index.contents]}); 66 | Appendix C: Code for performance testing

14 } else { 15 // Done 16 calculateMean(); 17 }; 18 }; 19 };

Listing C.6: Reason code for testing time add entry in sorted user list 1 let onRenderCallback=(_, phase, actualDuration ) => 2 if (phase ==="update"){ 3 if (state.iteration< iterations){ 4 if (state.iteration >= 0) { 5 results[index.contents].times 6 ->Array.set(state.iteration, actualDuration); 7 }; 8 setState (prevState => 9 {...prevState, iteration: prevState. iteration + 1} 10 ); 11 } else { 12 incr (index); 13 if (index.contents< results->Array.length ){ 14 setState (_ => 15 {iteration: (-1), userAmount: testValues[index.contents]} 16 ); 17 } else { 18 // Done 19 calculateMean(); 20 }; 21 }; 22 }; For DIVA

{ "Author1": { "name": "Axel Pettersson"}, "Degree": {"Educational program": "Degree Programme in Information and Communication Technology"}, "Title": { "Main title": "Investigation of Reason as a substitute for JavaScript", "Language": "eng" }, "Alternative title": { "Main title": "Undersökning av Reason som ett substitut till JavaScript", "Language": "swe" }, "Supervisor1": { "name": "Thomas Sjöland" }, "Examiner": { "name": "Johan Montelius", "organisation": {"L1": "School of Electrical Engineering and Computer Science" } }, "Cooperation": { "Partner_name": "Slagkryssaren AB"}, "Other information": { "Year": "2020", "Number of pages": "xiii,66"} } TRITA-EECS-EX-2020:235

www.kth.se