29/11/2016
{λ way}
+
{λ way} :: krakow
{lambda talk} alain marty | engineer ECL architect DPLG | france
[email protected]
abstract The {lambda way} project is built on two engines: 1. {lambda talk}, a purely functional language unifying writing, styling and scripting in a single and coherent notation, 2. {lambda tank}, a tiny wiki easy to install as a thin overlay on top of any web browser, allowing a collaborative work between authors, web designers and coders for creating and sharing rich documents on the web.
context « But there are hundred of wiki engines and hundred of languages! Why yet another wiki and another language nobody will ever want to use? » Let's talk about it! Web browsers give everybody an easy access to a plethora of rich documents created by people mastering HTML, CSS, JS, PHP... What is less known, web browser can give everybody a small window to write HTML/CSS/JS code and so add informations to web pages. Wikis[1] belong to this category: « A wiki is a web application which allows collaborative modification, extension, or deletion of its content and structure. »
Writing HTML/CSS/JS code being rather complex and at least tiresome, intermediate syntaxes, for instance WikiText[2], have been created to make things a bit easier. And it's exactly what people use in blogs and wikis. The best known of wikis is Wikipedia, full of rich documented pages written by people supposed not to be web designers or coders. Everything works well but the underlying code is a very obfuscated text, difficult to write, read, edit and maintain. In fact, the WikiText[2] syntax is not intended for writing rich documents. Works have been done to build enhanced syntaxes in order to unify writing, styling and coding, for instance, not to mention desktop tools like LaTeX[3], PDF[4], web tools like CURL[5], LML[6], Skribe[7], Scribble[8], SXML[9], LAML[10], Pollen[11] ... But these tools are definitively devoted to coders, not to web designers and even less to beginners. Hence the {lambda way} project ... In this paper we will focus on {lambda talk}, following two steps: 1. using {lambda talk}, a gentle introduction via simple examples, 2. {lambda talk} more deeply, structure, evaluation, implementation, frequently asked questions.
1. using {λ talk} 1.1 words http://epsilonwiki.free.fr/lambdaway/index.php?view=krakow
Words are written in a code editor frame and displayed in real time in the wiki page, following some 1/11
29/11/2016
{λ way}
predefined styling rules. For instance: Hello brave new World
Hello brave new World
{sqrt 2} {sqrt {+ {* 3 3} {* 4 4}}} code
view
Sometimes styling rules have to be modified here and there. In a standard text editor, applying some bold style on a sequence of words needs two steps, 1) selecting with the mouse and 2) applying a command via some button [B], or via some key combination [^C+B]. In {lambda talk} the sequence select/apply is based on a unique shorthand notation {first rest}, socalled form, where: 1) curly braces {} are used to select a sequence of words and forms, 2) first is a word referencing a function belonging to a given dictionary and applied to rest, 3) rest is any sequence of words and forms. This is a very simple example: Hello {b brave new} World
Hello brave new World
code
view
view
Some words can be seen as numbers and {lambda talk} becomes a pocket calculator code
{div {@ style="color:cyan"} Hello World }
{img {@ src="data/mustangs.jpg" width="98%" title="Mustangs at Las Colinas ©Robert Glen" style=" padding:5px 5px 35px 5px; border:1px solid white; background:white; boxshadow:0 0 8px black" }}
code
view
code
view
Sounds familiar to any web designer, you can simply copy/paste chunks of standard HTML/CSS code. But smart web designers will say « It's a bad practice to mix structure and style! » Ok it's right, it's time to introduce constants and functions.
cyan
You can put all the "ugly" constant HTML/CSS stuff under a name and call it later. For instance you can define the name cyan and apply it later on different words:
http://epsilonwiki.free.fr/lambdaway/index.php?view=krakow
The set of HTML tags is not infinite. Thanks to CSS rules this set can be extended ad libitum. For instance you could apply some cyan color to words like this:
{{cyan}Hello brave new World} {{cyan}Goodbye poor old World}
1.4 constants
2) and call:
1.3 styles
Or display a picture on a shadowed box like this:
1.2 numbers
1) define: {def cyan span {@ style="color:cyan"}}
marvelous world of mathematics.
code
You are in the holy world of nested prefixed expressions! In fact, the {lambda talk} syntax is a shorthand for the standard HTML syntax. whose evaluation will lead to a sequence of words embedded in a valid HTML/CSS code sent to the browser's engine for the final display. Remember that in {lambda talk} out of curly braces words are not evaluated.
{+ 1 2 3} {+ 1 {* 2 3} 4}
view
For instance, the expression {sqrt {+ {* 3 3} {* 4 4}}} is successively replaced by {sqrt {+ 9 16}}, then by {sqrt 25} and finally by 5. It's the hypotenuse of a right angle triangle [3,4]. You are entering the
Hello World
This one is more convoluted: {b Hello {sup World, {sub is {sup there {sub anybody {sup out {sub there {sup ???}}}}}}}} ?????? Hello World, is there anybody out there
6 11 1.4142135623730951 5
code
view
Hello brave new World Goodbye poor old World Giving a name to the messy HTML/CSS stuff defining the previous picture in a shadowed box, a friendly coder could help you to hide HTML/CSS code. Better he could externalize it in another wiki 2/11
29/11/2016
{λ way}
page behaving as a library, extending the concept of CSS stylesheet and opening a way towards more powerful capabilities.
The name hypo is nothing but an alias to {lambda {a b} {sqrt {+ {* a a} {* b b}}}} and it's rather easy to understand that {hypo 3 4} is first replaced by
You can give math expressions a name, provided they are evaluable:
{{lambda {a b} {sqrt {+ {* a a} {* b b}}}} 3 4}, where a and b will be replaced by 3 and 4, leading to this evaluable expression {sqrt {+ {* 3 3} {* 4 4}}}, finally replaced by 5, as we have seen before.
1) define: {def Φ {/ {+ 1 {sqrt 5}} 2} } {def 1*2*...*100 {* {serie 1 100}} }
code
Mixing text and numbers is easy, provided you take some care: 1) define: {def cute_add {lambda {:a :b} {b :a+:b {sup is equal to} {u {+ :a :b}}}}}
2) and call: {Φ} {1*2*...*100}
Φ 1*2*...*100
view
1.618033988749895 9.33262154439441e+157
code 1) define {def color {lambda {myColor} span {@ style="color: myColor;"}}}
view
Hello World Hello World We have seen that the expression {sqrt {+ {* 3 3} {* 4 4}}} is evaluated to 5, the hypotenuse of a right angle triangle [3,4]. Using a function we can delay the evaluation of {sqrt {+ {* a a} {* b b}}} containing undefined arguments a and b until they get their values: code
http://epsilonwiki.free.fr/lambdaway/index.php?view=krakow
1.6 fibonacci numbers {def fibonacci {def fibonacci.rec {lambda {:a :b :c} {if { "3+:b is equal to {+ 3 :b}" 3) and a new function {lambda {:b} 3+:b is equal to {+ 3 :b}} is returned for a future call.
Note: In order to avoid substitution conflicts, the string replacement process used by lambdas implies arguments to be prefixed by a distinctive char, say a colon. In the example shown this precaution obviously prevents the word equal to be replaced by equ3l! For a total security, it should be better to escape arguments between two colons, :local_name:, with the added benefit of enlighting them as local variables, to be compared with global constants called between curly braces, {global_name}.
{λ way}
2.3.4 Do lambdas create closures? No they don't! This weakness is partially balanced by the fact lambdas accept a number of values different from their arity, (partial application with memorization, currying). As a useful application of this capability, this is how can be defined derivatives of a function f(x): f'(x), f''(x), f'''(x), ..., which are functions of x and not values at a given x: • 1) we define the derivative function: {def D {lambda {:f :h :x} {/ { {:f {+ :x :h}} {:f { :x :h}} } {* 2 :h}}}} > D
• 2) we create the 1st, 2nd and 3rd derivatives of the function log for a given value of :h and as functions of :x: {def log' {lambda {:x} {D log 0.01 :x}} } > log' {def log'' {lambda {:x} {D log' 0.01 :x} }} > log'' {def log''' {lambda {:x} {D log'' 0.01 :x} }} > log'''
• 3) we can now call the 1st, 2nd and 3rd derivatives of log on a given value of x: {log' 1} > 1.0000333353334772 // 1 {log'' 1} > 1.0002000533493427 // 1 {log''' 1} > 2.0012007805464416 // 2
Another application of this capability is that any agregate data can be built with lambdas, for instance pairs, lists, arrays, R/C numbers, 2D/3D vectors, .... We have seen an application of pairs, lists in part 1). This is how could be built the cons, car, cdr functions usually associated to pairs:
{def cons {lambda {:a :b :m} {{:m :a} :b}}} {def car {lambda {:p} {:p {lambda {:x :y} :x}}}} {def cdr {lambda {:p} {:p {lambda {:x :y} :y}}}}
Because they are so useful, pairs and lists and arrays are actually built as primitives in the {lambda talk}'s dictionary.
2.3.4 Do lambdas create 2.3.5 Can special forms be nested? Yes you can! • defs can be nested. But inner defs are not local to the outer def. There are no nested environments. So, in order to prevent names http://epsilonwiki.free.fr/lambdaway/index.php?view=krakow
conflicts, a good practice - mimicking the OOP paradigm - is to prefix inner-defined names with the outer-defined names. For instance in the following example hypo.square can be considered as a property of hypo: {def hypo {def hypo.square {lambda {:x} {* :x :x}}} {lambda {:a :b} {sqrt {+ {hypo.square :a} 7/11
29/11/2016
{hypo.square :b}}}}} > hypo {hypo 3 4} > 5 {hypo 1 1} > 1.4142135623730951
• ifs can be nested, leading to conditional sequences, for instance:
{λ way}
factorial n! {def ! {lambda {:a :b} {if { ! {! 6} > 720
{def inside? {lambda {:x :a :b} {if {equal? {+ 1 :x} NaN} then {u :x} is Not a Number else {if { false {inside? 2 1 10} > true {inside? 11 1 10} > false {inside? foo 1 10} > foo is Not a Number
and the Euler's number 2.718281828459045 defined as an infinite serie: E = Σi=0∞[1/1*2*..*i]
• lambdas can be nested. This is an example where we want to compute the area of a right angle triangle [a,b,c] given by this formula: area = √s*(s-a)*(s-b)*(s-c) where s= (a+b+c)/2: 1) using lambdas: {{lambda {:a :b :c} {{lambda {:a :b :c :s} {sqrt {* :s { :s :a} { :s :b} { :s :c}} }} :a :b :c {/ {+ :a :b :c} 2} }} 3 4 5} > 6 2) using let: {{lambda {:a :b :c} {let { {:a :a} {:b :b} {:c :c} {:s {/ {+ :a :b :c} 2} }} {sqrt {* :s { :s :a} { :s :b} { :s :c}} }}} 3 4 5} > 6
• Note that, because lambdas don't create closures, inner lambdas have no access to the outer lambdas arguments. This is why :a :b :c must be duplicated in the above both versions. This workaround could be seen as a manual closure ... which could be automatized in a next version of lambdatalk. Wait and see!
2.3.6 What about iterative processes? Theoretically recursion can be used to build every iterative processes. For instance the well known
2.3.9 What about styles? CSS rules applied to the entire wiki are externalized as CSS files in the skins folder and can be selected in the lambdatank's topleft menu. The current skin can http://epsilonwiki.free.fr/lambdaway/index.php?view=krakow
{* {serie 1 20}} > 2432902008176640000
{def euler {lambda {:n} {+ 1 {reduce {lambda {:a :b} {+ :a :b}} {map {lambda {:i} {/ 1 {* {serie 1 :i {serie 1 :n}}}}}} > euler {euler 17} > 2.7182818284590455
2.3.7 What about mutability? Defined values can't be modified, lambdatalk is purely functional and has no set! special form. Mutations are exclusively made via functions' arguments.
2.3.8 Why is lambdatalk easy to use by web designers? In Part 1) we have seen how a the {lambda talk} syntax built over the HTML/CSS syntaxes can stay familiar to a web designer. However it's noticeable that the {@ ...} form breaks the previously claimed syntax unicity, there are no clean forms in it and to many ugly quoted strings used by HTML attributes and CSS rules! It was a matter of design choice, in order to avoid any pollution of the dictionary with a myriad of CSS rules and giving web designers an access to standard HTML attributes and CSS rules they are familiar with. And we have seen that any coder is able to hide behind names all those ugly things.
be analyzed in the file skins/newone/CSS.css. Local CSS rules can be applied to a page using the {style ...} form. For instance in this page, a few tags have been overloaded like this:
8/11
29/11/2016
{style body { background:#fff; normal 1.0em Times New Roman; } #title { color:#fff; textshadow:0 0 0; } #frame_view { width:100%; padding:0; border:0 solid; boxshadow:0 0 0; background:#fff; color:#000; } h1, h2, h3, h4, h5, h6 { margintop:10px; marginbottom:0px; } h1 { fontsize:3.0em; color:black; } h2 { fontsize:2.6em; color:red; } h3 { fontsize:2.2em; color:green; } h4 { fontsize:1.8em; color:blue; } h5 { fontsize:1.4em; color:magenta; } h6 { fontsize:1.0em; color:cyan; } }
2.3.10 What about scripts? The primitive {input ...} can easily embed short scripts via any onEvent attribute. For instance: {input {@ id="smart_hello" type = "text" placeholder = "Enter your name" onkeyup = "getId('yourName').innerHTML = 'Hello ' + getId('smart_hello').value + ' !'" }} {h1 {@ id="yourName"}}
{λ way}
{script function start() { document.chrono = window.setInterval( function() { getId('output').innerHTML = 'time: ' + LAMBDATALK.eval_forms({date}'); }, 1000 ); } function stop() { window.clearInterval( document.chrono ) } }
displays a digital watch:
time: 2016 11 29 11 40 47 start
stop
2.3.11 What about libraries? Sets of user variables and functions can be stored in wiki pages and called elsewhere via a (require library) call. Thus, the primitive dictionary can be extended as necessary with coherent modules carefully built to avoid name conflicts. For instance, functions defined in some lib_SVG_clock page can be used via a (require ...) to display a stylized clock: {center {{svg.clock 300 300} {svg.path 150 150 100 20 red 1} {svg.path 150 150 120 20 green 2} {svg.path 150 150 140 20 blue 3} {svg.digit} }}
displays this text field in which you can enter your name: Joe
Hello Joe !
11 39 28
The primitive {script ...} can be used to insert more complex scripts. For instance: {div {@ id="output" style="..."}time: } {input {@ type="submit" value="start" onclick="start()"}} {input {@ type="submit" value="stop" onclick="stop()"}}
2.3.12 What about macros? Macros in lambdatalk bring the power of regular expressions directly in the language. As an example, this is how we define an array of ten numbers and display them squarred using the lambdatalk syntax: {def A {array {serie 1 10}}} > A http://epsilonwiki.free.fr/lambdaway/index.php?view=krakow
{map {lambda {:i} {* {array.nth {A} :i} {array.nth {A} :i}}} {serie 0 { {array.length {A}} 1}}} > 1 4 9 16 25 36 49 64 81 100
It's rather difficult to read. Thanks to a small set of helper functions and a single macro {def K.disp {lambda {:arr} {array.disp {:arr}} 9/11
29/11/2016
{λ way}
}} > K.disp {def K.nth {lambda {:arr :i} {array.nth {:arr} :i} }} > K.nth {def K.range {lambda {:arr} {serie 0 { {array.length {:arr}} 1} }}} > K.range {macro ([\w:]+?)\[([\w:]*?)\] to {if {empty? €2} then {K.disp €1} else {if {equal? €2 range} then {K.range €1} else {K.nth €1 €2}}}}
we can write the previous expression in a more readable way: {map {lambda {i} {* A [i] A [i]}} A [range]} > 1 4 9 16 25 36 49 64 81 100
In this example it's easy to see a regular expression based syntax before the word to and a lambdatalk based syntax after with a nested if then else control structure. {lambda talk} comes with a predefined small set of useful macros allowing writing titles, paragraphs and item lists without curly braces: _h1 TITLE cr stands for {h1 TITLE} and alike for h2, h3, h4, h5, h6 _p Some paragraph ... cr stands for {p Some paragraph ...} _ul list item 1 cr _ul list item 1 cr _ul list item 1 cr stands for {ul {li list item 1} {li list item 2} {li list item 3} }
These simplified alternatives, avoiding curly braces as much as possible, are fully used in this document.
2.3.13 Where does lambdatalk come from? Not exactly from Lisp, built on List Processing, but from the lambda calculus[17] defined by Alonzo Church in the thirties and built on words substitution. Following the lambda calculus a {lambda talk} expression could be defined like this: expression ::= word | abstraction | application
Where 1. a word is any sequence of chars except spaces and {}, and is evaluated to itself, 2. an abstraction is a form {lambda {words} expression}, and is evaluated to the reference of an anonymous function, 3. an application is a form {abstraction expression}, and is evaluated to a sequence of words. At this point {lambda talk} knows nothing but text substitutions. For instance: 1) words Hello World > Hello World 2) abstraction {lambda {o a} oh happy day!} > lambda_1234 3) application {{lambda {o a} oh happy day!} oOOOo aaAAaa} > oOOOoh haaAAaappy daaAAaay!
Amazingly nothing more is needed to compute expressions such 6! = 1*2*3*4*5*6 = 720: {{λ {:n} {{λ {:p} {:p {λ {:x :y} :y}}} {{:n {λ {:p} {{λ {:a :b :m} {{:m :a} :b}} {{λ {:n :f :x} {:f {{:n :f} :x}}} {{λ {:p} {:p {λ {:x :y} :x}}} :p}} {{λ {:n :m :f} {:m {:n :f}}} {{λ {:p} {:p {λ {:x :y} :x}}} :p} {{λ {:p} {:p {λ {:x :y} :y}}} :p}}}}} {{λ {:a :b :m} {{:m :a} :b}} {λ {:f :x} {:f :x}} {λ {:f :x} {:f :x}}}}}} {λ {:f :x} {:f {:f {:f {:f {:f {:f ... total 6 times}}}}}}}} > {λ {:f :x} {:f {:f {:f {:f {:f {:f ... total 720 times}...}
where λ stands for lambda to be short. Read more in calc2talk[18]. Usually the lambda calculus comes with the Church numbers and a set of operators, [def, succ, add, mul, succ, power, cons, car, cdr, pred, subtract, ..., Y-combinator] to make things easy
to write and read. And theoretically, we could go on this way to build the majority of {lambda talk}'s functionalities. But in order to bring a bit of humanity and make coding much more easy it's more reasonable to play with readable defined names and populate the dictionary with some useful primitive functions built on the browser's foundations, Javascript's numbers, Math operators and functions, HTML tags, CSS rules, and some others. With an augmented set of special forms, [lambda, def, if, let, quote, ...], all these "improvements" lead to a more usable and effective language, {lambda talk}.
conclusion conclusion http://epsilonwiki.free.fr/lambdaway/index.php?view=krakow
10/11
29/11/2016
The {lambda way} project is essentially built on a 30kb PHP file and a 60kb JS file. It's free of any external dependancies, {lambda talk} can be used out of {lambda tank} and embedded in any other environment. The underlying PHP+JS code is small and easy to read, edit and improve. It's a free software under the GNU GPL licence. Its 100kb archive is easy to download & install on any web account running PHP. {lambda talk} is a small but complete programmable programming language offering tools which can be used, in any modern web browser and on any device (from desktop PCs to smartphones) at three levels of increasing complexity: with a handful of basic commands any author can easily create minimally structured documents made of words and pictures, any web designer can find a full set of HTML tags and CSS rules to enrich them, and any coder can fit specific needs and make pages compositing more easy by extending the language's builtin functionalities. Everybody sharing a clear, unique and coherent notation allowing to produce rich and dynamical documents in a true collaborative work. Commenting this work, somebody wrote this: « Reminds me of John McCarthy's lament at the W3C's choice of SGML as the basis for HTML: "An environment where the markup, styling and scripting is all sexpression based would be nice." » This was the goal of the lambdaway project[19]. Villeneuve de la Raho, 2016/11/22
references
{λ way}
- [1] https://en.wikipedia.org/wiki/Wiki - [2] https://en.wikipedia.org/wiki/Wiki_markup - [3] http://epsilonwiki.free.fr/lambdaway/? view=latex - [4] http://epsilonwiki.free.fr/lambdaway/? view=PDF - [5] http://epsilonwiki.free.fr/lambdaway/? view=curl - [6] http://epsilonwiki.free.fr/lambdaway/? view=LML - [7] http://epsilonwiki.free.fr/lambdaway/? view=skribe - [8] http://docs.racket-lang.org/scribble/ - [9] http://epsilonwiki.free.fr/lambdaway/? view=SXML - [10] http://people.cs.aau.dk/~normark/laml/papers/webprogramming-laml.pdf - [11] http://docs.racket-lang.org/pollen - [12] https://fr.wikipedia.org/wiki/Suite_de_Fibonacci - [13] https://en.wikipedia.org/wiki/De_Casteljau's_algorithm - [14] https://en.wikipedia.org/wiki/Simon_Peyton_Jones - [15] https://www.cnet.com/news/googlesubtracts-mathml-from-chrome - [16] https://en.wikipedia.org/wiki/Ward_Cunningham - [17] http://jwodder.freeshell.org/lambda.html - [18] http://epsilonwiki.free.fr/lambdaway/? view=calc2talk - [19] http://epsilonwiki.free.fr/lambdaway/ - ... - PDF version generated from this wiki page - ... - ... {λ way} v.20160608
http://epsilonwiki.free.fr/lambdaway/index.php?view=krakow
11/11