SlideShare ist ein Scribd-Unternehmen logo
1 von 78
Downloaden Sie, um offline zu lesen
Functional Objects
in Ruby
new horizons
Valentyn Ostakh
What is
Functional Object?
at first:
Object with
callable interface
Callable interface
#call
proc_fn = proc { |x| 1 + x }
lambda_fn = lambda { |x| 1 + x }
method_fn = 1.method(:+)
proc_fn.call(2) # => 3
lambda_fn.call(2) # => 3
method_fn.call(2) # => 3
Callable interface
Object + callable interface
class CallablePORO
def call
# TODO
end
def self.call
# TODO
end
end
CallablePORO.call
CallablePORO.new.call
Callable interface in action
Rack provides a minimal interface between webservers
that support Ruby and Ruby frameworks.
To use Rack, provide an object that responds to the call method.
secondly:
Object which
behave like functions
from FP
What is FP?
What is FP?
• programming paradigm

• stateless

• immutability

• evaluation of mathematical functions

• functions everywhere
FP concepts
• Purity

• Immutability

• Higher-order functions

• Closures

• Function Composition
• Point-Free Notation

• Currying

• Common Functional
Functions

• Referential Transparency
Purity
Purity
Pure Functions are very simple functions.
They only operate on their input parameters.
Pure Functions will always produce the same output given the same inputs.
Most useful Pure Functions must take at least one parameter.
All useful Pure Functions must return something.
Pure functions have no side effects.
Purity
z = 10
def sum(x, y)
x + y
end
def just10
10
end
Pure functions
Purity
z = 10
def sum(x, y)
x + y + z
end
def convert(file_name)
input = File.read(file_name)
output = JSON2YML.convert(input)
File.write('output.yml', output)
end
Impure functions
Purity
You don’t just write Pure Functions.
Since programs have to interface to the real world,
some parts of every program must be impure.
The goal is to minimize the amount of impure code
and segregate it from the rest of our program.
Immutability
Immutability
str = 'bite my shiny metal ass'
str.object_id # => 70317488591440
upper_str = str.upcase
upper_str # => "BITE MY SHINY METAL ASS"
upper_str.object_id # => 70317484572200
The simplest examples are the primitive objects:
Symbol, String, Integer, TrueClass(true), FalseClass(false), NilClass(nil) …
Immutability
Value Objects
• Small object that represents a simple entity whose equality is not based on identity
• Value objects have multiple attributes
• Attributes should be immutable throughout its life cycle
• Equality is determined by its attributes (and its type)
Immutability
There are no variables in Functional Programming.
Stored values are still called variables because of history but they are
constants, i.e. once x takes on a value, it’s that value for life.
x = 5
x = x + 1
In math, x can never be equal to x + 1
Higher-Order Functions
Higher-Order Functions
In Functional Programming, a function is a first-class citizen of the language.
In other words, a function is just another value.
Since functions are just values, we can pass them as parameters.
Higher-order Functions either take functions as parameters, return functions or both.
Higher-Order Functions
# returns value
values = [1, 2, 3, 4, 5]
values.map do |value|
value * value
end # => [1, 4, 9, 16, 25]
# returns function
def adder(a, b)
lambda { a + b }
end
adder_fn = adder(1, 2) # => #<Proc: (lambda)>
adder_fn.call # => 3
Closures
Closures
Techniques for implementing lexically scoped name binding
in languages with first-class functions
When a function is created, all of the variables in its scope at the time of
creation are accessible to it for the lifetime of the function.
A function exists as long as there still a reference to it.
A closure is a function’s scope that’s kept alive by a reference to that function.
Closures
outer = 1
def m
inner = 99
yield inner
puts "inner var = #{inner}"
end
m { |inner| outer += inner } # => 99
puts "outer var = #{outer}" # => 100
Functional Composition
Functional Composition
Code reuse sounds great but is difficult to achieve.
Make the code too specific and you can’t reuse it.
Make it too general and it can be too difficult to use in the first place.
So what we need is a balance between the two, a way to make smaller,
reusable pieces that we can use as building blocks
to construct more complex functionality.
Functional Composition
a = lambda { |x| x + 4 }
b = lambda { |y| y / 2 }
a.compose(b).call(4) #=> 6
b.compose(a).call(4) #=> 4
Functional Composition
add10 = -> value { value + 10 }
mult5 = -> value { value * 5 }
compose = -> (fn1, fn2) {
-> value { fn1.(fn2.(value)) }
}
add10mult5 = compose.(mult5, add10)
mult5add10 = compose.(add10, mult5)
add10mult5.(5) # => 75
mult5add10.(5) # => 35
Functional Composition
In math,  f ∘ g is functional composition and is read “f composed with g” or,
more commonly, “f after g”. So (f ∘ g)(x) is equivalent to calling  f after
calling g with x or simply,  f(g(x)).
Point-Free Notation
Point-Free Notation
A style of writing functions without having to specify the parameters.
First, we don’t have to specify redundant parameters. And since we don’t have to
specify them, we don’t have to think up names for all of them.
Second, it’s easier to read and reason about since it’s less verbose. This example is
simple, but imagine a function that took more parameters.
Tacit programming is a programming paradigm in which a function definition
does not include information regarding its arguments, using combinators and
function composition instead of variables
Point-Free Notation
tacit_string = :to_s.to_proc
def increment
self + 1
end
tacit_increment = :increment.to_proc
tacit_string.call(:Bender) # => "Bender"
tacit_increment.call(101) # => 102
Currying
Currying
Function decomposition.
A Curried Function is a function that only takes a single parameter at a time.
A Curried Function is a sequence of functions.
Currying
add = -> x, y { x + y }
native_curry = add.curry
curry_add = -> x { -> y { x + y } }
add.(5, 7) # => 12
native_curry.(5) # => #<Proc: (lambda)>
curry_add.(5) # => #<Proc: (lambda)>
native_curry.(5).(7) # => 12
curry_add.(5).(7) # => 12
Common Functional
Functions
Common Functional
Functions
This function is usually called fold in Functional Languages.
Higher-Order Functions for processing data structures
for building up new values.
Map, Reduce, Select, Find …
Functional Programming uses recursion to do looping.
Common Functional
Functions
values = [{k: :foo, v: 1}, {k: :bar, v: 2}, {k: :foo, v: 2}]
values.select { |value| value[:k] == :foo }
# => [{k: :foo, v: 1}, {k: :foo, v: 2}]
values.find { |value| value[:k] == :foo }
# => [{k: :foo, v: 1}]
values.reduce(0) { |m, value| m += value[:v] }
# => 5
Referential Transparency
Referential Transparency
Referential Transparency is a fancy term to describe
that a pure function can safely be replaced by its expression.
Referential Transparency
x = 3
x + 7 # => 10
3 + 7 # => 10
Not off all FP concepts
are applicable in Ruby
не все концепции из ФП
применимы к ООП

