How to make a new language
and make the world better
...or, let's talk about eDSLs
Greg Weng
about.me/snowmantw
snowmantw@...
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 language...
Make a new programming language?
Why?
var i, divs = document.getElementsByTagName
('div');
for(i = 0; i < divs.length; i++...
IMHO, programmer's life always
become better and better with every
single new language
Assembly
JavaScript
C++ JavaC
Haske...
Hey! They're LIBRARIES, not
LANGUAGES!
var i, divs = document.getElementsByTagName
('div');
for(i = 0; i < divs.length; i+...
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 subse...
You might already used some of
these eDSLs ...
$('#message')
.val("Winston Smith...")
.fadeOut('slow')
.hide( )
.val("Big ...
You might already used some of
these eDSLs ...
var stooges = [{name : 'curly', age : 25}, {name :
'moe', age : 21}, {name ...
You might already used some of
these eDSLs ...
query.from(customer)
.orderBy(customer.lastName.asc()
,customer.firstName.a...
You might already used some of
these eDSLs ...
select $
from $ (s, e) -> do
where_ (s ^. StockId ==. e ^. EndOfDayStockId ...
You might already used some of
these eDSLs ...
var mtxA = [ [ 1, 2, 3 ],
[ 4, 5, 6 ],
[ 7, 8, 9 ] ]
var mtxB = [ [ -1],
[ ...
eDSLs may (or may not) make your
code shorter and more elegant.
But the most important thing is it helps
you to focus on t...
eDSLs and their domain problems
jQuery DOM manipulation
Underscore.js Computation
LINQ Querying
esqueleto Database Queryin...
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,1...
Syntax
Well, it might be more formal and like a
real language if we can show
something hard to understand...
jsprog := JSS...
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...
The triangle relation between following
3 eDSLs:
Or at least its my goal...
// Data -> UI DOM
function recover(dataset)
{
...
The triangle relation between following
3 eDSLs:
Or at least its my goal...
// Data -> UI DOM
function recover(dataset)
{
...
JavaScript lacks these features to
become more "functional"
PDF: bit.ly/js-fun
From one of my representations in JS Group
...
With Fluorine you can:
GitHub: bit.ly/fluorine-js
1. Isolate impure parts in the program
2. Mix pure/impure when necessary...
(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 c...
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 ...
UI context
Customized Process
initialize
Step #1
Step #2
Step #3
Step #4
......
done
Process
IO context
initialize
Step #1...
Customized Process
IO context
initialize
Step #1
get
tie
post
......
done
Process You can extract result from UI and other...
Customized Process
IO context
initialize
Step #1
get
tie
post
......
done
Process For example, this is legal and safe:
var...
Customized Process
IO context
initialize
Step #1
get
tie
post
......
done
Process In Haskell, things should never escape
f...
The definition and running stage
IO context
initialize
Step #1
get
tie
post
......
done
Process IO.o.prototype.get
definit...
The definition and running stage
IO context
initialize
Step #1
get
tie
post
......
done
Process This stage would capture i...
The definition and running stage
IO context
initialize
Step #1
get
tie
post
......
done
Process The key is "to call the ne...
Tying
IO context
initialize
Step #1
get
tie
post
......
done
Process Tying means you tied another context into
the current...
Tying
IO context
initialize
Step #1
get
tie
post
......
done
Process
Note the tied context would take over the
control of ...
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 ...
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...
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!
Upcoming SlideShare
Loading in …5
×

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

254 views

Published on

How to make a new functional language and make the world better
--by Greg Wang (snowmantw)
--on Functional Thursday Meetup 7

0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
254
On SlideShare
0
From Embeds
0
Number of Embeds
42
Actions
Shares
0
Downloads
3
Comments
0
Likes
1
Embeds 0
No embeds

No notes for slide

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

  1. 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. 2. Make a new programming language? Why?
  3. 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. 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. 5. IMHO, programmer's life always become better and better with every single new language Assembly JavaScript C++ JavaC HaskellPython
  6. 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. 7. Not really. They're actually eDSLs, not only libraries.
  8. 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. 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. 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. 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. 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. 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. 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. 15. eDSLs and their domain problems jQuery DOM manipulation Underscore.js Computation LINQ Querying esqueleto Database Querying Matrix Manipulations Arithemetic (Matrix)
  16. 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. 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. 18. And the bigger one GitHub: bit.ly/fluorine-js
  19. 19. Motivation try to implement tolerable Monad-like mechanism in JavaScript, and make it more functional
  20. 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. 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. 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. 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. 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)
  25. 25. (Cheating) Demo GitHub: bit.ly/fluorine-js
  26. 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. 27. Some implementation details that might interest you
  28. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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
  38. 38. Something about Lint(s)
  39. 39. Lint hates my eDSL... Demo
  40. 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. 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
  42. 42. Conclusion
  43. 43. Languages which allow AMAP ways to say the same thing are not guilty
  44. 44. Instead of, they will become useful and graceful Swiss knifes
  45. 45. Of course you must provide a serious tool, not dangerous IEDs
  46. 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. 47. Even one of those math-like most language allows users create and use eDSL JavaScript, Ruby, Java...
  48. 48. Why forcing people to drive a car only as a car, when it's actually a Transformer ?
  49. 49. Make your own language!

×