# -*- mgp -*- undefine(len)dnl define(_big_arc, `icon arc "#a0afea" 50')dnl define(_med_arc, `icon arc "#a0afea" 40')dnl define(_small_arc, `icon arc "#a0afea" 30')dnl define(_tt_group, `font "ttb", size 2.9, left, prefix "", vgap 40')dnl define(_o, `%size 1, font "standard", prefix "" %size 5, _big_arc ')dnl define(_op, `%%pause _o')dnl define(_n, `%size 5, font "standard", vgap 60, prefix "" ')dnl define(_impl, `⇒ ')dnl" define(_tt, ` %cont, font "tt" $1 %cont, font "standard" ')dnl define(_it, ` %cont, font "italic" $1 %cont, font "standard" ')dnl define(_emph, ` %cont, fore "#ff4400" $1 %cont, fore "white" ')dnl define(_color, ` %cont, fore $1 $2 %cont, fore "white" ')dnl define(mpage, `page %mark, right %image "merd-logo.png" %again, leftfill')dnl # # %deffont "standard" tfont "arial.ttf" %deffont "italic" tfont "ariali.ttf" %deffont "bold" tfont "arialb.ttf" %deffont "tt" tfont "courbd.ttf" %deffont "ttb" tfont "courbd.ttf" # #%deffont "standard" xfont "lucidux sans-medium-r" #%deffont "italic" xfont "lucidux sans-medium-o" #%deffont "bold" xfont "lucidux sans-bold-r" #%deffont "tt" xfont "courier-bold-r" #%deffont "ttb" xfont "courier-bold-r" # #%deffont "standard" xfont "helvetica-medium-r" #%deffont "thick" xfont "helvetica-bold-r" # #%deffont "standard" tfont "/usr/share/fonts/ttf/western/Bluehigh.ttf" #%deffont "thick" xfont "/usr/share/fonts/ttf/western/Bluehigb.ttf" # #%deffont "standard" xfont "helvetica-medium-r" # # # first line is logo %default 1 area 90 90, fore "white", back "#6567a0", font "standard" # title %default 2 size 6, vgap 10, prefix " " # bar %default 3 size 2, bar "gray70" 10 0 93, vgap 100 # now the body %default 4 vgap 60 %% %tab 1 size 5, vgap 60, prefix " ", _med_arc %tab 2 size 4, vgap 60, prefix " ", _small_arc %tab 3 size 4, vgap 40, prefix " ", icon delta3 "white" 40 # # %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %mpage What's wrong with existing scripting languages? _o scripting languages (python, perl, ruby) are _it(expressive) # _op _emph(but) they miss static checks very few checks are done at compile-time code coverage needs runtime tests _impl medium to big programs hard to maintain # _op alas static analysis of scripting languages is difficult heterogeneous data structures (eg: lists) incremental compilation/loading of packages use of the same variable with values of different types return values ignored %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %mpage What's wrong with statically typed languages? _o explicitly typed languages (C++, Java) too verbose (explicit types can pollute the code) too rigid (no anonymous functions) no datatypes (aka variants) bad handling of non-mutable data %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %mpage Performance: the C case _o C's performance comes from low-level programming. _o The cost is hazardous behavior, safeness being the programmer's job, which doesn't scale. _o Performance doesn't need to imply unsafeness using higher-level libraries gives the same performance without loosing safeness separating low-level programming from high-level programming is a solution (see C# and pliant) _o optimizing C programs is hard and/or dangerous explicit parallelism hidden complex memory aliasing (eg: untagged unions) no way to differentiate requirements from unthought choices (eg: aligned vs non-aligned structs) program analysis very hard %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %mpage Pointers are dead! _o Datatype created in PL/I to access memory a la assembly _o Pros: liberty, powerful, simple to implement _o Cons: unsafe don't get along with Garbage Collection _tt(char*) is not a good representation of strings (see perl where substr is seldom used) arrays need a proper API _o Replaced by references no arithmetic operation allowed only dereferencing %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %mpage Memory management _o Static: everything must be known at compile time _o Stack: enables recursion enables stack allocated arrays (growing data) _o Heap: pros: data can outlive function cons: need to free memory _o GC (Garbage Collector) Heap with no need to free memory by hand %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %mpage Memory management: GC _o pros allows implicit memory allocation allows mutable lists in the language, eg: _tt(`l = [1,2]') favors data sharing, can be more efficient than hand-managed memory _o cons can be slow or block execution (think GUI) finalization time is unknown _o implementation reference counting (incremental, but circular ref!) mark & sweep (can be incremental) copying generational (copying + mark & sweep), train algorithm %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %mpage Memory management: Data sharing _o shallow vs deep copy _o shallow vs deep comparison _o no such problem with purely functional data structures shallow and deep is the same because use of copy on write %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %mpage What's wrong with statically typed languages? _o explicitly typed languages (C++, Java) too verbose (explicit types can pollute the code) too rigid (no anonymous functions) no datatypes (aka variants) bad handling of non-mutable data %pause # _op languages with type inference regain some expressivity Haskell: not adapted to imperative programming OCaml: serious candidate, but no overloading poor default library (esp. strings, lists, hashes) no data inheritance uncommon syntax (esp. for imperative programming and OO) %pause _n _impl bring type inference to the imperative/scripting world %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %mpage Syntax introduction _o alike python %mark, _tt_group # python # merd def wrap(str, width): wrap(str, width) = all = [] all = [] line = "" line = "" for l in str.split(): str.words.each.(l -> if len(line+l) >= width: if size(line+l) >= width then all += [line] all += [line] line = "" line = "" line += (line and " ") + l line += (line &&& " ") + l ) return "\n".join(all + [line]) join(all + [line], "\n") %pause _n variable declaration via initialization %again, mark, _tt_group # python # merd def wrap(str, width): wrap(str, width) = %fore "yellow" all = [] all = [] line = "" line = "" %fore "white" for l in str.split(): str.words.each.(l -> if len(line+l) >= width: if size(line+l) >= width then all += [line] all += [line] line = "" line = "" line += (line and " ") + l line += (line &&& " ") + l ) return "\n".join(all + [line]) join(all + [line], "\n") %pause _n indentation shows block structure? %again, mark, _tt_group # python # merd def wrap(str, width): wrap(str, width) = all = [] all = [] line = "" line = "" for l in str.split(): str.words.each.(l -> %fore "yellow" if len(line+l) >= width: if size(line+l) >= width then all += [line] all += [line] line = "" line = "" %fore "white" line += (line and " ") + l line += (line &&& " ") + l ) return "\n".join(all + [line]) join(all + [line], "\n") %pause _n object oriented syntax %again, mark, _tt_group # python # merd def wrap(str, width): wrap(str, width) = all = [] all = [] line = "" line = "" for l in str.split(): _color("yellow", str.words.each).(l -> if len(line+l) >= width: if size(line+l) >= width then all += [line] all += [line] line = "" line = "" line += (line and " ") + l line += (line &&& " ") + l ) return "\n".join(all + [line]) join(all + [line], "\n") %pause _n _tt(return) not needed, but it will _emph(not) kill you (contrary to Perl) %again, mark, _tt_group # python # merd def wrap(str, width): wrap(str, width) = all = [] all = [] line = "" line = "" for l in str.split(): str.words.each.(l -> if len(line+l) >= width: if size(line+l) >= width then all += [line] all += [line] line = "" line = "" line += (line and " ") + l line += (line &&& " ") + l ) %fore "yellow" return "\n".join(all + [line]) join(all + [line], "\n") %fore "white" %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %mpage Expressions vs statements _o a statement is like a procedure, it doesn't return any value _tt(i=0) being a statement disallows _tt(`j=(i=0)'), _tt(`if(i=0)') it also disallows _tt(i = if c then 1 else 2) _op merd enforces via types what Python does via syntax _tt(i=0) returns "_tt(`()')" (alike _tt(void)) _impl _tt(`j=(i=0)') is forbidden _tt(i = if c then 1 else 2) is allowed _impl no distinction with _tt(i = c ? 1 : 2) %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %mpage Functional syntax _o function declaration %size 4 define(_sm, `%prefix " ", _small_arc ')dnl _sm _tt(`f(x) = x + 1') _sm _tt(`f := x -> x + 1') (anonymous function) %size 1 %size 4 _sm _tt(`fact(x) = if x == 0 then 1 else x * fact(x - 1)') _sm _tt(`fact = 0 -> 1 x -> x * fact(x - 1)') %% _op anonymous functions %size 4 _sm _tt(`array.each_with_index(e, i -> "#{i} {e}".println)') _sm _tt(`palindromes = words.filter(s -> s == s.reverse)') %% _op partial application %size 4 _sm _tt(`f(,1)') is equivalent to _tt(`x -> f(x,1)') _sm _tt(`f(1,)') is equivalent to _tt(`x -> f(1,x)') _sm _tt(`[ 1, 0.2, 3.11 ].each(printf("%.2f euros\n",))') %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %mpage Control structures _n control structures are simple multi-operators _tt(if a then b) is sugar for _tt(`if_then(a,b)') evaluation of _tt(Lazy) parameters is delayed %_tt_group, prefix " " Pragma::prefix(-16,if then) Pragma::prefix(-16,if then else) Pragma::prefix(-16,while do) Pragma::prefix(38,not) if a then Lazy(b) else Lazy(c) := a. True -> b False -> c if a then Lazy(b) := if a then b else () while Lazy(a) do Lazy(b) := if a then b while a do b not a = if a then False else True _n %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %mpage Type inference _o simple type inference (Caml like) _tt(`i = 0 ') implies _tt(i !! Int) _tt(`s = "foo" ') implies _tt(s !! String) _tt(`fact(i) ') implies _tt(i !! Int) _tt(`f(x) = x + 1 ') implies _tt(f !! Int -> Int) # _op merd type inference _tt(`i = 0 ') implies _tt(i !> 0) _tt(`s = "foo" ') implies _tt(s !> "foo") _tt(`fact(i) ') implies _tt(i !< Int) _tt(`f(x) = x + 1 ') implies _tt(f !! x -> 1 !< x !< Addable ; x) %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %mpage Type inference (example) %_tt_group, prefix " " wrap(str, width) = all = [] ; line = "" str.words.each.(l -> if size(line+l) >= width then all += [line] line = "" line += (line &&& " ") + l ) join(all + [line], "\n") _n%pause, vgap 50 _tt(str.words) implies _tt(str !< String) %size 3.5 since _tt(words !! String -> [String]) %pause _tt(`size(...) >= width') implies _tt(width !< Uint) %size 3.5 since _tt(size !! Enumerable(a) -> Uint) %pause the return value _tt(`join(...) !! String') %size 3.5 since _tt(`join !! o(a), a -> o !< Vector ; a !< Addable ; a') %pause _n The result is: _tt(`wrap !! String, Uint -> String') _impl each call to _tt(wrap) will be type-checked _tt(`wrap("foo", "bar")') is ill-typed and is rejected %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %mpage Type checking %font "ttb", size 4, vgap 10 nbs = [ 1, 2, 5, 3 ] i = maximum(nbs) #=> 5 %pause nbs = [ 1, 2, 5, "foo" ] i = maximum(nbs)_emph(` #=> ill-typed at compile-time') %pause name, size = s.m("(\w+):(\d+)") _emph(` # example of valid s = "foo:100"') "%d has %0.2f\n".printf(name.capitalize) _emph(` #=> error missing argument to printf') %pause "%d has %0.2f\n".printf(name.capitalize, size / 10) _emph(` #=> error name.capitalize is not a number') %pause, fore "yellow" "%s has %0.2f\n".printf(name.capitalize, size / 10) define(_dsqqdsqd, ` _sm _tt(`[ 1, "foo" ].map(+ 1|&|"bar")') gives _tt(`[ 2, "foobar" ]') ') %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %mpage Merd innovations _o Syntax: horizontal layout _tt(`a * b+c') parsed as _tt(`a*(b+c)') _o Types structural equivalence and open world types experimentation of intersection values and union types _o staged evaluation: execute at compile-time what's possible _impl do some of the classical preprocessor work fill the expressivity gap between static typing world and dynamic typing world %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %mpage Merd: avenir of the universe _n More info: http://merd.net merd's homepage http://www.ocaml.org OCaml's homepage http://lambda.weblogs.com on programming languages http://pleac.sf.net scripting examples These slides online http://merd.net/slides