Правильнее будет сказать так, фп
языки построены на данных
концепциях, в этом их особенность,
В ОО языках мы можем лишь
имитировать данные концепции
New horizons
Purity + Object
Functional Object
Functional object abilities
• #call(input)

• no side-effects

• return some output
Callable object
class SurfaceGravity
attr_reader :weight
def initialize(weight)
@weight = weight
end
def call
weight * 9.8
end
end
weight_125 = SurfaceGravity.new(125)
weight_696 = SurfaceGravity.new(696)
weight_125.call # => 1225.0
weight_696.call # => 6820.8
Callable object
class SurfaceGravity
attr_reader :weight
def initialize(weight)
@weight = weight
end
def call
weight * 9.8
end
end
weight_125 = SurfaceGravity.new(125)
weight_696 = SurfaceGravity.new(696)
weight_125.call # => 1225.0
weight_696.call # => 6820.8
Achievements
• #call(input)

• no side-effects

• return some output
Functional object
class SurfaceGravity
def call(weight)
weight * 9.8
end
end
surface_gravity = SurfaceGravity.new
surface_gravity.call(125) # => 1225.0
surface_gravity.call(696) # => 6820.8
Functional object
class SurfaceGravity
def call(weight)
weight * 9.8
end
end
surface_gravity = SurfaceGravity.new
surface_gravity.call(125) # => 1225.0
surface_gravity.call(696) # => 6820.8
Achievements
• #call(input)

• no side-effects

• return some output
Callable Object
class LaunchShuttle
attr_reader :shuttle
def initialize(shuttle)
@shuttle = shuttle
end
def call
CheckFuelSystem.new(shuttle).call
ConfirmLaunchReady.new(shuttle).call
end
end
Callable Object
class LaunchShuttle
attr_reader :shuttle
def initialize(shuttle)
@shuttle = shuttle
end
def call
CheckFuelSystem.new(shuttle).call
ConfirmLaunchReady.new(shuttle).call
end
end
Achievements
• #call(input)

• no side-effects

• return some output
Functional Object
class LaunchShuttle
attr_reader :check_engines, :confirm_launch_ready
def initialize(check_engines:, confirm_launch_ready:)
@check_engines = check_engines
@confirm_launch_ready = confirm_launch_ready
end
def call(shuttle)
check_engines.call(shuttle)
confirm_launch_ready.call(shuttle)
end
end
Functional Object
class LaunchShuttle
attr_reader :check_engines, :confirm_launch_ready
def initialize(check_engines:, confirm_launch_ready:)
@check_engines = check_engines
@confirm_launch_ready = confirm_launch_ready
end
def call(shuttle)
check_engines.call(shuttle)
confirm_launch_ready.call(shuttle)
end
end
Achievements
• #call(input)

