C/CPS 506
Comparative Programming Languages Prof. Alex Ufkes
Topic 3: Out with Smalltalk, in with Elixir
Notice!
Obligatory copyright notice in the age of digital delivery and online classrooms:
The copyright to this original work is held by Alex Ufkes. Students registered in course CCPS 506 can use this material for the purposes of this course but no other use is permitted, and there can be no sale or transfer or use of the work for any other purpose without explicit permission of Alex Ufkes.
© Alex Ufkes, 2020, 2021 2
Course Administration
© Alex Ufkes, 2020, 2021
3
• •
Assignment description is posted!
If you liked Smalltalk, you could start working on the Smalltalk version.
Today
© Alex Ufkes, 2020, 2021
4
• Double dispatch
• Smalltalk conclusion
• Functional paradigm
• Getting started with Elixir
© Alex Ufkes, 2020, 2021
5
Method “Overloading”
Method Overloading
In Java, methods are overloaded through differing parameter lists:
• In Java, method name and parameter list are independent.
• In Smalltalk, they are fundamentally linked
© Alex Ufkes, 2020, 2021 6
Method Overloading
© Alex Ufkes, 2020, 2021
7
• In Smalltalk, there is no overloading in this fashion.
• We cannot have a single message that optionally
accepts differing numbers of arguments.
• When we add another argument, the method name
changes.
Method Overloading
When we add another argument, the method/message name changes.
• valueandvalue:are different names
• value:andvalue:value: are different names
• And so on
© Alex Ufkes, 2020, 2021 8
Method Overloading
• All well and good, but what about the same number of arguments with different types?
• In Java, compiler sees these as different: public int add(int x, int y)
public double add(double x, double y)
• In Smalltalk, argument types aren’t checked upon message pass.
• Invoking a method (passing a message) only fails when receiving
object can’t handle the message.
• We get a runtime error in the body of the method if the
argument type is incompatible.
© Alex Ufkes, 2020, 2021 9
Method Overloading
However! The following code succeeds!
• Pass + message to SmallInteger 3 with SmallInteger argument 4
• Pass + message to SmallInteger 3 with BoxedFloat64 argument 4.0
• Same message, same receiving class, different kind of argument. How?
© Alex Ufkes, 2020, 2021
10
Invoke superclass addition
© Alex Ufkes, 2020, 2021 11
© Alex Ufkes, 2020, 2021 12
• Check if argument is integer.
• If so, it’s an integer expression
and we can react accordingly
• Check if operands have same sign
• negative returns Boolean
© Alex Ufkes, 2020, 2021 13
© Alex Ufkes, 2020, 2021 14
If arg isFraction, we can still add precisely using numerator and denominator
If arg is neither fraction nor integer, we send it adaptToInteger:andSend: message
© Alex Ufkes, 2020, 2021 15
adaptToInteger:andSend:
• Convert original receiving integer to floating point
• Perform addition between two BoxedFloat64
• It’s now a problem for the Float class implementation of +!
© Alex Ufkes, 2020, 2021
16
Double Dispatch
• Method overloading not possible in Smalltalk.
• Uses the previous technique instead, called double dispatch
• Double/multiple dispatch is not unique to Smalltalk.
Double Dispatch:
• Broadly: Make additional method/function calls based on the types of the objects involved in the original call at runtime.
• I.e., if arg is float, invoke method for floating point addition.
• Overloading is done at compile time, double dispatch occurs
at runtime.
© Alex Ufkes, 2020, 2021 17
Double Dispatch
Overloading is decided at compile time, double dispatch at runtime.
• In Smalltalk (double dispatch), the same method gets invoked regardless of the argument type. Same message regardless!
• Secondary method call(s) occur in the body of the first method, depending on argument type.
• In Java, a different method gets invoked from the very start depending on the type of the argument.
• Decided at compile time (early binding).
Explore this on your own for some of the other types and operators
© Alex Ufkes, 2020, 2021 18
Late VS Early Binding
Dynamic/late binding VS static/early binding
Early binding
• Method to be called is found at compile time
• Method not found = compile error
• More efficient at runtime
Late binding
• Method is looked up at runtime
• Often as simple is searching name
• Symbol comparison in Smalltalk
• Method not found = runtime error
• Costlier at runtime
© Alex Ufkes, 2020, 2021
19
Double dispatch happens at runtime, late binding
This concludes your Smalltalk crash course!
Let’s finish with a high-level summary.
© Alex Ufkes, 2020, 2021 20
Smalltalk Syntax
Extremely minimalist:
• Only five reserved “keywords”: true, false, nil, self, super
• Java has 50, C++ has 82, C has 32
There is an adage – “Smalltalk syntax fits on a postcard”
© Alex Ufkes, 2020, 2021 21
“Smalltalk syntax fits on a postcard”
Method with argument:
Unary messages
Binary messages
Temporary variable
Block
Heterogeneous array
Keyword message
Pass do: message with block argument to array
© Alex Ufkes, 2020, 2021
22
Return result
Smalltalk Extensibility
We are free to modify core Smalltalk classes and methods:
© Alex Ufkes, 2020, 2021 23
Amuse your friends! Confound your enemies!
We are free to modify core Smalltalk classes and methods:
Beware: You WILL cause havoc and be forced to create a new Pharo image.
• The Pharo live environment is using these very methods in a JIT fashion.
• Changing True to False means Pharo itself thinks True is False.
© Alex Ufkes, 2020, 2021 24
Smalltalk Semantics
“A compiler will complain about syntax, your coworkers will complain about semantics”
Always remember:
© Alex Ufkes, 2020, 2021
25
1. 2. 3.
Everything is an object
Computation is done by passing messages to objects. Message precedence: unary, binary, keyword.
• Equal precedence evaluates left to right Everything else follows from these principles.
Smalltalk
• Has garbage collection (like Java)
• Best-in-class IDE (according to fans).
o Class browser, playground, debugger, transcript, etc.
• Just-in-time compilation (JIT)
o Code executed in a live environment
• Image-based development
© Alex Ufkes, 2020, 2021 26
Smalltalk popularity? A dead language?
https://medium.com/smalltalk-talk/who-uses-smalltalk-c6fdaa6319a
JPMorgan Chase:
“Around the time that Java was just being introduced to the world, the banking giant rolled out a new financial risk management and pricing system called Kapital, written entirely in Cincom Smalltalk.”
“JPMorgan estimates that developing and maintaining this system in any other language would’ve required at least three times the amount of resources.”
© Alex Ufkes, 2020, 2021 27
Smalltalk popularity? A dead language?
https://medium.com/smalltalk-talk/smalltalk-and-the-future-of-the- software-industry-3f69cac13e5a
“One of the goals of Smalltalk was to make it very easy to teach programming to children.”
“I believe the best way to teach beginners how to program is with a good teaching language. Languages like Java, Python, JavaScript, C#, C/C++, PHP, Ruby are all industrial languages; they carry a lot of industrial baggage that can get in the way of a beginner.”
© Alex Ufkes, 2020, 2021 28
Smalltalk popularity? A dead language?
https://www.quora.com/Why-did-the-Smalltalk-programming-language- fail-to-become-a-popular-language
“The popular story that’s been around is that Sun killed Smalltalk with Java. That seems to be partly true…”
“I think what prevented Smalltalk from increasing in popularity was the popularity of developing for the internet…”
“The dominant idea in the Smalltalk community in the ’90s was that it was a GUI desktop platform, and that’s where it should stay.”
© Alex Ufkes, 2020, 2021 29
Loved: % of people currently using that want to keep using
© Alex Ufkes, 2020, 2021
30
© Alex Ufkes, 2020, 2021
31
• Smalltalk disappears.
• Not sure why, but I think they
didn’t include it in the survey.
• Rust still on top!
Dreaded: % of people currently using that no longer want to.
© Alex Ufkes, 2020, 2021
32
© Alex Ufkes, 2020, 2021
33
Wanted: % of people not using who want to use
Important!
• •
This refers to what individual developers want to use.
It does not necessarily reflect what the market wants
https://spectrum.ieee.org/at-work/innovation/the-2018-top-programming-languages
© Alex Ufkes, 2020, 2021 34
Leaving OOP Behind
© Alex Ufkes, 2020, 2021
35
“Object-oriented programming is an exceptionally bad idea which could only have originated in California.”
“Object-oriented programs are offered as alternatives to correct ones…”
– Edsger Dijkstra
What OOP users claim:
Leaving OOP Behind
What actually happens:
© Alex Ufkes, 2020, 2021 https://www.reddit.com/r/ProgrammerHumor/comments/418×95/theory_vs_reality/ 36
© Alex Ufkes, 2020, 2021 37
Alternatives to Imperative?
Two widely used paradigms:
Object Oriented Programming:
• “Pure” OO languages treat even primitives and operators as objects
• Java/C++ and others support OOP to greater or lesser degrees.
Functional Programming:
• Avoid changing state, avoid mutable data
• Declarative rather than imperative
• Tell the program where to go, not
how to get there.
© Alex Ufkes, 2020, 2021
38
Functional Programming
© Alex Ufkes, 2020, 2021
39
Declarative VS Imperative
Declarative programming paradigm:
• Style of building and structuring computer programs.
• Functional programming languages are characterized by a declarative style.
• Express the logic of a computation rather than explicit control flow. ?
The order in which individual statements, instructions or function calls of an imperative program are executed or evaluated.
Emphasis on explicit control flow is one thing that separates imperative languages from declarative languages.
© Alex Ufkes, 2020, 2021
40
Control Flow
Determined using control structures in imperative languages.
© Alex Ufkes, 2020, 2021
41
C/CPS 310/590 Example
At the machine instruction level, control flow typically works by altering the program counter.
Program counter tells the OS which instruction to fetch next.
© Alex Ufkes, 2020, 2021
42
Declarative VS Imperative
Imperative languages implement algorithms as a sequence of explicit steps (statements, control flow)
Declarative language syntax describes the logic of an algorithm The declarative paradigm allows developers to worry about
the what, not the how.
The how is left up to the language’s implementation (interpreter/compiler)
© Alex Ufkes, 2020, 2021 43
Always Remember!
© Alex Ufkes, 2020, 2021
44
Machine code is imperative.
Functional programs compile into machine code, just like
imperative ones.
The distinction is in what the programmer is required to think about, and what the language hides behind the scenes.
Declarative VS Imperative
The actual, practical difference between these two paradigms can be very hard to grasp.
How can we program without thinking about control flow?
What makes a language declarative? The fact that it’s not imperative.
© Alex Ufkes, 2020, 2021
45
Faking it in C++
• This C++ code is imperative
• We use a control structure (for loop)
to tell the program to iterate.
• Even specify how this iteration is done. • Initialization,condition,update
© Alex Ufkes, 2020, 2021
46
Faking it in C++
• Simulatedeclarativeprogramming using preprocessor directives.
• Directives here are basically a list of substitutions
• Assume that this is done by the programming language behind the scenes.
© Alex Ufkes, 2020, 2021
47
Faking it in C++
Directives here are basically a list of substitutions
ALoop(5, PrintWord(“declarative”));
© Alex Ufkes, 2020, 2021
48
Faking it in C++
Directives here are basically a list of substitutions
action
cout << word << endl;
ALoop(5, PrintWord("declarative"));
LOOP_5 (action)
LOOP_5 (PrintWord("declarative"))
LOOP_5 (cout << word << endl;)
© Alex Ufkes, 2020, 2021
49
Faking it in C++
Directives here are basically a list of substitutions
action
cout << word << endl;
ALoop(5, PrintWord("declarative"));
LOOP_5 (action)
LOOP_4 (action) action
LOOP_3 (action) action action
LOOP_2 (action) action action action
LOOP_1 (action) action action action action action action action action action
© Alex Ufkes, 2020, 2021 50
Faking it in C++
Imagine this was all done behind the scenes by the implementation of the programming language
© Alex Ufkes, 2020, 2021
51
Declarative VS Imperative
Imperative:
• Programmerspecifies control flow
• Each loop iteration explicitly defined
Declarative (C++ fakery): • Programmersayswhat
they want
• Nevermind how it’s done
for (int i = 0; i < 5; i++)
{
cout << "Imperative" << endl; }
ALoop(5, PrintWord("declarative"));
© Alex Ufkes, 2020, 2021
52
Functional Programming
Depends what you’re doing, depends who you ask...
© Alex Ufkes, 2020, 2021 53
Functional Programming
Functional programming languages are characterized by a declarative style.
© Alex Ufkes, 2020, 2021
54
Functional are not the only declarative languages:
Always Remember!
© Alex Ufkes, 2020, 2021
55
The line between imperative/OOP and functional programming is grey.
Code can be written in a functional style using a language not specifically designed for functional programming.
Some languages are designed to be functional, but still contain imperative elements.
Functional Language Characteristics
Things that are generally foreign to imperative programming:
• Avoids changing global state, no state to reason about.
• Avoid global variables, keep scope as tight/local as possible
© Alex Ufkes, 2020, 2021 56
No side effects!
Side Effects?
Things that are generally foreign to imperative programming:
A function can be said to have a side effect if it has an observable interaction with the outside world aside from returning a value.
© Alex Ufkes, 2020, 2021
57
• Modify global variable
• Raise an exception
• Write data to display or file
Side Effects
Function/method output can depend on history (or current state):
• Call the same function, with the same argument, 5 times.
• Different result each time.
• Common in imperative languages.
• Rare in functional languages.
© Alex Ufkes, 2020, 2021 58
Side Effects
Declarative/functional languages avoid side effects
• The output of a function depends solely on the input arguments o No side effects, no dependence on global or local state.
• This makes it much easier to predict the behavior of a program o Primary motivation for developing functional programming
• With no state to be concerned of, parallel processing becomes much easier. No race conditions!
o Functions can be spawned as separate threads/processes
© Alex Ufkes, 2020, 2021 59
Functional Language Characteristics
Things that are generally foreign to imperative programming:
Pure functions are emphasized/enforced:
© Alex Ufkes, 2020, 2021
60
• •
• •
Pure function? A function without side effects
If the return value of a pure function is not used, the function can be safely removed.
Output depends solely on input (referential transparency). Pure functions without a data dependency can be executed in any order. Safe to parallelize (thread-safe).
Quick Note
© Alex Ufkes, 2020, 2021
61
• In practice it’s unreasonable to have a programming language containing only pure functions.
• This would preclude things like file I/O and user input.
• Common to have a pure function “core” surrounded by
impure functions that interact with the outside world
• This is true of Elixir, but depends on the language.
• Pure functions can be written in any language, but
functional languages enforce them in various ways.
Functional Language Characteristics
Functions and recursion are central:
Flow control accomplished with functions calls.
• We already saw in Smalltalk how this is possible
• Much lower focus on loop/if-else/case constructs.
• Collections are operated upon using recursion.
Specifically, tail recursion in Elixir. Tail recursion is recognized and optimized by the compiler into iterative machine code.
© Alex Ufkes, 2020, 2021
62
Recursion
mult(3, 4)
3+mult(3, 3) 3+(3+mult(3, 2)) 3+(3+(3+mult(3, 1))) 3+(3+(3+(3+mult(3, 0)))) 3+(3+(3+(3+0)))
12
© Alex Ufkes, 2020, 2021
63
Tail Recursion
tail_mult(3, 4, 0) tail_mult(3, 3, 3) tail_mult(3, 2, 6) tail_mult(3, 1, 9) tail_mult(3, 0, 12) 12
© Alex Ufkes, 2020, 2021
64
Tail Recursion
mult(3, 4)
3 + mult(3, 3)
3 + (3 + mult(3, 2))
3 + (3 + (3 + mult(3, 1)))
3 + (3 + (3 + (3 + mult(3, 0)))) 3 + (3 + (3 + (3 + 0)))
12
tail_mult(3, 4, 0)
tail_mult(3, 3, 3)
tail_mult(3, 2, 6)
tail_mult(3, 1, 9)
tail_mult(3, 0, 12)
12
Every recursive call must complete before we even begin adding values
Here, total is updated each call. This version looks a lot more like iteration. Optimizable.
© Alex Ufkes, 2020, 2021
65
Functional Language Characteristics
Things that are generally foreign to imperative programming:
First class functions and higher order functions:
• Functions that return functions or accept them as arguments
o I.e., differential operator. Derivative of function is a function.
• “First class” describes programming language entities that have no restriction on their use.
• I.e., first class functions can appear anywhere in the program that other first-class entities (such as numbers) can.
o Functions as arguments, return values, etc.
© Alex Ufkes, 2020, 2021 66
Always Remember...
The line between imperative and functional programming is grey.
C supports passing functions as arguments via function pointers.
© Alex Ufkes, 2020, 2021
67
Functional Language Characteristics
Things that are generally foreign to imperative programming:
Strict (eager) VS. non-strict (lazy) evaluation:
• •
Strict: Always evaluate function arguments before invoking the function. Lazy: Evaluates arguments if their value is required to invoke the function.
print length( [2+1, 3*2, 1/0, 5-4] );
Fails under strict evaluation, can’t divide by zero.
Under lazy evaluation we get the correct value of 4. We don’t need to know the actual values of the array elements to know how many there are.
• •
© Alex Ufkes, 2020, 2021 68
Functional Programming: Advantages
Easier to reason about pure functions:
• If the function is internally consistent, it’s always correct.
• No tracking down global variables, tracing pointers/references, etc.
© Alex Ufkes, 2020, 2021 69
Functional Programming: Advantages
Concurrent programming is easier:
• No side effects, functions can be spawned as processes/threads.
• There is no state to be shared between different threads.
• No need for semaphores (or similar) if you don’t have side effects!
o Pure functions never access or modify things outside their scope o No such thing as a race condition when values are immutable.
© Alex Ufkes, 2020, 2021 70
Functional Programming: Advantages Programs are easier to understand:
• Allocate space for variable i • Initializeito0
for (int i = 0; i < 5; i++) {
cout << "Imperative" << endl;
}
• •
Iterate as long as i is less than 5 Increment i after each iteration
• Dosomething5times
ALoop(5, PrintWord("declarative"));
© Alex Ufkes, 2020, 2021
71
Functional Programming: Disadvantages Recursion can cause memory use to explode:
• •
Operating on a list with 10000 items requires 10000 recursive calls. Stack explodes
Tail recursion mitigates this as we saw, but using tail recursion can often require inelegant code gymnastics.
© Alex Ufkes, 2020, 2021
72
Functional Programming: Disadvantages
Recursion can cause memory use to explode:
• Operating on a list with 10000 items requires 10000 recursive calls. Stack explodes
• Tail recursion mitigates this as we saw, but using tail recursion can often require inelegant code gymnastics.
No assignment statements, data is immutable:
© Alex Ufkes, 2020, 2021
73
• •
•
Performing actions requires allocating new memory. Remember strings in Java – Changing the value of a string actually creates a new string object with the new value. Garbage collection very important!
Functional Programming: Disadvantages
Performance:
• Functional languages will typically perform worse than imperative languages when:
• Computation is strictly sequential (CPU)
• Computation is uniformly parallel (GPU)
© Alex Ufkes, 2020, 2021
74
© Alex Ufkes, 2020, 2021 75
Only predated by FORTRAN
© Alex Ufkes, 2020, 2021 76
History: Erlang
• Proprietary language used at Ericsson, developed by Joe Armstrong
• Initially implemented in Prolog at Ericsson
• By 1988, it had been proven suitable for
prototyping telephone exchanges but...
• Prolog interpreter was much too slow,
needed to be 40x faster.
• In 1992 work began on BEAM VM
o Compiles Erlang to C
o Balance performance and disk space.
• Went from lab to real applications by 1995
• In 1998, Ericsson banned internal use of
Erlang, causing Armstrong to quit.
o Rehired in 2004, after ban was lifted.
© Alex Ufkes, 2020, 2021
77
History: Elixir
• Builds on Erlang, runs on BEAM VM
• Erlang was prolog-like, Elixir is more
conventional.
• First appeared in 2011
• Developed by Jose Valim as an R&D
project at Plataformatec (consulting firm)
• Used at Pinterest, and for web
development by Discord.
© Alex Ufkes, 2020, 2021
78
Elixir: Overview
• Elixir is a functional programming language
o Mostly immutable, rich support for concurrency
• Everything is an expression.
o Everything evaluates to something.
• Elixir compiles into Erlang bytecode.
o Thus, Erlang functions can be called from Elixir
• Emphasizes recursion and higher-order functions o As opposed to side-effect-based looping
© Alex Ufkes, 2020, 2021
79
Elixir: Processes
© Alex Ufkes, 2020, 2021
80
• •
Elixir code runs inside lightweight threads of execution. o Isolated, exchange information via message passing.
Not uncommon to have hundreds of thousands of processes running concurrently in same VM.
o Note: These are NOT operating system processes! o Extremely lightweight in terms of CPU and memory o A process need not be an expensive resource
Installing Elixir
https://elixir-lang.org/
© Alex Ufkes, 2020, 2021
81
© Alex Ufkes, 2020, 2021 82
© Alex Ufkes, 2020, 2021 83
Erlang Shell
Better than just a terminal window
© Alex Ufkes, 2020, 2021
84
Writing and Compiling Elixir
Play around in the interactive shell, or do things from the command line.
IDEs exist, but you’re on your own. I won’t help troubleshoot IDE-related problems.
This is the Erlang shell. We can:
• Type code into here line by line
• Copy and paste code into here large chunks at a time
• Define modules and functions – though it’s tedious.
© Alex Ufkes, 2020, 2021 85
Elixir References
https://media.pragprog.com/titles/elixir/ElixirCheat.pdf
https://elixir-lang.org/getting-started/introduction.html https://hexdocs.pm/elixir/master/api-reference.html#content
© Alex Ufkes, 2020, 2021 86
Hello World
IO.puts “Hello, World!”
• IO.puts prints to the shell
• When executing in the shell, return values get echoed.
• In this case, IO.puts returns the atom :ok
• Atoms in Elixir are similar in concept to symbols in
Smalltalk.
© Alex Ufkes, 2020, 2021
87
Hello World
IO.puts “Hello, World!”
We will start in this shell for basic concepts. Later, we will see how to run scripts and compile code from the command line (It’s not so bad)
© Alex Ufkes, 2020, 2021
88
Elixir Scripts
© Alex Ufkes, 2020, 2021
89
Elixir Syntax: Basic Types
Typing literals into the shell will echo them back, assuming they are valid.
Decimal, binary, octal, and hexadecimal integers
© Alex Ufkes, 2020, 2021 90
Elixir Syntax: Basic Types
Typing literals into the shell will echo them back, assuming they are valid.
More accurately:
© Alex Ufkes, 2020, 2021
91
• • • •
Everything in Elixir is an expression, even single literals. Evaluating a literal simply results in that value.
In the interactive shell, the return value is printed for us. :ok is the return value of IO.puts. The actual printing to the screen is a side effect!
Elixir Syntax: Basic Types
© Alex Ufkes, 2020, 2021
92
Floating point, Boolean, strings
Floating Point
Floating point numbers in Elixir are 64-bit, double precision
Elixir supports scientific notation
Rounding and truncate functions
© Alex Ufkes, 2020, 2021
93
Floating Point
Floating point numbers in Elixir are 64-bit, double precision
Notice:
• We can omit parentheses around function arguments.
• Multiple arguments are still separated by commas.
© Alex Ufkes, 2020, 2021 94
Boolean
Comparison operator works the way we’re used to
We can check if a value is Boolean using the is_boolean function
© Alex Ufkes, 2020, 2021
95
Types, Values, Truthiness
In Elixir we have Boolean values true and false. Not all languages have a Boolean type.
C does not have a Boolean type. It still supports Boolean expressions, of course. • In C, numeric 0 is considered False, and everything else is considered True.
In Java, we have Boolean. Logical operators are only valid with Boolean operands.
Elixir complicates things by combining both approaches:
• We have Boolean True and False, but values of every other type are considered either true or false.
© Alex Ufkes, 2020, 2021 96
Boolean:
true, false
Boolean Expressions
With these operators:
• non-false and non-nil are true.
• nil and false are false.
• 0 is considered true!
iex> “gh” && false Except…
© Alex Ufkes, 2020, 2021
97
false
iex> “gh” || false
“gh”
• •
The result isn’t true or false It’s the value that decided the result of true or false
&&, ||, !
What we actually get is the value that determined the truthiness of the expression
Test Type
Elixir is dynamically typed!
• Type errors occur at run-time, not at compile time.
• I.e., attempting some operation on incompatible types
results in a run-time error.
• A static type system catches type errors at compile time
© Alex Ufkes, 2020, 2021
98
Basic Arithmetic
Addition, multiplication
Division:
• Notice 5.0, despite integer operands
• / operator returns floating point in Elixir
© Alex Ufkes, 2020, 2021
99
Basic Arithmetic
div and rem functions
div:
• Result of integer division
• Like / in Java rem:
• Remainderoperator
• Same as % in C
• Requiresintegerarguments
© Alex Ufkes, 2020, 2021
100
Precedence?
It’s fairly typical:
https://hexdocs.pm/elixir/master/operators.html
© Alex Ufkes, 2020, 2021 101
div and rem are functions:
• Elixir allows us to drop the brackets
• Even with multiple arguments.
• Can make precedence hard to decipher.
© Alex Ufkes, 2020, 2021
102
Likewise for round and trunc and is_boolean
Summary
© Alex Ufkes, 2020, 2021
103
• Double dispatch
• Smalltalk conclusion
• Functional paradigm
• Getting started with Elixir
© Alex Ufkes, 2020, 2021 104