Functional Javascript
snowmantw@gmail.com
2012/5/24 JS Group
http://goo.gl/5WCjI
snowmantw
: Vimer
/ Linux User
λ Haskell learner
G self-studier
JS developer
MS student -> Dept. of Computer Science, NCCU
C C++ PHP JS Haskell Java
Functional Javascript
What ?
JavaScript's C-like syntax, including curly braces
and the clunky for statement, makes it appear
to be an ordinary procedural language. This is
misleading because JavaScript has more in
common with functional languages like Lisp or
Scheme than with C or Java. It has arrays
instead of lists and objects instead of property
lists. Functions are first class. It has closures.
You get lambdas without having to balance all
those parens.
“JavaScript: The World's Most Misunderstood Programming Language”
by Douglas Crockford
JavaScript's C-like syntax, including curly braces
and the clunky for statement, makes it appear
to be an ordinary procedural language. This is
misleading because JavaScript has more in
common with functional languages like Lisp or
Scheme than with C or Java. It has arrays
instead of lists and objects instead of property
lists. Functions are first class. It has closures.
You get lambdas without having to balance all
those parens.
“JavaScript: The World's Most Misunderstood Programming Language”
by Douglas Crockford
So, Javascript is a
Functional
Programming
Language
function id( a )
{
return a;
}
function curried( a )
{
return function ( b ) {
return a + b;
}
}
First-Class Function
Curry
function compose( gn )
{
return function ( fn ) {
return function( a ) {
return gn( fn ( a ) ) ;
}
}
} High-Order Function
curried( a )
curried( a ) ( b )
curried( a ) ( c )
curried( b ) ( c )
curried( a ) :: a function
curried( b ) :: another fn
Curry can make a
new function
without definition
curried( a )
curried( a ) ( b )
curried( a ) ( c )
curried( b ) ( c )
curried( a )
curried( a ) ( b )
curried( a ) ( c )
curried( b ) ( c )
new_fn1 = curried( 1 )
new_fn2 = curried( 2 )
new_fn1 ( 1 ) == 1 + 1
new_fn2 ( 1 ) == 2 + 1
We “defined” two functions
without definition !
curried( a )
curried( a ) ( b )
High-Order Function
take one or more fn as an input
OR output a function ( like Curry )
curried( a )
curried( a ) ( b )
compose( curried( a ) )
compose( curried( a ) ) ( curried( b ) )
compose( curried( a ) ) ( curried( b ) ) ( a )
Yet another high-order function
A normal function
A value
curried( a )
curried( a ) ( b )
compose( curried( 3 ) ) ( curried( 4 ) )
compose( curried( 3 ) ) ( curried( 4 ) ) ( 5 )
Generate value when all conditions are satisfied
Now We Have…
First-Class
Function
Now We Have…
That’s all; It’s so sad
Now We Have…
High-Order
Function
- Pure Function
- Immutable Variable
- Encapsulated Impure Features
- ( More ) High Order Function
- Lazy Evaluation
- Functional Data Structure
- Type System
Javascript lacks
Why they
matter ?
Immutable Variable
mut = 1 ;
function victim( ) {
return 10 / mut ;
}
$.get ( ‘/change/mut’ , function(data) {
mut = 0;
});
Immutable Variable
function bad_fn ( arr )
{
var mut = 0;
for( ; mut != arr.length ; mut ++ )
{
arr[ mut ] += mut;
}
return mut;
}
Pure Function
Side-Effect Free
Impure Function
OOPs… It may cause serious problems
gn(3) = 3
gn(3) = 3
gn(3) = 3
gn(3) = 3
gn(3) = 3
gn(3) = 4
Impure Function
i_m_an_innocent_fn
:: ( ) -> Int
function i_m_an_innocent_fn()
{
launch_nuclear_missles();
return 3;
}
Need to be Encapsulated
Pure X Impure
var innocent_var =
3 * 4 + pow ( 2, 4 ) -
i_m_an_innocent_fn() +
floor ( 10 * varA ) …
… It’s just a numerical expression
( I lied )
We ( the laugnage ! )
shouldn’t allow pure
functions to mix with
impure functions.
A Real World Case ( 2 x 4 hr )
render : function(nst) {
var t = this, s = t.settings, id = t.id, sl = tinymce.ScriptLoader;
// Page is not loaded yet, wait for it
// DEBUG : No, we don't need 'tinymce style' check here......
// Because we use bigpipe tech, this condition statement
// will always keep failed.
//
// snowmantw @ 2012-04-25 18:00:41+08:00
//
// if (!Event.domLoaded) {
// Event.add(window, 'ready', function() {
// t.render();
// });
// return;
// }
Encapsulated Impure
Features
Pure Functions need to be ‘wrapped’
Encapsulated Impure
Features
Encapsulated Impure
Features
This is why type system matters
Encapsulated Impure
Features
‘return’ can “lift” one pure fn‘s result
Encapsulated Impure
Features
make pure ‘digitToInt’ impure
Encapsulated Impure
Features
It is the Monad version ‘。’
。
Encapsulated Impure
Features
Encapsulated Impure
Features
(>>=) ‘bind’ can glue another Action
( functions return Monadic value)
No pure function can
get and use values
from Monad,
unless we wrap it and
make it impure, too.
Monad also make “Statements”
in functional way
main =
printStrLn “This is a interactive program !” >>
printStrLn “----” >>
printStrLn “Input Something: ” >>
readline >>= maybe_str -> case maybe_str of
Nothing -> return ()
Just line -> printStrLn “Input from user: ” >>
printStrLn line
Monad also make “Statements”
in functional way
function main( ) {
console.log( “ This is a interactive program ! ” ) ;
console.log( “ ---- “ ) ;
var input = readline( ) ;
if ( “” == input ) { return ; }
console.log( “Input from user: ” ) ;
console.log( input ) ;
}
Why Bother ?
We can assume that
there are no impure
functions leaking to
the pure world
And pure functions
still can be reusable
components
in our program
Just need to be wrapped first
It’s important because…
In most cases we
just need
Modular Programming,
not Object-Oriented
Programming
And the concepts of
pureness and
composition
just fit the need
Welcome to The World of Composition
Function composition ( pure ) ‘。’
: make larger and pure function
Monad bind ( impure ) ‘ >>=’
: make useful and larger COMPUTATION
Arrow compose ( purer than Monad ) ‘>>>’
: make useful and larger COMPUTATION
You can build your whole program with composition
BTW: Composite "Pattern" is Nothing
fa a = b ; fb b = c ; fc = fb . fa
class functorA {
<Tb> public Tb exec( Ta a ) {
return Tb b;
} }
class functorB{
<Tc> public Tc exec( Tb b ) {
return Tc c;
} }
BTW: Composite "Pattern" is Nothing
fa a = b ; fb b = c ; fc = fb . fa
class FunctorCompose
{ public Functor compose( fa, fb )
{
//.......
}
}
// Use in some method
(new FunctorCompose()).compose(fa ,fb)
Sounds good, but…
“It’s not Javascript !”
The Problem:
How can we program
more functionally in the
Javascript world ?
Concepts
id; map; foldl; getChar; putStrLn; (+) ....
map (+1) ; getChar >>= putChar ; f . g
prog = map putStrLn >> getChar >>=
return . digitToInt >>=
x-> return (!!) x str_xs >>=
putStrLn
Libraries
Keep your functions pure ( Dot )
function fn( x ){
return x;
}
$IO.impure = function( x ){
return x + read_from_server ( );
}
All we can use is the '$' and '_'
Impure functions should be restricted in some contexts
Underscore.js ( Line )
_.reduce ( [ 1,2,3 ], function(m,n){ return m+n; },0)
`map` and other high order functions
_.map ( [ 1,2,3 ], function(n){ return n+1; } )
http://underscorejs.org/
Functional Javascript ( Line )
' x -> y -> x+y '.lambda()(2);
More functional features than Underscore.js
' y x -> x+2*y '.lambda()(2, 3);
http://osteele.com/sources/javascript/functional/
jQuery ( Plane )
var pure_val =
$( DOM ) . manipulateDOM ( )
. pureCB ( function ( ) { ... } )
. it_has_unwrapper_fns () ;
"jQuery is Monad“: http://goo.gl/cFErM
http://importantshock.wordpress.com/2009/01/18/jquery-is-a-monad/
http://jquery.com//
It's ( almost ) a " DOM Monad "
Javascript Arrowlet ( Plane )
http://www.cs.umd.edu/projects/PL/arrowlets/api-arrowlets.xhtml
Redefine the "Process"
Javascript Arrowlet ( Plane )
targetA
.next(EventA("click"))
.next(start2)
.next(EventA("click"))
.next(cancel2)
.next(Repeat).repeat().run();
http://www.cs.umd.edu/projects/PL/arrowlets/api-arrowlets.xhtml
Fully event-driven programming
Redefine the "Process"
Flapjax ( Plane )
<p>
The time is {! timerB(100) !}.
</p>
Functional Reactive Programming
Need supported compilers
http://www.flapjax-lang.org/
Languages
CoffeeScript ( Language )
function curried ( a ) {
return function ( b ){
return a + b;
} }
f a b = a + b
f = a->b-> a + b
Why syntax matters
a >>=
b >>=
c >>=
d >>=
e
a >>=
( b >>=
c >>=
d >>=
e )
a >>=
( b >>=
( c >>=
d >>=
e ))
a >>=
( b >>=
( c >>=
( d >>=
e )))
Why syntax matters
a >>=
b >>=
c >>=
d >>=
e ......
a >>=
( b >>=
( c >>=
( d >>=
e ...... ))))))))))))))))))))
Parenthesis Hell
Why syntax matters
First-Class Function + Monad
$( R.id.ButtonToClick ). click ( function(event){
$( R.id.TextViewToShow ).text(
( new SimpleDataFormat( “h:mm:ss a” ) ).format( new Date() ) ;
);
} );
But CoffeeScript is just a little language…
- Pure Function
- Immutable Variable
- Encapsulated Impure Features
- ( More ) High Order Function
- Lazy Evaluation
- Functional Data Structure
- Type System
Personal Project: FunTang language
https://github.com/snowmantw/FunTang
Personal Project: FunTang language
CoffeeScript
Functional Features
+
Personal Project: FunTang language
Will focus on
- Compile into CoffeeScript
- Immutable Variable
- Pure Function
- Integrated Arrow
- Fully Event-Driven Process
In early stage
Thanks for
Your Attention