• no side-effects

• return some output
Functional Object
class LaunchShuttle
attr_reader :check_engines, :confirm_launch_ready
def initialize(check_engines:, confirm_launch_ready:)
@check_engines = check_engines
@confirm_launch_ready = confirm_launch_ready
end
def call(shuttle)
check_engines.call(shuttle)
confirm_launch_ready.call(shuttle)
end
end
Functional Object
launch_shuttle = LaunchShuttle.new(
check_engines: CheckEngines.new,
confirm_launch_ready: ConfirmLaunchReady.new
)
launch_shuttle.call(shuttle)
Discover Dependency
Injection
Single Responsibility
Open/closed
Liskov substitution
Interface segregation
Dependency inversion
Inversion of Control
container
Flow of control
Functional Object
class LaunchShuttle
attr_reader :check_engines, :confirm_launch_ready
def initialize(check_engines:, confirm_launch_ready:)
@check_engines = check_engines
@confirm_launch_ready = confirm_launch_ready
end
def call(shuttle)
check_engines.call(shuttle)
confirm_launch_ready.call(shuttle)
end
end
Achievements
• #call(input)

• side-effects under control

• return some output
Single Responsibility
Open/closed
Liskov substitution
Interface segregation
Dependency inversion
Single Responsibility
A class should have only one reason to change
Open / closed
Entities should be open for extension,
but closed for modification
Liskov substitution
Subtypes must be substitutable for their base types
Interface segregation
Many client-specific interfaces are better than one general-purpose interface
Dependency inversion
One should depend upon abstractions,
not concretions
Functional objects benefits
• simplicity

• reusability

• composition

• following SOLID

• architecture style
Inspired by
• Functional Architecture for the Practical Rubyist -
RedDotRubyConf 2017: https://www.youtube.com/watch?
time_continue=962&v=7qnsRejCyEQ

• Next Generation Ruby Web Appswith dry-rb, ROM, and Roda -
RedDotRubyConf 2016: https://www.youtube.com/watch?
v=6ecNAjVWqaI

• Full Stack Fest 2015: Blending Functional and OO Programming
in Ruby, by Piotr Solnica: https://www.youtube.com/watch?
v=rMxurF4oqsc

• RubyConf 2017: 4 Programming Paradigms in 45 Minutes by Aja
Hammerly: https://www.youtube.com/watch?v=3TBq__oKUzk
Thank you!
Questions?

Weitere ähnliche Inhalte

Was ist angesagt?

Inline function
Inline functionInline function
Inline function
Tech_MX
 

Was ist angesagt? (20)

DIWE - Advanced PHP Concepts
DIWE - Advanced PHP ConceptsDIWE - Advanced PHP Concepts
DIWE - Advanced PHP Concepts
 
Intro to functional programming
Intro to functional programmingIntro to functional programming
Intro to functional programming
 
Introduction To Functional Programming
Introduction To Functional ProgrammingIntroduction To Functional Programming
Introduction To Functional Programming
 
C++ functions
C++ functionsC++ functions
C++ functions
 
Intro to functional programming
Intro to functional programmingIntro to functional programming
Intro to functional programming
 
Functions in c++
Functions in c++Functions in c++
Functions in c++
 
Practical Functional Programming Presentation by Bogdan Hodorog
Practical Functional Programming Presentation by Bogdan HodorogPractical Functional Programming Presentation by Bogdan Hodorog
Practical Functional Programming Presentation by Bogdan Hodorog
 
Functions in c++
Functions in c++Functions in c++
Functions in c++
 
Functional programming in JavaScript
Functional programming in JavaScriptFunctional programming in JavaScript
Functional programming in JavaScript
 
Scala categorytheory
Scala categorytheoryScala categorytheory
Scala categorytheory
 
Clojure basics
Clojure basicsClojure basics
Clojure basics
 
An Introduction to Functional Programming - DeveloperUG - 20140311
An Introduction to Functional Programming - DeveloperUG - 20140311An Introduction to Functional Programming - DeveloperUG - 20140311
An Introduction to Functional Programming - DeveloperUG - 20140311
 
Inline Functions and Default arguments
Inline Functions and Default argumentsInline Functions and Default arguments
Inline Functions and Default arguments
 
C++ functions
C++ functionsC++ functions
C++ functions
 
Introduction to Functional Programming in JavaScript
Introduction to Functional Programming in JavaScriptIntroduction to Functional Programming in JavaScript
Introduction to Functional Programming in JavaScript
 
