[FREE PDF sample] Introducing ReScript: Functional Programming for Web Applications 1st Edition Danny Yang ebooks
[FREE PDF sample] Introducing ReScript: Functional Programming for Web Applications 1st Edition Danny Yang ebooks
com
https://ebookmass.com/product/introducing-rescript-
functional-programming-for-web-applications-1st-edition-
danny-yang/
OR CLICK HERE
DOWLOAD NOW
https://ebookmass.com/product/introducing-functional-programming-
using-c-leveraging-a-new-perspective-for-oop-developers-vaskaran-
sarcar/
ebookmass.com
https://ebookmass.com/product/php-8-basics-for-programming-and-web-
development-1st-edition-gunnard-engebreth/
ebookmass.com
https://ebookmass.com/product/social-studies-for-the-preschool-
primary-child-9th-edition-ebook-pdf/
ebookmass.com
https://ebookmass.com/product/hydrometallurgy-theory-1st-edition-
michael-nicol/
ebookmass.com
https://ebookmass.com/product/conservation-technology-serge-a-wich/
ebookmass.com
ebookmass.com
https://ebookmass.com/product/college-algebra-11e-11th-edition-ron-
larson/
ebookmass.com
Graph Data Science with Neo4j: Learn how to use Neo4j 5
with Graph Data Science library 2.0 and its Python driver
for your project Scifo
https://ebookmass.com/product/graph-data-science-with-neo4j-learn-how-
to-use-neo4j-5-with-graph-data-science-library-2-0-and-its-python-
driver-for-your-project-scifo/
ebookmass.com
Introducing
ReScript
Functional Programming for
Web Applications
—
Danny Yang
Introducing ReScript
Functional Programming
for Web Applications
Danny Yang
Introducing ReScript: Functional Programming for Web Applications
Danny Yang
Mountain View, CA, USA
Introduction���������������������������������������������������������������������������������������xiii
iii
Table of Contents
Chapter 2: Functions��������������������������������������������������������������������������29
Defining and Using Functions�����������������������������������������������������������������������������29
Type Annotations�������������������������������������������������������������������������������������������31
Using Standard Library Functions and Opening Modules������������������������������32
Higher-Order Functions���������������������������������������������������������������������������������34
Piping������������������������������������������������������������������������������������������������������������35
Labeled and Optional Parameters�����������������������������������������������������������������38
Currying and Partial Application��������������������������������������������������������������������40
Polymorphic Functions����������������������������������������������������������������������������������42
Pure Functions����������������������������������������������������������������������������������������������������43
Ignoring Return Values����������������������������������������������������������������������������������44
Recursion������������������������������������������������������������������������������������������������������������46
Syntax������������������������������������������������������������������������������������������������������������46
How to Use Recursion�����������������������������������������������������������������������������������48
Final Thoughts�����������������������������������������������������������������������������������������������������52
iv
Table of Contents
v
Table of Contents
Printing Objects�������������������������������������������������������������������������������������������105
Objects and JSON����������������������������������������������������������������������������������������106
Objects vs. Records������������������������������������������������������������������������������������������108
Chapter 6: Collections����������������������������������������������������������������������141
Immutable Collections��������������������������������������������������������������������������������������142
Immutable Sets�������������������������������������������������������������������������������������������143
Immutable Maps������������������������������������������������������������������������������������������146
vi
Table of Contents
Chapter 7: Modules��������������������������������������������������������������������������173
Files as Modules�����������������������������������������������������������������������������������������������174
Defining Modules����������������������������������������������������������������������������������������������174
Using Modules��������������������������������������������������������������������������������������������������175
Opening Modules�����������������������������������������������������������������������������������������177
Destructuring a Module�������������������������������������������������������������������������������181
Module Examples����������������������������������������������������������������������������������������������182
Module Signatures��������������������������������������������������������������������������������������������188
Interface Files����������������������������������������������������������������������������������������������189
Defining Module Signatures������������������������������������������������������������������������189
Functors������������������������������������������������������������������������������������������������������194
Defining and Using Functors�����������������������������������������������������������������������195
Extending Modules��������������������������������������������������������������������������������������197
Functors in the Standard Library�����������������������������������������������������������������199
Final Thoughts���������������������������������������������������������������������������������������������������200
vii
Table of Contents
Index�������������������������������������������������������������������������������������������������255
viii
About the Author
Danny Yang is a professional software engineer at Meta working on
infrastructure for WhatsApp. He has previously worked on Facebook
Messenger, including the web interface which was written in ReScript.
His technical interests include functional programming, compilers, and
data visualization, which he writes about on his blog at www.yangdanny97
.github.io.
ix
About the Technical Reviewer
German Gonzalez-Morris is a software architect/engineer working
with C/C++, Java, and different application containers, in particular
with WebLogic Server. He has developed various applications using JEE,
Spring, and Python. His areas of expertise also include OOP, Java/JEE,
Python, design patterns, algorithms, Spring Core/MVC/security, and
microservices. German has worked with performance messaging, RESTful
API, and transactional systems. For more information about him, visit
www.linkedin.com/in/german-gonzalez-morris.
xi
Introduction
Why Learn ReScript?
JavaScript is vital to the modern web ecosystem. It’s used in the front end
to implement websites and other user interfaces, and used in the back end
to implement servers for websites and APIs.
Part of JavaScript’s ubiquity is due to its ease of use. JavaScript is
dynamic and flexible, making it easy for people to pick up. However, this
strength becomes a weakness when working on large web applications
with multiple developers – the only way to know that JavaScript code works
correctly is to actually run it, and it’s relatively easy to make mistakes when
programming in JavaScript.
What if there was a way to detect bugs in JavaScript before running
the code, or prevent many classes of bugs altogether? What if there was a
language that was concise and elegant that made it easy for programmers
to write complex web applications and hard for programmers to make
mistakes?
Enter ReScript.
ReScript is a language designed for writing web applications. It brings
a lot to the table: static typechecking, a strong type system, and powerful
language features that will change the way you program.
Here’s a glimpse of some of the features that make ReScript a great
language:
xiii
Introduction
There are a number of other languages and tools that offer static
typechecking for web applications, but ReScript has several key advantages
over its competitors. As an example, let’s look at the benefits ReScript has
compared with another popular JavaScript alternative, TypeScript:
xiv
Introduction
History of ReScript
The lineage of ReScript can ultimately be traced back to the ML family of
languages originating from the 1960s. In particular, ReScript is directly
based on OCaml, a general-purpose programming language that was
developed in the 1980s and used today for systems programming in
academia and industry.
In 2015, Jordan Walke, the creator of the React web framework,
developed a toolchain and alternative syntax for OCaml called Reason.
Reason was designed to bridge the gap between the web and OCaml
ecosystems – it could be compiled into both native machine code and
JavaScript, allowing web developers to take advantage of OCaml’s
features. Static typechecking and OCaml’s sound type system eliminated
many common bugs in JavaScript code, and OCaml’s immutability and
functional style was a great fit for React.
Reason was compiled to JavaScript using a compiler called
BuckleScript, which was developed at Bloomberg around the same time
Reason was being created at Facebook.
Around 2020, the BuckleScript project created a new language
based on Reason that could only be compiled to JavaScript using the
BuckleScript compiler, and so ReScript was born.
xv
Introduction
xvi
Introduction
xvii
Introduction
xviii
Introduction
Installing ReScript
ReScript projects are set up just like modern JavaScript projects, except we
have an extra development dependency on the rescript package.
Before we begin, make sure you have Node.js v10 or higher, and npm.
To check the version of Node.js you have, run node -v in your terminal. If
you don’t have Node.js installed, you can find installation instructions at
https://nodejs.org.
Once you’ve confirmed that you have the right version of Node.js
installed, create a new directory for your project, and run npm install
rescript@10 to install v10 of ReScript.
There will be a package.json file with the following contents inside the
project’s root directory. Add the following scripts to it:
{
...
"scripts": {
"build": "rescript",
"start": "rescript build -w"
}
}
xix
Introduction
Next, create a bsconfig.json file inside the same directory, with the
following contents:
{
"name": "your-project-name",
"sources": [
{
"dir": "src",
"subdirs": true
}
],
"package-specs": [
{
"module": "commonjs",
"in-source": true
}
],
"suffix": ".bs.js",
"bs-dependencies": []
}
The dir field specifies which directory ReScript source files are
located, in this case under the folder src. For every ReScript file Foo.res
under src, the compiler will output a JavaScript file named Foo.bs.js in
the same location as the original source.
Now we’re ready to write some ReScript!
xx
Introduction
Js.log("hello, world")
console.log("hello, world");
xxi
CHAPTER 1
ReScript Basics
In this chapter, we’ll dive right into the basic concepts of ReScript:
expressions, values, control flow, and binding. At the end of the chapter,
we’ll use those concepts in a simple command-line program.
2
Chapter 1 ReScript Basics
3
Chapter 1 ReScript Basics
Additionally, there are a few operations that are done using functions
instead of operators:
Here are some examples of int and float arithmetic operators and their
equivalents in JavaScript:
ReScript JavaScript
1+1 1+1
1.0 +. 1.0 1.0 + 1.0
1.0 +. float(1) 1.0 + 1
2.0 ** 3.0 Math.pow(2.0, 3.0)
float(2) ** float(3) Math.pow(2, 3)
Other standard library functions for ints and floats are found in the
Belt.Int, Belt.Float, Js.Int, Js.Float, and Js.Math modules. The
latter contains many useful utilities like random numbers, rounding,
trigonometry, and more.
4
Chapter 1 ReScript Basics
Boolean
The boolean values true and false in ReScript are exactly the same as
booleans in JavaScript. Unlike in JavaScript, there is no such thing as
interpreting non-boolean values like numbers or strings as “truthy” and
“falsy” in ReScript – the only possible values for the bool type are true and
false. Furthermore, only boolean values may be passed to conditionals
and boolean operators, like while, if, &&, ||, etc.
Here are some common boolean operators:
5
Chapter 1 ReScript Basics
x == x evaluates to true.
Note that equality operators can only be used on two values that are
the same type; for example, the expression 1 == "2" is not allowed and
will result in the following typechecker error:
String
String literals in ReScript are written with double quotes and may span
multiple lines. Strings can be concatenated using the ++ operator.
To convert other primitive values to strings, use the toString functions
in the standard library – for example, Js.Int.toString, Js.Float.
toString, etc. Here is an example of string concatenation and conversion:
6
Chapter 1 ReScript Basics
The standard library functions for strings are found in the Js.String2
module – for the most part, these functions are exactly the same as the
JavaScript function with the same name.
In JavaScript, we might trim and split a string like this:
let s = " 1,2,3,4,5 "
let s2 = s.trim().split(",")
let s = " 1,2,3,4,5 "
let s2 = s->Js.String2.trim->Js.String2.split(",")
Unit
ReScript has a type called unit that only has one possible value, the
unit value. Unit is the name of the type, AND it is the name of the single
possible value of that type.
Just like how the two possible values for the boolean type (true and
false) can be written with the literals true and false, the single possible
value for the unit type is written with the literal ().
In JavaScript, calling a function that does not return any values and
assigning the result to a variable will make the variable equal undefined.
In ReScript, the result is modeled as the unit value.
Since the ReScript compiler compiles () to undefined, the unit value is
undefined at run time.
7
Chapter 1 ReScript Basics
Js.log("hello")
8
Chapter 1 ReScript Basics
Bindings
Bindings in ReScript allow us to associate values with names so that
they can be referenced later. They are like variable declarations in other
languages, but we don’t call them variables in ReScript because the value
can’t be changed (more on that later).
Let bindings in ReScript look similar to variable let declarations in
JavaScript. Names must start with lowercase letters:
let x = 1
let y = 2
let z = x + y
Types may be added to a binding, but they are not required. If a type
is added, the compiler checks to make sure that the value on the right side
matches the declared type. If the type is not added, then the binding is
whatever type the compiler infers the right side to have:
let w: unit = ()
let x: int = 1
let y: bool = true
let z: string = "hello"
let x = 1
let x = 2
9
Chapter 1 ReScript Basics
let x: int = 1
let x: string = "hello"
ReScript JavaScript
10
Chapter 1 ReScript Basics
Compiler output:
var x = {
contents: 0
};
Compiler output:
var x = {
contents: 0
};
console.log(x.contents);
Console output:
Compiler output:
var x = {
contents: 0
};
x.contents = x.contents + 1 | 0;
console.log(x.contents);
11
Chapter 1 ReScript Basics
Console output:
Blocks
Multiple expressions can be grouped into a block, where they will be
evaluated in sequence. The result of evaluating the whole block is the
value of the last expression. Blocks are delimited by curly braces, and the
expressions within can be separated by newlines or semicolons.
Blocks must contain at least one expression or binding, and every
expression in a block except for the last one must evaluate to unit.
This expression block has type unit and evaluates to unit:
{
Js.log(1); Js.log(2); Js.log(3)
}
12
Chapter 1 ReScript Basics
{
Js.log("hello")
3
}
let x = {
Js.log("hello")
{
Js.log("world")
}
3
}
Js.log(x)
Console output:
Unused bindings, like those that are at the end of a block, evaluate
to unit:
let x: unit = {
let blah = 3
}
13
Chapter 1 ReScript Basics
Block Scoping
Bindings are local to each block.
This example prints 3, because x is only bound to the value 4 inside
that block. It is also a good showcase of immutable bindings – the value of
x is not updated by the new binding in the nested scope, only shadowed:
let x = 3
{
let x = 4
}
Js.log(x)
Console output:
Here’s an example which fails to compile, since the binding for y does
not exist outside of the nested scope:
let x = {
let y = Js.Math.random_int(0, 5)
y
}
let z = y
Compiler output:
Conditionals
If-expressions in ReScript do not behave like if-statements in JavaScript.
Instead, they are like ternaries – each branch is an expression and the
entire if-expression evaluates to the value of the branch corresponding
with the condition.
14
Chapter 1 ReScript Basics
ReScript JavaScript
ReScript JavaScript
15
Chapter 1 ReScript Basics
ReScript JavaScript
Switches
Switches in ReScript are very different from switches in JavaScript or most
other languages, to such an extent that I would say they are similar in
name only.
Although on the surface they both let us match some expression
against a number of cases and provide nice features like exhaustiveness
checking, there are a number of major differences that make ReScript’s
switches behave differently from switches in other languages:
16
Chapter 1 ReScript Basics
The last two points are very important – ReScript’s switches support
a powerful feature called pattern matching. Instead of only being able to
match primitive types against literal values, conditions can be expressed as
patterns, allowing cases to match complex conditions on compound data
types like tuples, lists, records, etc.
As you learn about more data types in ReScript, you’ll also learn how
to leverage pattern matching to work with them. For now, let’s see how
switches can be used on the simple data types we just covered.
When used for simple data types like integers, ReScript’s switches can
be used similarly to JavaScript’s switches. The basic syntax for a switch is
outlined in the following example. Each case begins with a pipe |, then the
value or pattern that we want to match against, then an arrow =>, and finally
the expression that we want to evaluate and return if that case matches.
A case that is just an underscore _ is a default or wildcard which
matches everything. Cases are evaluated in order, so it’s common to see a
wildcard case at the bottom, just like we would use a default in JavaScript
switch statements:
let x = Js.Math.random_int(0, 5)
switch x {
| 0 => Js.log("zero")
| 1 => Js.log("one")
| _ => Js.log("some other number")
}
switch x {
case 0:
console.log("zero");
break;
17
Chapter 1 ReScript Basics
case 1:
console.log("one");
break;
default:
console.log("some other number");
}
Conditions can fall through, allowing you to use the same body and
return the same value for multiple cases:
let x = Js.Math.random_int(0, 5)
switch x {
| 0 | 1 => Js.log("zero or one")
| _ => Js.log("some other number")
}
switch x {
case 0:
case 1:
console.log("zero or one");
break;
default:
console.log("some other number");
}
let x = Js.Math.random_int(0, 5)
let y = switch x {
| 0 | 1 => true
| _ => false
}
18
Chapter 1 ReScript Basics
var y;
switch x {
case 0:
case 1:
y = true;
break;
default:
y = false;
}
Patterns can also be used like bindings. When we use a name instead
of a literal in a pattern, it creates a binding with that name in the body of
the case:
let x = Js.Math.random_int(0, 5)
switch x {
| y => Js.log(y)
}
Be careful that the binding in the case does not accidentally shadow
another binding. For example, this switch statement that tries to check if x
and y are equal is incorrect:
let x = Js.Math.random_int(0, 5)
let y = Js.Math.random_int(0, 5)
switch x {
| y => Js.log("x == y")
| _ => Js.log("x != y")
}
19
Chapter 1 ReScript Basics
unused variable y.
This is because the first case is the equivalent of adding the let y
= x binding, thereby shadowing the binding for y instead of comparing
against the value of y. Therefore, the first case is always hit, not just when x
equals y.
The previous incorrect snippet is equivalent to the following:
let x = Js.Math.random_int(0, 5)
let y = Js.Math.random_int(0, 5)
switch x {
| _ => {
let y = x
Js.log("x == y")
}
}
Let’s go over how we would correctly write the switch from the
previous example.
If we want to match against a condition that is not a literal value, we
cannot include the value in the pattern directly. Instead, we can specify
more complex conditions using the when clause in a case:
let x = Js.Math.random_int(0, 5)
let y = Js.Math.random_int(0, 5)
switch x {
| x when x == y => Js.log("x == y")
| _ => Js.log("x != y")
}
20
Random documents with unrelated
content Scribd suggests to you:
back
back
back
back
back
back
back
back
back
back
back
back
back
back
back
back
back
back
back
back
back
back
back
back
back
back
back
back
Welcome to our website – the ideal destination for book lovers and
knowledge seekers. With a mission to inspire endlessly, we offer a
vast collection of books, ranging from classic literary works to
specialized publications, self-development books, and children's
literature. Each book is a new journey of discovery, expanding
knowledge and enriching the soul of the reade
Our website is not just a platform for buying books, but a bridge
connecting readers to the timeless values of culture and wisdom. With
an elegant, user-friendly interface and an intelligent search system,
we are committed to providing a quick and convenient shopping
experience. Additionally, our special promotions and home delivery
services ensure that you save time and fully enjoy the joy of reading.
ebookmass.com