Things about Functional JavaScript

  • 1.
  • 2.
  • 3.
    snowmantw : Vimer / LinuxUser λ Haskell learner G self-studier JS developer MS student -> Dept. of Computer Science, NCCU C C++ PHP JS Haskell Java
  • 4.
  • 5.
  • 6.
    JavaScript's C-like syntax,including curly braces and the clunky for statement, makes it appear to be an ordinary procedural language. This is misleading because JavaScript has more in common with functional languages like Lisp or Scheme than with C or Java. It has arrays instead of lists and objects instead of property lists. Functions are first class. It has closures. You get lambdas without having to balance all those parens. “JavaScript: The World's Most Misunderstood Programming Language” by Douglas Crockford
  • 7.
    JavaScript's C-like syntax,including curly braces and the clunky for statement, makes it appear to be an ordinary procedural language. This is misleading because JavaScript has more in common with functional languages like Lisp or Scheme than with C or Java. It has arrays instead of lists and objects instead of property lists. Functions are first class. It has closures. You get lambdas without having to balance all those parens. “JavaScript: The World's Most Misunderstood Programming Language” by Douglas Crockford
  • 8.
    So, Javascript isa Functional Programming Language
  • 10.
    function id( a) { return a; } function curried( a ) { return function ( b ) { return a + b; } } First-Class Function Curry
  • 11.
    function compose( gn) { return function ( fn ) { return function( a ) { return gn( fn ( a ) ) ; } } } High-Order Function
  • 12.
    curried( a ) curried(a ) ( b ) curried( a ) ( c ) curried( b ) ( c ) curried( a ) :: a function curried( b ) :: another fn
  • 13.
    Curry can makea new function without definition curried( a ) curried( a ) ( b ) curried( a ) ( c ) curried( b ) ( c )
  • 14.
    curried( a ) curried(a ) ( b ) curried( a ) ( c ) curried( b ) ( c ) new_fn1 = curried( 1 ) new_fn2 = curried( 2 ) new_fn1 ( 1 ) == 1 + 1 new_fn2 ( 1 ) == 2 + 1 We “defined” two functions without definition !
  • 15.
    curried( a ) curried(a ) ( b ) High-Order Function take one or more fn as an input OR output a function ( like Curry )
  • 16.
    curried( a ) curried(a ) ( b ) compose( curried( a ) ) compose( curried( a ) ) ( curried( b ) ) compose( curried( a ) ) ( curried( b ) ) ( a ) Yet another high-order function A normal function A value
  • 17.
    curried( a ) curried(a ) ( b ) compose( curried( 3 ) ) ( curried( 4 ) ) compose( curried( 3 ) ) ( curried( 4 ) ) ( 5 ) Generate value when all conditions are satisfied
  • 18.
  • 19.
  • 20.
    That’s all; It’sso sad Now We Have… High-Order Function
  • 21.
    - Pure Function -Immutable Variable - Encapsulated Impure Features - ( More ) High Order Function - Lazy Evaluation - Functional Data Structure - Type System Javascript lacks
  • 22.
  • 23.
    Immutable Variable mut =1 ; function victim( ) { return 10 / mut ; } $.get ( ‘/change/mut’ , function(data) { mut = 0; });
  • 24.
    Immutable Variable function bad_fn( arr ) { var mut = 0; for( ; mut != arr.length ; mut ++ ) { arr[ mut ] += mut; } return mut; }
  • 25.
  • 26.
    Impure Function OOPs… Itmay cause serious problems gn(3) = 3 gn(3) = 3 gn(3) = 3 gn(3) = 3 gn(3) = 3 gn(3) = 4
  • 27.
    Impure Function i_m_an_innocent_fn :: () -> Int function i_m_an_innocent_fn() { launch_nuclear_missles(); return 3; } Need to be Encapsulated
  • 28.
    Pure X Impure varinnocent_var = 3 * 4 + pow ( 2, 4 ) - i_m_an_innocent_fn() + floor ( 10 * varA ) … … It’s just a numerical expression
  • 29.
  • 31.
    We ( thelaugnage ! ) shouldn’t allow pure functions to mix with impure functions.
  • 32.
    A Real WorldCase ( 2 x 4 hr ) render : function(nst) { var t = this, s = t.settings, id = t.id, sl = tinymce.ScriptLoader; // Page is not loaded yet, wait for it // DEBUG : No, we don't need 'tinymce style' check here...... // Because we use bigpipe tech, this condition statement // will always keep failed. // // snowmantw @ 2012-04-25 18:00:41+08:00 // // if (!Event.domLoaded) { // Event.add(window, 'ready', function() { // t.render(); // }); // return; // }
  • 33.
  • 34.
  • 35.
    Encapsulated Impure Features This iswhy type system matters
  • 36.
    Encapsulated Impure Features ‘return’ can“lift” one pure fn‘s result
  • 37.
  • 38.
    Encapsulated Impure Features It isthe Monad version ‘。’ 。
  • 39.
  • 40.
    Encapsulated Impure Features (>>=) ‘bind’can glue another Action ( functions return Monadic value)
  • 41.
    No pure functioncan get and use values from Monad, unless we wrap it and make it impure, too.
  • 42.
    Monad also make“Statements” in functional way main = printStrLn “This is a interactive program !” >> printStrLn “----” >> printStrLn “Input Something: ” >> readline >>= maybe_str -> case maybe_str of Nothing -> return () Just line -> printStrLn “Input from user: ” >> printStrLn line
  • 43.
    Monad also make“Statements” in functional way function main( ) { console.log( “ This is a interactive program ! ” ) ; console.log( “ ---- “ ) ; var input = readline( ) ; if ( “” == input ) { return ; } console.log( “Input from user: ” ) ; console.log( input ) ; }
  • 44.
  • 45.
    We can assumethat there are no impure functions leaking to the pure world
  • 46.
    And pure functions stillcan be reusable components in our program Just need to be wrapped first
  • 47.
    It’s important because… Inmost cases we just need Modular Programming, not Object-Oriented Programming
  • 48.
    And the conceptsof pureness and composition just fit the need
  • 49.
    Welcome to TheWorld of Composition Function composition ( pure ) ‘。’ : make larger and pure function Monad bind ( impure ) ‘ >>=’ : make useful and larger COMPUTATION Arrow compose ( purer than Monad ) ‘>>>’ : make useful and larger COMPUTATION You can build your whole program with composition
  • 50.
    BTW: Composite "Pattern"is Nothing fa a = b ; fb b = c ; fc = fb . fa class functorA { <Tb> public Tb exec( Ta a ) { return Tb b; } } class functorB{ <Tc> public Tc exec( Tb b ) { return Tc c; } }
  • 51.
    BTW: Composite "Pattern"is Nothing fa a = b ; fb b = c ; fc = fb . fa class FunctorCompose { public Functor compose( fa, fb ) { //....... } } // Use in some method (new FunctorCompose()).compose(fa ,fb)
  • 52.
    Sounds good, but… “It’snot Javascript !”
  • 53.
    The Problem: How canwe program more functionally in the Javascript world ?
  • 54.
  • 55.
    id; map; foldl;getChar; putStrLn; (+) .... map (+1) ; getChar >>= putChar ; f . g
  • 56.
    prog = mapputStrLn >> getChar >>= return . digitToInt >>= x-> return (!!) x str_xs >>= putStrLn
  • 57.
  • 58.
    Keep your functionspure ( Dot ) function fn( x ){ return x; } $IO.impure = function( x ){ return x + read_from_server ( ); } All we can use is the '$' and '_' Impure functions should be restricted in some contexts
  • 59.
    Underscore.js ( Line) _.reduce ( [ 1,2,3 ], function(m,n){ return m+n; },0) `map` and other high order functions _.map ( [ 1,2,3 ], function(n){ return n+1; } ) http://underscorejs.org/
  • 60.
    Functional Javascript (Line ) ' x -> y -> x+y '.lambda()(2); More functional features than Underscore.js ' y x -> x+2*y '.lambda()(2, 3); http://osteele.com/sources/javascript/functional/
  • 61.
    jQuery ( Plane) var pure_val = $( DOM ) . manipulateDOM ( ) . pureCB ( function ( ) { ... } ) . it_has_unwrapper_fns () ; "jQuery is Monad“: http://goo.gl/cFErM http://importantshock.wordpress.com/2009/01/18/jquery-is-a-monad/ http://jquery.com// It's ( almost ) a " DOM Monad "
  • 62.
    Javascript Arrowlet (Plane ) http://www.cs.umd.edu/projects/PL/arrowlets/api-arrowlets.xhtml Redefine the "Process"
  • 63.
    Javascript Arrowlet (Plane ) targetA .next(EventA("click")) .next(start2) .next(EventA("click")) .next(cancel2) .next(Repeat).repeat().run(); http://www.cs.umd.edu/projects/PL/arrowlets/api-arrowlets.xhtml Fully event-driven programming Redefine the "Process"
  • 64.
    Flapjax ( Plane) <p> The time is {! timerB(100) !}. </p> Functional Reactive Programming Need supported compilers http://www.flapjax-lang.org/
  • 65.
  • 66.
    CoffeeScript ( Language) function curried ( a ) { return function ( b ){ return a + b; } } f a b = a + b f = a->b-> a + b
  • 67.
    Why syntax matters a>>= b >>= c >>= d >>= e a >>= ( b >>= c >>= d >>= e ) a >>= ( b >>= ( c >>= d >>= e )) a >>= ( b >>= ( c >>= ( d >>= e )))
  • 68.
    Why syntax matters a>>= b >>= c >>= d >>= e ...... a >>= ( b >>= ( c >>= ( d >>= e ...... )))))))))))))))))))) Parenthesis Hell
  • 69.
    Why syntax matters First-ClassFunction + Monad $( R.id.ButtonToClick ). click ( function(event){ $( R.id.TextViewToShow ).text( ( new SimpleDataFormat( “h:mm:ss a” ) ).format( new Date() ) ; ); } );
  • 70.
    But CoffeeScript isjust a little language… - Pure Function - Immutable Variable - Encapsulated Impure Features - ( More ) High Order Function - Lazy Evaluation - Functional Data Structure - Type System
  • 71.
    Personal Project: FunTanglanguage https://github.com/snowmantw/FunTang
  • 72.
    Personal Project: FunTanglanguage CoffeeScript Functional Features +
  • 73.
    Personal Project: FunTanglanguage Will focus on - Compile into CoffeeScript - Immutable Variable - Pure Function - Integrated Arrow - Fully Event-Driven Process In early stage
  • 74.

Editor's Notes

  • #11 「不是標準 Haskell 語法!」
  • #50 某語言…
  • #51 某語言…
  • #52 因為太可怕所以被迫用 pattern ?