16717 functions in C++
16717 functions in C++16717 functions in C++
16717 functions in C++
 
Functional Python Webinar from October 22nd, 2014
Functional Python Webinar from October 22nd, 2014Functional Python Webinar from October 22nd, 2014
Functional Python Webinar from October 22nd, 2014
 
Unit 6 pointers
Unit 6   pointersUnit 6   pointers
Unit 6 pointers
 
Functions in python slide share
Functions in python slide shareFunctions in python slide share
Functions in python slide share
 
Inline function
Inline functionInline function
Inline function
 

Ähnlich wie Functional Objects in Ruby: new horizons – Valentine Ostakh

Notes5
Notes5Notes5
Notes5
hccit
 

Ähnlich wie Functional Objects in Ruby: new horizons – Valentine Ostakh (20)

Functional programming with Ruby - can make you look smart
Functional programming with Ruby - can make you look smartFunctional programming with Ruby - can make you look smart
Functional programming with Ruby - can make you look smart
 
Functions & Closures in Scala
Functions & Closures in ScalaFunctions & Closures in Scala
Functions & Closures in Scala
 
Functions & Closures in Scala
Functions & Closures in ScalaFunctions & Closures in Scala
Functions & Closures in Scala
 
Functions & closures
Functions & closuresFunctions & closures
Functions & closures
 
Notes5
Notes5Notes5
Notes5
 
Functional Programming - Past, Present and Future
Functional Programming - Past, Present and FutureFunctional Programming - Past, Present and Future
Functional Programming - Past, Present and Future
 
Functional Programming Past Present Future
Functional Programming Past Present FutureFunctional Programming Past Present Future
Functional Programming Past Present Future
 
Programming in Scala - Lecture Two
Programming in Scala - Lecture TwoProgramming in Scala - Lecture Two
Programming in Scala - Lecture Two
 
Pythonlearn-04-Functions (1).pptx
Pythonlearn-04-Functions (1).pptxPythonlearn-04-Functions (1).pptx
Pythonlearn-04-Functions (1).pptx
 
Python Learn Function with example programs
Python Learn Function with example programsPython Learn Function with example programs
Python Learn Function with example programs
 
Functional programming with Scala
Functional programming with ScalaFunctional programming with Scala
Functional programming with Scala
 
Functions_21_22.pdf
Functions_21_22.pdfFunctions_21_22.pdf
Functions_21_22.pdf
 
Lecture 08.pptx
Lecture 08.pptxLecture 08.pptx
Lecture 08.pptx
 
04_python_functions.ppt You can define functions to provide the required func...
04_python_functions.ppt You can define functions to provide the required func...04_python_functions.ppt You can define functions to provide the required func...
04_python_functions.ppt You can define functions to provide the required func...
 
Functional programming in ruby
Functional programming in rubyFunctional programming in ruby
Functional programming in ruby
 
Pydiomatic
PydiomaticPydiomatic
Pydiomatic
 
Python idiomatico
Python idiomaticoPython idiomatico
Python idiomatico
 
CS101- Introduction to Computing- Lecture 29
CS101- Introduction to Computing- Lecture 29CS101- Introduction to Computing- Lecture 29
CS101- Introduction to Computing- Lecture 29
 
Functional programming 101
Functional programming 101Functional programming 101
Functional programming 101
 
Functions.pdf
Functions.pdfFunctions.pdf
Functions.pdf
 

Mehr von Ruby Meditation

Mehr von Ruby Meditation (20)

Is this Legacy or Revenant Code? - Sergey Sergyenko | Ruby Meditation 30
Is this Legacy or Revenant Code? - Sergey Sergyenko  | Ruby Meditation 30Is this Legacy or Revenant Code? - Sergey Sergyenko  | Ruby Meditation 30
Is this Legacy or Revenant Code? - Sergey Sergyenko | Ruby Meditation 30
 
Life with GraphQL API: good practices and unresolved issues - Roman Dubrovsky...
Life with GraphQL API: good practices and unresolved issues - Roman Dubrovsky...Life with GraphQL API: good practices and unresolved issues - Roman Dubrovsky...
Life with GraphQL API: good practices and unresolved issues - Roman Dubrovsky...
 
Where is your license, dude? - Viacheslav Miroshnychenko | Ruby Meditation 29
Where is your license, dude? - Viacheslav Miroshnychenko | Ruby Meditation 29Where is your license, dude? - Viacheslav Miroshnychenko | Ruby Meditation 29
Where is your license, dude? - Viacheslav Miroshnychenko | Ruby Meditation 29
 
Dry-validation update. Dry-validation vs Dry-schema 1.0 - Aleksandra Stolyar ...
Dry-validation update. Dry-validation vs Dry-schema 1.0 - Aleksandra Stolyar ...Dry-validation update. Dry-validation vs Dry-schema 1.0 - Aleksandra Stolyar ...
Dry-validation update. Dry-validation vs Dry-schema 1.0 - Aleksandra Stolyar ...
 
