Last active
August 29, 2015 14:14
-
-
Save skanev/1bcc776d7f8ca4d0371f to your computer and use it in GitHub Desktop.
My "slides" from WCEU 2014
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# encoding: utf-8 | |
def annotate(string, code = '4') | |
string.gsub(/@(.*?)@/, "\e[#{code}m\\1\e[0m") | |
end | |
def colorize(string) | |
string.gsub(/#(.*?)#/, "\e[\\1m").gsub(/##/, "\e[0m") | |
end | |
block colorize(<<-EOS) | |
┌───────────────── Dimension test ─────────────────┐ | |
│ │ | |
│ │ | |
│ │ | |
│ │ | |
│ Color Test │ | |
│ │ | |
│ #90#█████ The quick brown fox jumps over the## │ | |
│ #31#█████ The quick brown fox jumps over the## │ | |
│ #1##31#█████ The quick brown fox jumps over the## │ | |
│ #32#█████ The quick brown fox jumps over the## │ | |
│ #36#█████ The quick brown fox jumps over the## │ | |
│ █████ The quick brown fox jumps over the## │ | |
│ │ | |
│ │ | |
│ │ | |
│ │ | |
└──────────────────────────────────────────────────┘ | |
EOS | |
block colorize <<-EOS.chomp | |
## | |
#1#F U N C T I O N A L P R O G R A M M I N G## | |
What's the fuss all about? | |
Stefan Kanev WordCamp Europe | |
#36#\@skanev 27 September 2014## | |
EOS | |
section 'Audience participation time' do | |
block <<-EOS | |
Who hates audience participation questions? | |
EOS | |
block <<-EOS | |
That's it! | |
EOS | |
end | |
block colorize <<-EOS | |
#1#\$ whoami## | |
\a | |
- programmer | |
\a | |
• currently: Ruby, (Java|Coffee)Script | |
\a• in the past: Java, PHP, Perl, Python | |
\e[0m | |
EOS | |
image 'pics/proglangs.jpg' | |
block colorize <<-EOS | |
#1#\$ whoami## | |
- programmer | |
• currently: Ruby, (Java|Coffee)Script | |
• in the past: Java, PHP, Perl, Python | |
- interests | |
\a• programming languages | |
\a• theoretical things | |
\a• practical things | |
\a- often playing the Devil's advocate | |
\a- @skanev (twitter, github) | |
EOS | |
section 'Functional programming!' do | |
center annotate <<-EOS, 90 | |
LISP | |
@(the grandfather of FP)@ | |
Haskell | |
@(the popular thing)@ | |
Scala | |
@(the… not really sure what)@ | |
JavaScript | |
@(occasionally)@ | |
EOS | |
block annotate <<-EOS, 1 | |
@What@ is functional programming? | |
EOS | |
block colorize <<-EOS | |
Functional programming is a | |
_ _ | |
| | | | | |
| |__ _ _ __________ _____ _ __ __| | | |
| '_ \\| | | |_ /_ /\\ \\ /\\ / / _ \\| '__/ _` | | |
| |_) | |_| |/ / / / \\ V V / (_) | | | (_| | | |
|_.__/ \\__,_/___/___| \\_/\\_/ \\___/|_| \\__,_| | |
#38;5;241#“Now: 50% more functional”## | |
EOS | |
center colorize <<-EOS | |
Don't talk about | |
#1#“functional programming”## | |
Instead, talk about | |
#1#specific language features## | |
EOS | |
center annotate <<-EOS, 1 | |
IMHO when they say "FP" they mean: | |
@Immutable & no side effects@ | |
@Higher-order functions@ | |
@Strong typing@ | |
EOS | |
end | |
def section_title(n) | |
sections = [ | |
'Immutability & no-side effects ', | |
'Higher-order functions', | |
'Strong typing', | |
] | |
sections[n].upcase!.sub!(/\A.*\Z/, "\e[1m\\0\e[0m") | |
sections.join("\n\n") | |
end | |
section section_title(2) do | |
center <<-EOS | |
I'm not into static/strong typing | |
\a | |
You probably aren't either | |
\a | |
But: Devil's advocate! 😈 | |
\a | |
Let's pretend we are | |
EOS | |
block colorize <<-EOS | |
❯ If the only type systems I knew were C, C++, | |
Java, or Go's, I'd be a Ruby programmer too. | |
#90#twitter.com/sunahsuh/status/512666588361658369## | |
EOS | |
center colorize <<-EOS | |
Type systems can be | |
#1#P O W E R F U L## | |
EOS | |
block colorize <<-EOS | |
TYPE SYSTEMS CAN | |
──────────────── | |
• detect a lot of errors at compile time | |
• generate a lot more efficient code | |
• be a useful documentation in some systems | |
EOS | |
end | |
section section_title(0) do | |
block colorize <<-EOS | |
#define immutable | |
───────────────── | |
• Creating copies instead of modifying | |
• No (re-)assignment | |
• Referential transparency | |
#38;5;240#(same fn args → always same result)## | |
EOS | |
block annotate <<-EOS, '38;5;242' | |
copy, don't modify | |
────────────────── | |
@// mutable:@ | |
@// modifies array in place@ | |
sort( $items ); | |
@// immutable:@ | |
@// returns a copy@ | |
array_reverse( $items ); | |
EOS | |
block annotate <<-EOS, '38;5;242' | |
No re-assignment | |
──────────────── | |
@// reassignment:@ | |
$name = getName(); | |
if ( !$name ) { | |
$name = 'N/A'; | |
} | |
@// no reassingment:@ | |
$name = getName() ?: 'N/A'; | |
EOS | |
block annotate <<-EOS, '38;5;242' | |
Referential transparency | |
──────────────────────── | |
@// not referentially transparent:@ | |
$now = date( DATE_RFC2822 ); | |
$id = mysqli_insert_id( $db ); | |
@// referentially transparent:@ | |
$say_it = array_reverse( $alphabet ); | |
@Also called "pure functions"@ | |
EOS | |
center annotate <<-EOS, 1 | |
With those three, the code becomes | |
@D E C L A R A T I V E@ | |
as opposed to | |
@I M P E R A T I V E@ | |
EOS | |
center annotate <<-EOS, 1 | |
We tell the computer | |
@"what we want"@ | |
Instead of telling it | |
@"how to do it"@ | |
EOS | |
center annotate <<-EOS, 1 | |
Consider a metaphor…\a | |
Declarative is like showing | |
@a picture of a dish@\a | |
Imperative is like giving | |
@the recipe@ | |
EOS | |
image 'pics/pancakes.jpg' | |
block <<-EOS | |
PANCAKES | |
──────── | |
1. Sift flour, b. powder, salt and sugar | |
2. Make a well in the center | |
3. Pour in milk, egg and melted butter | |
4. Mix until smooth | |
5. Heat an oiled griddle med. high heat | |
6. Pour the batter for each | |
7. Brown on both sides and serve hot | |
EOS | |
block <<-EOS | |
???? ???????? | |
───────────── | |
1. Preheat oven to 400°F | |
2. Stir together flour, b. powder, salt & sugar | |
3. Make a well in the center | |
4. In a small bowl, beat egg with a fork | |
5. Stir in milk and oil | |
6. Pour all at once into the well | |
7. Mix quickly & lightly with until moistened | |
8. Pour the batter into forms | |
9. Bake for 25 minutes, or until golden | |
EOS | |
image 'pics/muffins.jpg' | |
block <<-EOS | |
You have to pretend | |
you're the computer | |
EOS | |
center <<-EOS | |
Don't be a computer, | |
you're a human ;-) | |
EOS | |
end | |
section section_title(1) do | |
block <<-EOS | |
Higher-order functions | |
────────────────────── | |
Funtions that take other | |
functions as arguments | |
or return functions. | |
EOS | |
center annotate <<-EOS, 1 | |
HOFs allow us to | |
@say more with less@ | |
and give us | |
@better abstractions@. | |
EOS | |
code <<-EOS, :php | |
SORTING | |
─────── | |
// By length of name | |
usort( $items, function( $a, $b ) { | |
return strlen( $a ) - strlen( $b ); | |
} ); | |
usort( $items, function( $a, $b ) { | |
return strcmp( | |
explode( ' ', $a )[1], | |
explode( ' ', $b )[1] | |
); | |
} ); | |
EOS | |
end | |
section 'Code examples' do | |
image 'pics/gauss.jpg' | |
block <<-EOS | |
1 + 2 + 3 + … + 100 = ? | |
EOS | |
end | |
section 'Summing up 1 to 100' do | |
code <<-EOS, :php | |
$sum = 0; | |
for ( $i = 0; $i <= 100; $i++ ) { | |
$sum += $i; | |
} | |
print $sum; | |
EOS | |
code <<-EOS, :php | |
array_sum( range( 0, 100 ) ) | |
EOS | |
center annotate <<-EOS, 1 | |
Second version is obviously better | |
Let's dig into @why@ | |
EOS | |
block annotate <<-EOS, 36 | |
@Declarative, not imperative@ | |
@───────────────────────────@ | |
@HOW@: $sum = 0; | |
for ( $i = 0; $i <= 100; $i++ ) { | |
$sum += $i; | |
} | |
@WHAT@: array_sum( range( 0, 100 ) ); | |
EOS | |
center annotate <<-EOS, 1 | |
Another way to think about it: | |
@E S S E N T I A L@ | |
vs. | |
@A C C I D E N T A L@ | |
complexity | |
EOS | |
block annotate <<-EOS, 36 | |
@Essential vs. accidental@ | |
@────────────────────────@ | |
@ACCIDENTAL@: $sum = 0; | |
for ( $i = 0; $i < 100; $i++ ) { | |
$sum += $i; | |
} | |
@ESSENTIAL@: array_sum( range( 0, 100 ) ); | |
EOS | |
block annotate <<-EOS, 36 | |
@Side effects@ | |
@────────────@ | |
$sum = 0; | |
for ( $i = 0; $i < 100; @$i++@ ) { | |
$sum @+=@ $i; | |
} | |
EOS | |
block 'By the way…' | |
block annotate <<-EOS, 36 | |
The 2 hardest things in computer science | |
──────────────────────────────────────── | |
\a | |
• Cache invalidation | |
\a | |
• Naming things | |
\a | |
• Off-by-one errors | |
EOS | |
block annotate <<-EOS, 36 | |
@Off-by-one risks@ | |
@────────────────@ | |
$sum = 0; | |
for ( $i = 0; $i @<=@ 100; $i++ ) { | |
$sum += $i; | |
} | |
EOS | |
block annotate <<-EOS, 36 | |
@Off-by-one errors@ | |
@─────────────────@ | |
$sum = 0; | |
for ( $i = 0; $i \e[31m<\e[0m 100; @$i++@ ) { | |
$sum @+=@ $i; | |
} | |
EOS | |
end | |
section 'Sending email' do | |
block <<-EOS | |
Problem | |
─────── | |
You need to send a newsletter to | |
all your active users. How do you | |
get their addresses? | |
EOS | |
code <<-EOS, :php | |
$emails = []; | |
foreach ( $users as $user ) { | |
if ( $user->active ) { | |
$emails[] = $user->email; | |
} | |
} | |
EOS | |
block <<-EOS | |
oooo | |
`888 | |
888 .oo. .ooooo. oooo oooo ooo | |
888P"Y88b d88' `88b `88. `88. .8' | |
888 888 888 888 `88..]88..8' | |
888 888 888 888 `888'`888' | |
o888o o888o `Y8bod8P' `8' `8' | |
EOS | |
block <<-EOS | |
oooo . | |
`888 .o8 | |
oooo oooo ooo 888 .oo. .oooo. .o888oo | |
`88. `88. .8' 888P"Y88b `P )88b 888 | |
`88..]88..8' 888 888 .oP"888 888 | |
`888'`888' 888 888 d8( 888 888 . | |
`8' `8' o888o o888o `Y888""8o "888" | |
EOS | |
code <<-EOS, :php | |
$active = array_filter( $users, function( $u ) { | |
return $u->active; | |
} ); | |
$emails = array_map( function( $u ) { | |
return $u->email; | |
}, $active ); | |
EOS | |
code <<-EOS, :php | |
array_map( | |
function( $u ) { | |
return $u->email; | |
}, | |
array_filter( $users, function( $u ) { | |
return $u->active; | |
} ) ); | |
EOS | |
block <<-EOS | |
…but is that better? | |
EOS | |
code <<-EOS, :javascript | |
JavaScript | |
────────── | |
users | |
.filter(function(u) { return u.active }) | |
.map(function(u) { return u.email }); | |
EOS | |
code <<-EOS, :coffee | |
CoffeeScript | |
──────────── | |
users | |
.filter((u) -> u.active) | |
.map((u) -> u.email) | |
EOS | |
code <<-EOS, :php | |
Back to PHP | |
─────────── | |
array_map( | |
function( $u ) { return $u->email; }, | |
array_filter( $users, function( $u ) { | |
return $u->active; | |
} ) ); | |
// Noise and inconsistency | |
// Yet, conceptually simpler | |
// → Very readable | |
EOS | |
center <<-EOS | |
Not convinced yet? | |
Let's talk about readibility… | |
EOS | |
block colorize <<-EOS | |
You know you are working with clean code | |
when each routine you read turns out to | |
be pretty much what you expected. | |
#90#— Ward Cunningham## | |
EOS | |
block <<-EOS | |
Should be self-evident, right?\a | |
As in natural languages?\a | |
Let's run an experiment!\a | |
Two sentences, same meaning: which is more readable?\a | |
Ready? | |
EOS | |
verbatim <<-EOS | |
\e[0m | |
ルビを使って嬉しい開発者になる。 | |
ルビを使って嬉しいソフトウェアを作る人になる。 | |
EOS | |
center annotate <<-EOS, 1 | |
Readibility depends on the reader too! | |
You must know the alphabet to read | |
EOS | |
block colorize <<-EOS | |
LIST COMPREHENSIONS | |
─────────────────── | |
• map + filter is so useful, that it has a name\a | |
• Python has them: | |
[u.email for u in users if u.active]\a | |
• PHP might have the some day: | |
[foreach ($users as $u) | |
if $u->active | |
yield $u->email] | |
#90#markmail.org/thread/uvendztpe2rrwiif## | |
EOS | |
end | |
#section 'Grouping things' do | |
#block <<-EOS | |
#We have an array of people. | |
#Can we group them by arbitrary things? | |
#Like country? | |
#[ | |
#'Bulgaria' => [$ivan, $marin], | |
#'Sweden' => [$sven, $jon, $martin], | |
#… | |
#] | |
#EOS | |
#code <<-EOS, :php | |
#group_by( $people, function( $u ) { | |
#return $u->countryName; | |
#} ) | |
#EOS | |
#code <<-EOS, :php | |
#function group_by( $items, $func ) { | |
#$grouped = []; | |
#foreach ( $items as $item ) { | |
#$key = $func( $item ); | |
#if ( ! isset( $grouped[ $key ] ) ) { | |
#$grouped[ $key ] = []; | |
#} | |
#$grouped[ $key ][] = $item; | |
#} | |
#return $grouped; | |
#} | |
#EOS | |
#center <<-EOS | |
#Did you see anything fishy?\a | |
#There were side-effects!\a | |
#OTOH it was ref. transparent\a | |
#It's philosophical! | |
#EOS | |
#block <<-EOS | |
#If a tree falls in the woods, | |
#does it make a sound? | |
#If a pure function mutates some | |
#local data in order to produce an | |
#immutable return value, is that ok? | |
#EOS | |
#end | |
section 'In conclusion' do | |
block annotate <<-EOS, 1 | |
Say @what@ instead of @how@! | |
EOS | |
block annotate <<-EOS, 1 | |
Readibility is @subjective@! (ルビー) | |
EOS | |
block annotate <<-EOS, 1 | |
It's a @buzzword@! | |
EOS | |
end | |
section 'Thank you' | |
block colorize <<-EOS | |
QUESTIONS? | |
────────── | |
• Say #1#what## instead of #1#how##! | |
• Readibility is #1#subjective##! (ルビー) | |
• It's a #1#buzzword##! | |
#90#\@skanev## | |
EOS |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment