SlideShare a Scribd company logo
How to make a new language
and make the world better
...or, let's talk about eDSLs
Greg Weng
about.me/snowmantw
snowmantw@gmail.com
bit.ly/edsl-intro
Make a new programming language?
Why?
Make a new programming language?
Why?
You may have heard
somebody claim that we
already have TOO MUCH
programming languages
in the world
Make a new programming language?
Why?
var i, divs = document.getElementsByTagName
('div');
for(i = 0; i < divs.length; i++) {
divs[i].onclick = function() {
this.style.backgroundColor = 'red';
}
}
var nextElement = document.getElementById
("wrap").nextSibling;
var map_r = [ ];
for( var i = 0; i < foodParcel; i++) {
map_r[i] = foodParcel[i].contents.split(',')
}
var flattern_r = [ ];
// Omit annoying flattern code...
var reduce_r = 0;
// ...
$('div').click(function() {
$(this).css('background-color', 'red');
});
var nextElement = $("#wrap").next();
_(foodParcel).chain()
.map(function(type)
{ return type.contents.split(','); })
.flatten()
.reduce(function(counts, item) {
counts[item] = (counts[item] || 0) + 1;
return counts;
}, {}).value();
From this...
...To this
IMHO, programmer's life always
become better and better with every
single new language
Assembly
JavaScript
C++ JavaC
HaskellPython
Hey! They're LIBRARIES, not
LANGUAGES!
var i, divs = document.getElementsByTagName
('div');
for(i = 0; i < divs.length; i++) {
divs[i].onclick = function() {
this.style.backgroundColor = 'red';
}
}
var nextElement = document.getElementById
("wrap").nextSibling;
var map_r = [ ];
for( var i = 0; i < foodParcel; i++) {
map_r[i] = foodParcel[i].contents.split(',')
}
var flattern_r = [ ];
// Omit annoying flattern code...
var reduce_r = 0;
// ...
$('div').click(function() {
$(this).css('background-color', 'red');
});
var nextElement = $("#wrap").next();
_(foodParcel).chain()
.map(function(type)
{ return type.contents.split(','); })
.flatten()
.reduce(function(counts, item) {
counts[item] = (counts[item] || 0) + 1;
return counts;
}, {}).value();
From this...
...To this
Not really.
They're actually eDSLs,
not only libraries.
embedded DSL means
"...implemented as libraries which exploit the
syntax of their host general purpose language or
a subset thereof, while adding domain-specific
language elements (data types, routines, methods,
macros etc.)."
From Wikipedia (eDSL)
You might already used some of
these eDSLs ...
$('#message')
.val("Winston Smith...")
.fadeOut('slow')
.hide( )
.val("Big Brother Is Watching You")
.css('font-color', 'red')
.show( )
var $message = document.getElementById('message')
$message.value = "Winston Smith..."
fadeOut($message, 'slow')
hide($message)
$message.value = "Big Brother is Watching You"
$message.style.frontColor = 'red'
show($message)
jQuery
You might already used some of
these eDSLs ...
var stooges = [{name : 'curly', age : 25}, {name :
'moe', age : 21}, {name : 'larry', age : 23}]
var youngest = _.chain(stooges)
.sortBy(function(stooge)
{ return stooge.age })
.map(function(stooge)
{ return stooge.name + ' is ' + stooge.age })
.first()
.value();
var stooges = [{name : 'curly', age : 25}, {name :
'moe', age : 21}, {name : 'larry', age : 23}]
stooges.sort( function(stooge)
{ return stooge.age } )
var sorted = [ ]
stooges.forEach( function(e,i,x)
{ result[i] = e.name + 'is' + e,age } )
var yougest = sorted[0]
underscore.js
You might already used some of
these eDSLs ...
query.from(customer)
.orderBy(customer.lastName.asc()
,customer.firstName.asc())
.list(customer.firstName
,customer.lastName);
// Well, I don't want to handle SQL strings in Java
// manually...
// The left will generate SQL like this:
SELECT c.first_name, c.last_name
FROM customer c
ORDER BY c.last_name ASC, c.first_name ASC
LINQ (Java porting)
You might already used some of
these eDSLs ...
select $
from $ (s, e) -> do
where_ (s ^. StockId ==. e ^. EndOfDayStockId &&.
s ^. StockTicker ==. val ticker &&.
s ^. EndOfDayTradeDate ==. val stockDate)
return (e ^. EndOfDayClosingPrice,
e ^. EndOfDayTradeDate)
SELECT end_of_day.closing_price,
end_of_day.trade_date
FROM stock, end_of_day
WHERE stock.stock_id = end_of_day.
stock_id AND (stock.ticker = ? AND
end_of_day.trade_date = ?)
esqueleto
(Haskell)
You might already used some of
these eDSLs ...
var mtxA = [ [ 1, 2, 3 ],
[ 4, 5, 6 ],
[ 7, 8, 9 ] ]
var mtxB = [ [ -1],
[ 0],
[ 1] ]
var mtxC = mul( mtxA, mtxB)
var mtxA = [ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 7, 8, 9 ] ]
var mtxB = [ [ -1], [ 0], [ 1] ]
var mtxC = mul( mtxA, mtxB)
Matrix
Manipulations
eDSLs may (or may not) make your
code shorter and more elegant.
But the most important thing is it helps
you to focus on the current domain
problem with right tools.
$('#message')
.val("Winston Smith...")
.fadeOut('slow')
.hide( )
.val("Big Brother Is Watching You")
.css('font-color', 'red')
.show( )
var $message = document.getElementById('message')
$message.value = "Winston Smith..."
fadeOut($message, 'slow')
hide($message)
$message.value = "Big Brother is Watching You"
$message.style.frontColor = 'red'
show($message)
eDSLs and their domain problems
jQuery DOM manipulation
Underscore.js Computation
LINQ Querying
esqueleto Database Querying
Matrix
Manipulations
Arithemetic (Matrix)
My small but useful (?) eDSL
Gist: bit.ly/sntw-mtx
mtx( 1, 2, 3)
( 4, 5, 6)
( 7, 8, 9)
(10,11,12).
.mul(11,12,13,14)
(14,15,16,15)
(17,18,19,16)
.mul( 3)
( 4)
( 5)
( 6)
.get()
1. Because using Arrays to represent Matrices
is too mainstream.
2. You don't need the stupid [[outer] [brackets]]
anymore!
3. To test my "inifinite curry" in this example.
Syntax
Well, it might be more formal and like a
real language if we can show
something hard to understand...
jsprog := JSStatements prog JSStatements
prog := mtx manipulations get
mtx := mtx rows
rows := row rows
| row
row := ( JSNumber, ..., JSNumber )
get := .get ()
mul := .mul rows
manipulations := mul
/* Can add more manipulations if we need */
And the bigger one
GitHub: bit.ly/fluorine-js
Motivation
try to implement tolerable Monad-like
mechanism in JavaScript,
and make it more functional
The triangle relation between following
3 eDSLs:
Or at least its my goal...
jQuery
UI, IO and other computations
with side-effects
Underscore.js
Pure computations like
map-reduce
Fluorine
Isolate impure computation
and combine them with pure
ones reasonably.
The triangle relation between following
3 eDSLs:
Or at least its my goal...
// Data -> UI DOM
function recover(dataset)
{
return $('#form-wrapper')
.find('#cover')
.hide()
.end()
.find('#form')
.find('input')
.each(/*fill dataset in*/)
.end()
.fadeIn('slow')
.end()
}
// Use function as argument.
fetch_data(URL, recover)
// URL -> IO Data
function fetch_data(url, cb)
{
let parse =
function(html,cb)
{
$vals = $(html)
.find('input')
.val()
return _
.chain($vals)
.map(/*...*/)
.reduce(/* ... */)
.value()
cb($vals)
}
$.get(url, parse)
// IO is async
}
Impure
Pure
The triangle relation between following
3 eDSLs:
Or at least its my goal...
// Data -> UI DOM
function recover(dataset)
{
return $('#form-wrapper')
.find('#cover')
.hide()
.end()
.find('#form')
.find('input')
.each(/*fill dataset in*/)
.end()
.fadeIn('slow')
.end()
}
// Use function as argument.
fetch_data(URL, recover)
// URL -> IO Data
function fetch_data(url, cb)
{
let parse =
function(html,cb)
{
$vals = $(html)
.find('input')
.val()
return _
.chain($vals)
.map(/*...*/)
.reduce(/* ... */)
.value()
cb($vals)
}
$.get(url, parse)
// IO is async
}
// URL -> IO DOM
var recover = IO(URL)
.get()
.tie(function(html)
{ return UI()
.find('input')
.val()
})
._(parse) // IO HTML -> IO Data
.tie(recover) // IO Data -> IO DOM
.idgen()
// recover :: ( ) -> IO DOM
// recover():: IO DOM
var main = recover()
// Run the "Monad", runIO
main()
JavaScript lacks these features to
become more "functional"
PDF: bit.ly/js-fun
From one of my representations in JS Group
1. (Has) First class function & anonymous function
2. (Could) Curry & Partial Application
3. (Poorly) Supports recursion
4. (Isn't) Pure
5. (Isn't) Lazy
The most lethal one is that you can't isolate impure code
as nature as in Haskell.
With Fluorine you can:
GitHub: bit.ly/fluorine-js
1. Isolate impure parts in the program
2. Mix pure/impure when necessary
3. Flow-Control, to avoid callback hell
4. Laziness (well, sort of)
(Cheating) Demo
GitHub: bit.ly/fluorine-js
Principles
GitHub: bit.ly/fluorine-js
1. Define impure parts with contexts
2. foo().bar() ≌ foo >>= bar
3. Don't extract contexts unless necessary
4. Use generators wisely
5. "Making Wrong Code Look Wrong"
Some implementation details
that might interest you
UI context
Customized Process
initialize
Step #1
Step #2
Step #3
Step #4
......
done
Process The type of our contexts are actually
m (Process a)
rather than
m a
They all have implicit process
UI context
Customized Process
initialize
Step #1
Step #2
Step #3
Step #4
......
done
Process
IO context
initialize
Step #1
get
tie
post
......
done
Process
flattern callback hell
reasonably
Process helps us
(Pure code never goes async)
Customized Process
IO context
initialize
Step #1
get
tie
post
......
done
Process You can extract result from UI and other
context (remember Maybe or List?)
var foo = IO().get()....done()().
extract()
// Don't do this.
Because of its internal aschronous
process may return wrong value
However, IO is not "co-context"
You should never extract things from IO
Customized Process
IO context
initialize
Step #1
get
tie
post
......
done
Process For example, this is legal and safe:
var foo = IO().get()....done()().
extract()
However, you should never:
var foo = UI('#foo').$().done()().
extract()
m = head ([1,2,3] >>= return.odd)
Just like
Just like
m = unsafePerformIO (getChar >> getChar)
Customized Process
IO context
initialize
Step #1
get
tie
post
......
done
Process In Haskell, things should never escape
from IO monad due to the side-effects
It's occasionally true in Fluorine. And we
both have very good reasons to say that
The definition and running stage
IO context
initialize
Step #1
get
tie
post
......
done
Process IO.o.prototype.get
definition
➔ Setup the step
from the context
➔ Push the step to
the process
(runtime stack)
➔ Return this to
keep chaining
running
➔ Pop one step from
the stack
➔ Execute it with the
environment
➔ Capture its return
value and pass to
the next
➔ Call next when
this one is done
The definition and running stage
IO context
initialize
Step #1
get
tie
post
......
done
Process This stage would capture information from
the context to create the step
It's also possible to do more check before
we enter the running stage
IO().get('/todo').tie(renew_ui).post
('/ok')
.done()
For example, typed JavaScript?
Thus we don't have compilation time,
we have definition time
The definition and running stage
IO context
initialize
Step #1
get
tie
post
......
done
Process The key is "to call the next when this one
is done" in runtime.
Thus, the |get| step can call the next |tie|
step only after its remote request has
returned success.
This empower us to make customized
binding function, just like the different
>>= among Haskell monads.
Tying
IO context
initialize
Step #1
get
tie
post
......
done
Process Tying means you tied another context into
the current one
In theory, it's very simple: just push
another context generator into the stack
It's an unsuccessful attempt to mimic the
>>= function in Monad Transformer
tie:: m a -> (a -> n b) -> m b
>>=:: M m a -> (a -> M m b) -> M m b
Tying
IO context
initialize
Step #1
get
tie
post
......
done
Process
Note the tied context would take over the
control of the whole process:
IO().get('/todo')
.tie(function(todos)
{
return Event('user-request')
.tie(ui_render(todos))
.done()
})
.post('/ok')
.done()
The |post| won't be executed til the event
|user-request| fired, because it's Event's
default behavior
Something about Lint(s)
Lint hates my eDSL...
Demo
What will you get and lose if you
force your eDSL compatible with
harsh Lint(s)
Too bad...
1. You CAN'T figure out what's going wrong at first look
2. You CAN'T indetify symbols and strings anymore
3. Damn semicolons in a language needn't them
Here are you only choices...
To be or not to be,
that is the question
(Hard work) Make your own Lint
(Bad) Ignore the Lint
Conclusion
Languages
which allow
AMAP ways
to say the
same thing
are
not guilty
Instead of, they will become useful
and graceful Swiss knifes
Of course you must provide a
serious tool, not dangerous IEDs
Of course you must provide a
serious tool, not dangerous IEDs
Remember, you are desinging a
REAL programming language !
In my (painful) experience:
1. debugger, debugger, debugger
2. useful examples
3. simple introducation & detailed API/technical documents
4. eat your own dog food
Even one of those math-like most
language allows users create and
use eDSL
JavaScript, Ruby, Java...
Why forcing people to drive a car only as
a car, when it's actually a Transformer ?
Make your own language!

More Related Content

PDF
Java Basics - Part1
PDF
The art of readable code (ch1~ch4)
PPT
PDF
Swift - 혼자 공부하면 분명히 안할테니까 같이 공부하기
PDF
The Art Of Readable Code
PDF
RxSwift 시작하기
PDF
Symfony2 and Doctrine2 Integration
PDF
JavaScript Design Patterns
Java Basics - Part1
The art of readable code (ch1~ch4)
Swift - 혼자 공부하면 분명히 안할테니까 같이 공부하기
The Art Of Readable Code
RxSwift 시작하기
Symfony2 and Doctrine2 Integration
JavaScript Design Patterns

What's hot (20)

PDF
Rails' Next Top Model
PDF
Doctrator Symfony Live 2011 San Francisco
PPTX
I regret nothing
PPTX
PPTX
Javascript Common Design Patterns
PDF
Transparent Object Persistence with FLOW3
PPTX
Object oriented javascript
KEY
Indexing thousands of writes per second with redis
PDF
Libertyvasion2010
PPTX
Pragmatic metaprogramming
ZIP
Object Oriented PHP5
PDF
CoffeeScript
PDF
Fnt Software Solutions Pvt Ltd Placement Papers - PHP Technology
PDF
Cleaner, Leaner, Meaner: Refactoring your jQuery
PDF
Json and SQL DB serialization Introduction with Play! and Slick
PDF
Pooja Sharma , BCA Third Year
PDF
DataMapper @ RubyEnRails2009
PPTX
Python 내장 함수
PDF
Type safe embedded domain-specific languages
PPT
Bucc Toy Project: Learn programming through Game Development
Rails' Next Top Model
Doctrator Symfony Live 2011 San Francisco
I regret nothing
Javascript Common Design Patterns
Transparent Object Persistence with FLOW3
Object oriented javascript
Indexing thousands of writes per second with redis
Libertyvasion2010
Pragmatic metaprogramming
Object Oriented PHP5
CoffeeScript
Fnt Software Solutions Pvt Ltd Placement Papers - PHP Technology
Cleaner, Leaner, Meaner: Refactoring your jQuery
Json and SQL DB serialization Introduction with Play! and Slick
Pooja Sharma , BCA Third Year
DataMapper @ RubyEnRails2009
Python 내장 함수
Type safe embedded domain-specific languages
Bucc Toy Project: Learn programming through Game Development
Ad

Viewers also liked (20)

PPT
Middleware 2002
PPTX
Evaluation Part 1
PPTX
3 lesiones deportivas
PPTX
Student managed fund final
PPT
Washdc cto-0905-2003
PDF
Service Portfolio-Faculty Version
PPTX
Autodesk inventor basic tools
PPTX
Presentasi april mei cantik
PDF
[하종욱 설명서] IN 기아자동차
PDF
Tempus PROMIS Work Plan (September 2014)
PPT
Dions globalsoa web2presentation1_2006
DOCX
Nagaraj
PPTX
Proekt shum2
PDF
Using Hadoop
DOC
แบบสรุปข้อมูลปรองดองอำเภอแม่ใจ 2557
PPT
10 basics of human genetics
PPT
Social apps 3_1_2008
DOC
Manisha Garg_Resume modified
PPT
It outsourcing 2005
RTF
Prashant Kumar
Middleware 2002
Evaluation Part 1
3 lesiones deportivas
Student managed fund final
Washdc cto-0905-2003
Service Portfolio-Faculty Version
Autodesk inventor basic tools
Presentasi april mei cantik
[하종욱 설명서] IN 기아자동차
Tempus PROMIS Work Plan (September 2014)
Dions globalsoa web2presentation1_2006
Nagaraj
Proekt shum2
Using Hadoop
แบบสรุปข้อมูลปรองดองอำเภอแม่ใจ 2557
10 basics of human genetics
Social apps 3_1_2008
Manisha Garg_Resume modified
It outsourcing 2005
Prashant Kumar
Ad

Similar to [FT-7][snowmantw] How to make a new functional language and make the world better (20)

PDF
Questions On The Code And Core Module
PDF
HTML5 for the Silverlight Guy
KEY
#NewMeetup Performance
PDF
Addressing Scenario
PPT
The Theory Of The Dom
PDF
He stopped using for/while loops, you won't believe what happened next!
KEY
Your Library Sucks, and why you should use it.
PDF
React Native Evening
PDF
Fun Teaching MongoDB New Tricks
PDF
Migrating legacy data
PDF
Exploring Clojurescript
PDF
Practical JavaScript Programming - Session 8/8
KEY
JavaScript Growing Up
PDF
A Small Talk on Getting Big
PPT
Cpp tutorial
PPTX
Untangling8
PDF
A la découverte de TypeScript
PPTX
Rapid and Scalable Development with MongoDB, PyMongo, and Ming
PDF
Node Boot Camp
PPTX
Dart : one language to rule them all - MixIT 2013
Questions On The Code And Core Module
HTML5 for the Silverlight Guy
#NewMeetup Performance
Addressing Scenario
The Theory Of The Dom
He stopped using for/while loops, you won't believe what happened next!
Your Library Sucks, and why you should use it.
React Native Evening
Fun Teaching MongoDB New Tricks
Migrating legacy data
Exploring Clojurescript
Practical JavaScript Programming - Session 8/8
JavaScript Growing Up
A Small Talk on Getting Big
Cpp tutorial
Untangling8
A la découverte de TypeScript
Rapid and Scalable Development with MongoDB, PyMongo, and Ming
Node Boot Camp
Dart : one language to rule them all - MixIT 2013

Recently uploaded (20)

PPTX
Engineering Ethics, Safety and Environment [Autosaved] (1).pptx
PPTX
bas. eng. economics group 4 presentation 1.pptx
PDF
BMEC211 - INTRODUCTION TO MECHATRONICS-1.pdf
PDF
keyrequirementskkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk
PDF
PPT on Performance Review to get promotions
PDF
Embodied AI: Ushering in the Next Era of Intelligent Systems
PPT
introduction to datamining and warehousing
PPTX
FINAL REVIEW FOR COPD DIANOSIS FOR PULMONARY DISEASE.pptx
PPTX
CARTOGRAPHY AND GEOINFORMATION VISUALIZATION chapter1 NPTE (2).pptx
PDF
TFEC-4-2020-Design-Guide-for-Timber-Roof-Trusses.pdf
PDF
Mohammad Mahdi Farshadian CV - Prospective PhD Student 2026
PPTX
Internet of Things (IOT) - A guide to understanding
DOCX
573137875-Attendance-Management-System-original
PPTX
Artificial Intelligence
PPTX
Geodesy 1.pptx...............................................
PPTX
Sustainable Sites - Green Building Construction
PPTX
OOP with Java - Java Introduction (Basics)
PPTX
CH1 Production IntroductoryConcepts.pptx
PPTX
CYBER-CRIMES AND SECURITY A guide to understanding
PPT
Project quality management in manufacturing
Engineering Ethics, Safety and Environment [Autosaved] (1).pptx
bas. eng. economics group 4 presentation 1.pptx
BMEC211 - INTRODUCTION TO MECHATRONICS-1.pdf
keyrequirementskkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk
PPT on Performance Review to get promotions
Embodied AI: Ushering in the Next Era of Intelligent Systems
introduction to datamining and warehousing
FINAL REVIEW FOR COPD DIANOSIS FOR PULMONARY DISEASE.pptx
CARTOGRAPHY AND GEOINFORMATION VISUALIZATION chapter1 NPTE (2).pptx
TFEC-4-2020-Design-Guide-for-Timber-Roof-Trusses.pdf
Mohammad Mahdi Farshadian CV - Prospective PhD Student 2026
Internet of Things (IOT) - A guide to understanding
573137875-Attendance-Management-System-original
Artificial Intelligence
Geodesy 1.pptx...............................................
Sustainable Sites - Green Building Construction
OOP with Java - Java Introduction (Basics)
CH1 Production IntroductoryConcepts.pptx
CYBER-CRIMES AND SECURITY A guide to understanding
Project quality management in manufacturing

[FT-7][snowmantw] How to make a new functional language and make the world better

  • 1. How to make a new language and make the world better ...or, let's talk about eDSLs Greg Weng about.me/snowmantw snowmantw@gmail.com bit.ly/edsl-intro
  • 2. Make a new programming language? Why?
  • 3. Make a new programming language? Why? You may have heard somebody claim that we already have TOO MUCH programming languages in the world
  • 4. Make a new programming language? Why? var i, divs = document.getElementsByTagName ('div'); for(i = 0; i < divs.length; i++) { divs[i].onclick = function() { this.style.backgroundColor = 'red'; } } var nextElement = document.getElementById ("wrap").nextSibling; var map_r = [ ]; for( var i = 0; i < foodParcel; i++) { map_r[i] = foodParcel[i].contents.split(',') } var flattern_r = [ ]; // Omit annoying flattern code... var reduce_r = 0; // ... $('div').click(function() { $(this).css('background-color', 'red'); }); var nextElement = $("#wrap").next(); _(foodParcel).chain() .map(function(type) { return type.contents.split(','); }) .flatten() .reduce(function(counts, item) { counts[item] = (counts[item] || 0) + 1; return counts; }, {}).value(); From this... ...To this
  • 5. IMHO, programmer's life always become better and better with every single new language Assembly JavaScript C++ JavaC HaskellPython
  • 6. Hey! They're LIBRARIES, not LANGUAGES! var i, divs = document.getElementsByTagName ('div'); for(i = 0; i < divs.length; i++) { divs[i].onclick = function() { this.style.backgroundColor = 'red'; } } var nextElement = document.getElementById ("wrap").nextSibling; var map_r = [ ]; for( var i = 0; i < foodParcel; i++) { map_r[i] = foodParcel[i].contents.split(',') } var flattern_r = [ ]; // Omit annoying flattern code... var reduce_r = 0; // ... $('div').click(function() { $(this).css('background-color', 'red'); }); var nextElement = $("#wrap").next(); _(foodParcel).chain() .map(function(type) { return type.contents.split(','); }) .flatten() .reduce(function(counts, item) { counts[item] = (counts[item] || 0) + 1; return counts; }, {}).value(); From this... ...To this
  • 7. Not really. They're actually eDSLs, not only libraries.
  • 8. embedded DSL means "...implemented as libraries which exploit the syntax of their host general purpose language or a subset thereof, while adding domain-specific language elements (data types, routines, methods, macros etc.)." From Wikipedia (eDSL)
  • 9. You might already used some of these eDSLs ... $('#message') .val("Winston Smith...") .fadeOut('slow') .hide( ) .val("Big Brother Is Watching You") .css('font-color', 'red') .show( ) var $message = document.getElementById('message') $message.value = "Winston Smith..." fadeOut($message, 'slow') hide($message) $message.value = "Big Brother is Watching You" $message.style.frontColor = 'red' show($message) jQuery
  • 10. You might already used some of these eDSLs ... var stooges = [{name : 'curly', age : 25}, {name : 'moe', age : 21}, {name : 'larry', age : 23}] var youngest = _.chain(stooges) .sortBy(function(stooge) { return stooge.age }) .map(function(stooge) { return stooge.name + ' is ' + stooge.age }) .first() .value(); var stooges = [{name : 'curly', age : 25}, {name : 'moe', age : 21}, {name : 'larry', age : 23}] stooges.sort( function(stooge) { return stooge.age } ) var sorted = [ ] stooges.forEach( function(e,i,x) { result[i] = e.name + 'is' + e,age } ) var yougest = sorted[0] underscore.js
  • 11. You might already used some of these eDSLs ... query.from(customer) .orderBy(customer.lastName.asc() ,customer.firstName.asc()) .list(customer.firstName ,customer.lastName); // Well, I don't want to handle SQL strings in Java // manually... // The left will generate SQL like this: SELECT c.first_name, c.last_name FROM customer c ORDER BY c.last_name ASC, c.first_name ASC LINQ (Java porting)
  • 12. You might already used some of these eDSLs ... select $ from $ (s, e) -> do where_ (s ^. StockId ==. e ^. EndOfDayStockId &&. s ^. StockTicker ==. val ticker &&. s ^. EndOfDayTradeDate ==. val stockDate) return (e ^. EndOfDayClosingPrice, e ^. EndOfDayTradeDate) SELECT end_of_day.closing_price, end_of_day.trade_date FROM stock, end_of_day WHERE stock.stock_id = end_of_day. stock_id AND (stock.ticker = ? AND end_of_day.trade_date = ?) esqueleto (Haskell)
  • 13. You might already used some of these eDSLs ... var mtxA = [ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 7, 8, 9 ] ] var mtxB = [ [ -1], [ 0], [ 1] ] var mtxC = mul( mtxA, mtxB) var mtxA = [ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 7, 8, 9 ] ] var mtxB = [ [ -1], [ 0], [ 1] ] var mtxC = mul( mtxA, mtxB) Matrix Manipulations
  • 14. eDSLs may (or may not) make your code shorter and more elegant. But the most important thing is it helps you to focus on the current domain problem with right tools. $('#message') .val("Winston Smith...") .fadeOut('slow') .hide( ) .val("Big Brother Is Watching You") .css('font-color', 'red') .show( ) var $message = document.getElementById('message') $message.value = "Winston Smith..." fadeOut($message, 'slow') hide($message) $message.value = "Big Brother is Watching You" $message.style.frontColor = 'red' show($message)
  • 15. eDSLs and their domain problems jQuery DOM manipulation Underscore.js Computation LINQ Querying esqueleto Database Querying Matrix Manipulations Arithemetic (Matrix)
  • 16. My small but useful (?) eDSL Gist: bit.ly/sntw-mtx mtx( 1, 2, 3) ( 4, 5, 6) ( 7, 8, 9) (10,11,12). .mul(11,12,13,14) (14,15,16,15) (17,18,19,16) .mul( 3) ( 4) ( 5) ( 6) .get() 1. Because using Arrays to represent Matrices is too mainstream. 2. You don't need the stupid [[outer] [brackets]] anymore! 3. To test my "inifinite curry" in this example.
  • 17. Syntax Well, it might be more formal and like a real language if we can show something hard to understand... jsprog := JSStatements prog JSStatements prog := mtx manipulations get mtx := mtx rows rows := row rows | row row := ( JSNumber, ..., JSNumber ) get := .get () mul := .mul rows manipulations := mul /* Can add more manipulations if we need */
  • 18. And the bigger one GitHub: bit.ly/fluorine-js
  • 19. Motivation try to implement tolerable Monad-like mechanism in JavaScript, and make it more functional
  • 20. The triangle relation between following 3 eDSLs: Or at least its my goal... jQuery UI, IO and other computations with side-effects Underscore.js Pure computations like map-reduce Fluorine Isolate impure computation and combine them with pure ones reasonably.
  • 21. The triangle relation between following 3 eDSLs: Or at least its my goal... // Data -> UI DOM function recover(dataset) { return $('#form-wrapper') .find('#cover') .hide() .end() .find('#form') .find('input') .each(/*fill dataset in*/) .end() .fadeIn('slow') .end() } // Use function as argument. fetch_data(URL, recover) // URL -> IO Data function fetch_data(url, cb) { let parse = function(html,cb) { $vals = $(html) .find('input') .val() return _ .chain($vals) .map(/*...*/) .reduce(/* ... */) .value() cb($vals) } $.get(url, parse) // IO is async } Impure Pure
  • 22. The triangle relation between following 3 eDSLs: Or at least its my goal... // Data -> UI DOM function recover(dataset) { return $('#form-wrapper') .find('#cover') .hide() .end() .find('#form') .find('input') .each(/*fill dataset in*/) .end() .fadeIn('slow') .end() } // Use function as argument. fetch_data(URL, recover) // URL -> IO Data function fetch_data(url, cb) { let parse = function(html,cb) { $vals = $(html) .find('input') .val() return _ .chain($vals) .map(/*...*/) .reduce(/* ... */) .value() cb($vals) } $.get(url, parse) // IO is async } // URL -> IO DOM var recover = IO(URL) .get() .tie(function(html) { return UI() .find('input') .val() }) ._(parse) // IO HTML -> IO Data .tie(recover) // IO Data -> IO DOM .idgen() // recover :: ( ) -> IO DOM // recover():: IO DOM var main = recover() // Run the "Monad", runIO main()
  • 23. JavaScript lacks these features to become more "functional" PDF: bit.ly/js-fun From one of my representations in JS Group 1. (Has) First class function & anonymous function 2. (Could) Curry & Partial Application 3. (Poorly) Supports recursion 4. (Isn't) Pure 5. (Isn't) Lazy The most lethal one is that you can't isolate impure code as nature as in Haskell.
  • 24. With Fluorine you can: GitHub: bit.ly/fluorine-js 1. Isolate impure parts in the program 2. Mix pure/impure when necessary 3. Flow-Control, to avoid callback hell 4. Laziness (well, sort of)
  • 26. Principles GitHub: bit.ly/fluorine-js 1. Define impure parts with contexts 2. foo().bar() ≌ foo >>= bar 3. Don't extract contexts unless necessary 4. Use generators wisely 5. "Making Wrong Code Look Wrong"
  • 27. Some implementation details that might interest you
  • 28. UI context Customized Process initialize Step #1 Step #2 Step #3 Step #4 ...... done Process The type of our contexts are actually m (Process a) rather than m a They all have implicit process
  • 29. UI context Customized Process initialize Step #1 Step #2 Step #3 Step #4 ...... done Process IO context initialize Step #1 get tie post ...... done Process flattern callback hell reasonably Process helps us (Pure code never goes async)
  • 30. Customized Process IO context initialize Step #1 get tie post ...... done Process You can extract result from UI and other context (remember Maybe or List?) var foo = IO().get()....done()(). extract() // Don't do this. Because of its internal aschronous process may return wrong value However, IO is not "co-context" You should never extract things from IO
  • 31. Customized Process IO context initialize Step #1 get tie post ...... done Process For example, this is legal and safe: var foo = IO().get()....done()(). extract() However, you should never: var foo = UI('#foo').$().done()(). extract() m = head ([1,2,3] >>= return.odd) Just like Just like m = unsafePerformIO (getChar >> getChar)
  • 32. Customized Process IO context initialize Step #1 get tie post ...... done Process In Haskell, things should never escape from IO monad due to the side-effects It's occasionally true in Fluorine. And we both have very good reasons to say that
  • 33. The definition and running stage IO context initialize Step #1 get tie post ...... done Process IO.o.prototype.get definition ➔ Setup the step from the context ➔ Push the step to the process (runtime stack) ➔ Return this to keep chaining running ➔ Pop one step from the stack ➔ Execute it with the environment ➔ Capture its return value and pass to the next ➔ Call next when this one is done
  • 34. The definition and running stage IO context initialize Step #1 get tie post ...... done Process This stage would capture information from the context to create the step It's also possible to do more check before we enter the running stage IO().get('/todo').tie(renew_ui).post ('/ok') .done() For example, typed JavaScript? Thus we don't have compilation time, we have definition time
  • 35. The definition and running stage IO context initialize Step #1 get tie post ...... done Process The key is "to call the next when this one is done" in runtime. Thus, the |get| step can call the next |tie| step only after its remote request has returned success. This empower us to make customized binding function, just like the different >>= among Haskell monads.
  • 36. Tying IO context initialize Step #1 get tie post ...... done Process Tying means you tied another context into the current one In theory, it's very simple: just push another context generator into the stack It's an unsuccessful attempt to mimic the >>= function in Monad Transformer tie:: m a -> (a -> n b) -> m b >>=:: M m a -> (a -> M m b) -> M m b
  • 37. Tying IO context initialize Step #1 get tie post ...... done Process Note the tied context would take over the control of the whole process: IO().get('/todo') .tie(function(todos) { return Event('user-request') .tie(ui_render(todos)) .done() }) .post('/ok') .done() The |post| won't be executed til the event |user-request| fired, because it's Event's default behavior
  • 39. Lint hates my eDSL... Demo
  • 40. What will you get and lose if you force your eDSL compatible with harsh Lint(s) Too bad... 1. You CAN'T figure out what's going wrong at first look 2. You CAN'T indetify symbols and strings anymore 3. Damn semicolons in a language needn't them
  • 41. Here are you only choices... To be or not to be, that is the question (Hard work) Make your own Lint (Bad) Ignore the Lint
  • 43. Languages which allow AMAP ways to say the same thing are not guilty
  • 44. Instead of, they will become useful and graceful Swiss knifes
  • 45. Of course you must provide a serious tool, not dangerous IEDs
  • 46. Of course you must provide a serious tool, not dangerous IEDs Remember, you are desinging a REAL programming language ! In my (painful) experience: 1. debugger, debugger, debugger 2. useful examples 3. simple introducation & detailed API/technical documents 4. eat your own dog food
  • 47. Even one of those math-like most language allows users create and use eDSL JavaScript, Ruby, Java...
  • 48. Why forcing people to drive a car only as a car, when it's actually a Transformer ?
  • 49. Make your own language!