How to cook Rabbit on Production - Bohdan Parshentsev | Ruby Meditation 28
How to cook Rabbit on Production - Bohdan Parshentsev | Ruby Meditation 28 How to cook Rabbit on Production - Bohdan Parshentsev | Ruby Meditation 28
How to cook Rabbit on Production - Bohdan Parshentsev | Ruby Meditation 28
 
How to cook Rabbit on Production - Serhiy Nazarov | Ruby Meditation 28
How to cook Rabbit on Production - Serhiy Nazarov | Ruby Meditation 28How to cook Rabbit on Production - Serhiy Nazarov | Ruby Meditation 28
How to cook Rabbit on Production - Serhiy Nazarov | Ruby Meditation 28
 
Reinventing the wheel - why do it and how to feel good about it - Julik Tarkh...
Reinventing the wheel - why do it and how to feel good about it - Julik Tarkh...Reinventing the wheel - why do it and how to feel good about it - Julik Tarkh...
Reinventing the wheel - why do it and how to feel good about it - Julik Tarkh...
 
Performance Optimization 101 for Ruby developers - Nihad Abbasov (ENG) | Ruby...
Performance Optimization 101 for Ruby developers - Nihad Abbasov (ENG) | Ruby...Performance Optimization 101 for Ruby developers - Nihad Abbasov (ENG) | Ruby...
Performance Optimization 101 for Ruby developers - Nihad Abbasov (ENG) | Ruby...
 
Use cases for Serverless Technologies - Ruslan Tolstov (RUS) | Ruby Meditatio...
Use cases for Serverless Technologies - Ruslan Tolstov (RUS) | Ruby Meditatio...Use cases for Serverless Technologies - Ruslan Tolstov (RUS) | Ruby Meditatio...
Use cases for Serverless Technologies - Ruslan Tolstov (RUS) | Ruby Meditatio...
 
The Trailblazer Ride from the If Jungle into a Civilised Railway Station - Or...
The Trailblazer Ride from the If Jungle into a Civilised Railway Station - Or...The Trailblazer Ride from the If Jungle into a Civilised Railway Station - Or...
The Trailblazer Ride from the If Jungle into a Civilised Railway Station - Or...
 
What/How to do with GraphQL? - Valentyn Ostakh (ENG) | Ruby Meditation 27
What/How to do with GraphQL? - Valentyn Ostakh (ENG) | Ruby Meditation 27What/How to do with GraphQL? - Valentyn Ostakh (ENG) | Ruby Meditation 27
What/How to do with GraphQL? - Valentyn Ostakh (ENG) | Ruby Meditation 27
 
New features in Rails 6 - Nihad Abbasov (RUS) | Ruby Meditation 26
New features in Rails 6 -  Nihad Abbasov (RUS) | Ruby Meditation 26New features in Rails 6 -  Nihad Abbasov (RUS) | Ruby Meditation 26
New features in Rails 6 - Nihad Abbasov (RUS) | Ruby Meditation 26
 
Security Scanning Overview - Tetiana Chupryna (RUS) | Ruby Meditation 26
Security Scanning Overview - Tetiana Chupryna (RUS) | Ruby Meditation 26Security Scanning Overview - Tetiana Chupryna (RUS) | Ruby Meditation 26
Security Scanning Overview - Tetiana Chupryna (RUS) | Ruby Meditation 26
 
Teach your application eloquence. Logs, metrics, traces - Dmytro Shapovalov (...
Teach your application eloquence. Logs, metrics, traces - Dmytro Shapovalov (...Teach your application eloquence. Logs, metrics, traces - Dmytro Shapovalov (...
Teach your application eloquence. Logs, metrics, traces - Dmytro Shapovalov (...
 
Best practices. Exploring - Ike Kurghinyan (RUS) | Ruby Meditation 26
Best practices. Exploring - Ike Kurghinyan (RUS) | Ruby Meditation 26Best practices. Exploring - Ike Kurghinyan (RUS) | Ruby Meditation 26
Best practices. Exploring - Ike Kurghinyan (RUS) | Ruby Meditation 26
 
Road to A/B testing - Alexey Vasiliev (ENG) | Ruby Meditation 25
Road to A/B testing - Alexey Vasiliev (ENG) | Ruby Meditation 25Road to A/B testing - Alexey Vasiliev (ENG) | Ruby Meditation 25
Road to A/B testing - Alexey Vasiliev (ENG) | Ruby Meditation 25
 
Concurrency in production. Real life example - Dmytro Herasymuk | Ruby Medita...
Concurrency in production. Real life example - Dmytro Herasymuk | Ruby Medita...Concurrency in production. Real life example - Dmytro Herasymuk | Ruby Medita...
Concurrency in production. Real life example - Dmytro Herasymuk | Ruby Medita...
 
Data encryption for Ruby web applications - Dmytro Shapovalov (RUS) | Ruby Me...
Data encryption for Ruby web applications - Dmytro Shapovalov (RUS) | Ruby Me...Data encryption for Ruby web applications - Dmytro Shapovalov (RUS) | Ruby Me...
Data encryption for Ruby web applications - Dmytro Shapovalov (RUS) | Ruby Me...
 
Rails App performance at the limit - Bogdan Gusiev
Rails App performance at the limit - Bogdan GusievRails App performance at the limit - Bogdan Gusiev
Rails App performance at the limit - Bogdan Gusiev
 
GDPR. Next Y2K in 2018? - Anton Tkachov | Ruby Meditation #23
GDPR. Next Y2K in 2018? - Anton Tkachov | Ruby Meditation #23GDPR. Next Y2K in 2018? - Anton Tkachov | Ruby Meditation #23
GDPR. Next Y2K in 2018? - Anton Tkachov | Ruby Meditation #23
 

Kürzlich hochgeladen

EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
Earley Information Science
 

Kürzlich hochgeladen (20)

Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024Axa Assurance Maroc - Insurer Innovation Award 2024
Axa Assurance Maroc - Insurer Innovation Award 2024
 
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdfThe Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
The Role of Taxonomy and Ontology in Semantic Layers - Heather Hedden.pdf
 
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
Strategies for Unlocking Knowledge Management in Microsoft 365 in the Copilot...
 
Real Time Object Detection Using Open CV
Real Time Object Detection Using Open CVReal Time Object Detection Using Open CV
Real Time Object Detection Using Open CV
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonets
 
A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?
 
The Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptxThe Codex of Business Writing Software for Real-World Solutions 2.pptx
The Codex of Business Writing Software for Real-World Solutions 2.pptx
 
A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024
 
Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024Finology Group – Insurtech Innovation Award 2024
Finology Group – Insurtech Innovation Award 2024
 
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptxEIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
EIS-Webinar-Prompt-Knowledge-Eng-2024-04-08.pptx
 
Scaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organizationScaling API-first – The story of a global engineering organization
Scaling API-first – The story of a global engineering organization
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processors
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf
 
Advantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your BusinessAdvantages of Hiring UIUX Design Service Providers for Your Business
Advantages of Hiring UIUX Design Service Providers for Your Business
 
Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024Tata AIG General Insurance Company - Insurer Innovation Award 2024
Tata AIG General Insurance Company - Insurer Innovation Award 2024
 
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time AutomationFrom Event to Action: Accelerate Your Decision Making with Real-Time Automation
From Event to Action: Accelerate Your Decision Making with Real-Time Automation
 
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
 

Functional Objects in Ruby: new horizons – Valentine Ostakh

  • 1. Functional Objects in Ruby new horizons Valentyn Ostakh
  • 5. proc_fn = proc { |x| 1 + x } lambda_fn = lambda { |x| 1 + x } method_fn = 1.method(:+) proc_fn.call(2) # => 3 lambda_fn.call(2) # => 3 method_fn.call(2) # => 3 Callable interface
  • 6. Object + callable interface class CallablePORO def call # TODO end def self.call # TODO end end CallablePORO.call CallablePORO.new.call
  • 7. Callable interface in action Rack provides a minimal interface between webservers that support Ruby and Ruby frameworks. To use Rack, provide an object that responds to the call method.
  • 10. What is FP? • programming paradigm • stateless • immutability • evaluation of mathematical functions • functions everywhere
  • 11. FP concepts • Purity • Immutability • Higher-order functions • Closures • Function Composition • Point-Free Notation • Currying • Common Functional Functions • Referential Transparency
  • 13. Purity Pure Functions are very simple functions. They only operate on their input parameters. Pure Functions will always produce the same output given the same inputs. Most useful Pure Functions must take at least one parameter. All useful Pure Functions must return something. Pure functions have no side effects.
  • 14. Purity z = 10 def sum(x, y) x + y end def just10 10 end Pure functions
  • 15. Purity z = 10 def sum(x, y) x + y + z end def convert(file_name) input = File.read(file_name) output = JSON2YML.convert(input) File.write('output.yml', output) end Impure functions
  • 16. Purity You don’t just write Pure Functions. Since programs have to interface to the real world, some parts of every program must be impure. The goal is to minimize the amount of impure code and segregate it from the rest of our program.
  • 18. Immutability str = 'bite my shiny metal ass' str.object_id # => 70317488591440 upper_str = str.upcase upper_str # => "BITE MY SHINY METAL ASS" upper_str.object_id # => 70317484572200 The simplest examples are the primitive objects: Symbol, String, Integer, TrueClass(true), FalseClass(false), NilClass(nil) …
  • 19. Immutability Value Objects • Small object that represents a simple entity whose equality is not based on identity • Value objects have multiple attributes • Attributes should be immutable throughout its life cycle • Equality is determined by its attributes (and its type)
  • 20. Immutability There are no variables in Functional Programming. Stored values are still called variables because of history but they are constants, i.e. once x takes on a value, it’s that value for life. x = 5 x = x + 1 In math, x can never be equal to x + 1
  • 22. Higher-Order Functions In Functional Programming, a function is a first-class citizen of the language. In other words, a function is just another value. Since functions are just values, we can pass them as parameters. Higher-order Functions either take functions as parameters, return functions or both.
  • 23. Higher-Order Functions # returns value values = [1, 2, 3, 4, 5] values.map do |value| value * value end # => [1, 4, 9, 16, 25] # returns function def adder(a, b) lambda { a + b } end adder_fn = adder(1, 2) # => #<Proc: (lambda)> adder_fn.call # => 3
  • 25. Closures Techniques for implementing lexically scoped name binding in languages with first-class functions When a function is created, all of the variables in its scope at the time of creation are accessible to it for the lifetime of the function. A function exists as long as there still a reference to it. A closure is a function’s scope that’s kept alive by a reference to that function.
  • 26. Closures outer = 1 def m inner = 99 yield inner puts "inner var = #{inner}" end m { |inner| outer += inner } # => 99 puts "outer var = #{outer}" # => 100
  • 28. Functional Composition Code reuse sounds great but is difficult to achieve. Make the code too specific and you can’t reuse it. Make it too general and it can be too difficult to use in the first place. So what we need is a balance between the two, a way to make smaller, reusable pieces that we can use as building blocks to construct more complex functionality.
  • 29. Functional Composition a = lambda { |x| x + 4 } b = lambda { |y| y / 2 } a.compose(b).call(4) #=> 6 b.compose(a).call(4) #=> 4
  • 30. Functional Composition add10 = -> value { value + 10 } mult5 = -> value { value * 5 } compose = -> (fn1, fn2) { -> value { fn1.(fn2.(value)) } } add10mult5 = compose.(mult5, add10) mult5add10 = compose.(add10, mult5) add10mult5.(5) # => 75 mult5add10.(5) # => 35
  • 31. Functional Composition In math,  f ∘ g is functional composition and is read “f composed with g” or, more commonly, “f after g”. So (f ∘ g)(x) is equivalent to calling  f after calling g with x or simply,  f(g(x)).
  • 33. Point-Free Notation A style of writing functions without having to specify the parameters. First, we don’t have to specify redundant parameters. And since we don’t have to specify them, we don’t have to think up names for all of them. Second, it’s easier to read and reason about since it’s less verbose. This example is simple, but imagine a function that took more parameters. Tacit programming is a programming paradigm in which a function definition does not include information regarding its arguments, using combinators and function composition instead of variables
  • 34. Point-Free Notation tacit_string = :to_s.to_proc def increment self + 1 end tacit_increment = :increment.to_proc tacit_string.call(:Bender) # => "Bender" tacit_increment.call(101) # => 102
  • 36. Currying Function decomposition. A Curried Function is a function that only takes a single parameter at a time. A Curried Function is a sequence of functions.
  • 37. Currying add = -> x, y { x + y } native_curry = add.curry curry_add = -> x { -> y { x + y } } add.(5, 7) # => 12 native_curry.(5) # => #<Proc: (lambda)> curry_add.(5) # => #<Proc: (lambda)> native_curry.(5).(7) # => 12 curry_add.(5).(7) # => 12
  • 39. Common Functional Functions This function is usually called fold in Functional Languages. Higher-Order Functions for processing data structures for building up new values. Map, Reduce, Select, Find … Functional Programming uses recursion to do looping.
  • 40. Common Functional Functions values = [{k: :foo, v: 1}, {k: :bar, v: 2}, {k: :foo, v: 2}] values.select { |value| value[:k] == :foo } # => [{k: :foo, v: 1}, {k: :foo, v: 2}] values.find { |value| value[:k] == :foo } # => [{k: :foo, v: 1}] values.reduce(0) { |m, value| m += value[:v] } # => 5
  • 42. Referential Transparency Referential Transparency is a fancy term to describe that a pure function can safely be replaced by its expression.
  • 43. Referential Transparency x = 3 x + 7 # => 10 3 + 7 # => 10
  • 44. Not off all FP concepts are applicable in Ruby не все концепции из ФП применимы к ООП Правильнее будет сказать так, фп языки построены на данных концепциях, в этом их особенность, В ОО языках мы можем лишь имитировать данные концепции
  • 48. Functional object abilities • #call(input) • no side-effects • return some output
  • 49. Callable object class SurfaceGravity attr_reader :weight def initialize(weight) @weight = weight end def call weight * 9.8 end end weight_125 = SurfaceGravity.new(125) weight_696 = SurfaceGravity.new(696) weight_125.call # => 1225.0 weight_696.call # => 6820.8
  • 50. Callable object class SurfaceGravity attr_reader :weight def initialize(weight) @weight = weight end def call weight * 9.8 end end weight_125 = SurfaceGravity.new(125) weight_696 = SurfaceGravity.new(696) weight_125.call # => 1225.0 weight_696.call # => 6820.8
  • 51. Achievements • #call(input) • no side-effects • return some output
  • 52. Functional object class SurfaceGravity def call(weight) weight * 9.8 end end surface_gravity = SurfaceGravity.new surface_gravity.call(125) # => 1225.0 surface_gravity.call(696) # => 6820.8
  • 53. Functional object class SurfaceGravity def call(weight) weight * 9.8 end end surface_gravity = SurfaceGravity.new surface_gravity.call(125) # => 1225.0 surface_gravity.call(696) # => 6820.8
  • 54. Achievements • #call(input) • no side-effects • return some output
  • 55. Callable Object class LaunchShuttle attr_reader :shuttle def initialize(shuttle) @shuttle = shuttle end def call CheckFuelSystem.new(shuttle).call ConfirmLaunchReady.new(shuttle).call end end
  • 56. Callable Object class LaunchShuttle attr_reader :shuttle def initialize(shuttle) @shuttle = shuttle end def call CheckFuelSystem.new(shuttle).call ConfirmLaunchReady.new(shuttle).call end end
  • 57. Achievements • #call(input) • no side-effects • return some output
  • 58. Functional Object class LaunchShuttle attr_reader :check_engines, :confirm_launch_ready def initialize(check_engines:, confirm_launch_ready:) @check_engines = check_engines @confirm_launch_ready = confirm_launch_ready end def call(shuttle) check_engines.call(shuttle) confirm_launch_ready.call(shuttle) end end
  • 59. Functional Object class LaunchShuttle attr_reader :check_engines, :confirm_launch_ready def initialize(check_engines:, confirm_launch_ready:) @check_engines = check_engines @confirm_launch_ready = confirm_launch_ready end def call(shuttle) check_engines.call(shuttle) confirm_launch_ready.call(shuttle) end end
  • 60. Achievements • #call(input) • no side-effects • return some output
  • 61. Functional Object class LaunchShuttle attr_reader :check_engines, :confirm_launch_ready def initialize(check_engines:, confirm_launch_ready:) @check_engines = check_engines @confirm_launch_ready = confirm_launch_ready end def call(shuttle) check_engines.call(shuttle) confirm_launch_ready.call(shuttle) end end
  • 62. Functional Object launch_shuttle = LaunchShuttle.new( check_engines: CheckEngines.new, confirm_launch_ready: ConfirmLaunchReady.new ) launch_shuttle.call(shuttle)
  • 67. Functional Object class LaunchShuttle attr_reader :check_engines, :confirm_launch_ready def initialize(check_engines:, confirm_launch_ready:) @check_engines = check_engines @confirm_launch_ready = confirm_launch_ready end def call(shuttle) check_engines.call(shuttle) confirm_launch_ready.call(shuttle) end end
  • 68. Achievements • #call(input) • side-effects under control • return some output
  • 70. Single Responsibility A class should have only one reason to change
  • 71. Open / closed Entities should be open for extension, but closed for modification
  • 72. Liskov substitution Subtypes must be substitutable for their base types
  • 73. Interface segregation Many client-specific interfaces are better than one general-purpose interface
  • 74. Dependency inversion One should depend upon abstractions, not concretions
  • 75. Functional objects benefits • simplicity • reusability • composition • following SOLID • architecture style
  • 76. Inspired by • Functional Architecture for the Practical Rubyist - RedDotRubyConf 2017: https://www.youtube.com/watch? time_continue=962&v=7qnsRejCyEQ • Next Generation Ruby Web Appswith dry-rb, ROM, and Roda - RedDotRubyConf 2016: https://www.youtube.com/watch? v=6ecNAjVWqaI • Full Stack Fest 2015: Blending Functional and OO Programming in Ruby, by Piotr Solnica: https://www.youtube.com/watch? v=rMxurF4oqsc • RubyConf 2017: 4 Programming Paradigms in 45 Minutes by Aja Hammerly: https://www.youtube.com/watch?v=3TBq__oKUzk