diff --git a/extra/otug-talk/2bi.png b/extra/otug-talk/2bi.png new file mode 100644 index 0000000000..8f431f87ce Binary files /dev/null and b/extra/otug-talk/2bi.png differ diff --git a/extra/otug-talk/2bi_at.png b/extra/otug-talk/2bi_at.png new file mode 100644 index 0000000000..55d42c2a4c Binary files /dev/null and b/extra/otug-talk/2bi_at.png differ diff --git a/extra/otug-talk/2bi_star.png b/extra/otug-talk/2bi_star.png new file mode 100644 index 0000000000..0fff37624b Binary files /dev/null and b/extra/otug-talk/2bi_star.png differ diff --git a/extra/otug-talk/authors.txt b/extra/otug-talk/authors.txt new file mode 100644 index 0000000000..1901f27a24 --- /dev/null +++ b/extra/otug-talk/authors.txt @@ -0,0 +1 @@ +Slava Pestov diff --git a/extra/otug-talk/bi.png b/extra/otug-talk/bi.png new file mode 100644 index 0000000000..2470c9fab1 Binary files /dev/null and b/extra/otug-talk/bi.png differ diff --git a/extra/otug-talk/bi_at.png b/extra/otug-talk/bi_at.png new file mode 100644 index 0000000000..282f2f118d Binary files /dev/null and b/extra/otug-talk/bi_at.png differ diff --git a/extra/otug-talk/bi_star.png b/extra/otug-talk/bi_star.png new file mode 100644 index 0000000000..e94e3710cf Binary files /dev/null and b/extra/otug-talk/bi_star.png differ diff --git a/extra/otug-talk/logo.bmp b/extra/otug-talk/logo.bmp new file mode 100644 index 0000000000..defc7cc814 Binary files /dev/null and b/extra/otug-talk/logo.bmp differ diff --git a/extra/otug-talk/otug-talk.factor b/extra/otug-talk/otug-talk.factor new file mode 100644 index 0000000000..5730b7b635 --- /dev/null +++ b/extra/otug-talk/otug-talk.factor @@ -0,0 +1,368 @@ +! Copyright (C) 2008 Slava Pestov. +! See http://factorcode.org/license.txt for BSD license. +USING: slides help.markup math arrays hashtables namespaces +sequences kernel sequences parser memoize io.encodings.binary +locals kernel.private tools.vocabs.browser assocs quotations + tools.vocabs tools.annotations tools.crossref +help.topics math.functions compiler.tree.optimizer +compiler.cfg.optimizer fry graphics.bitmap graphics.viewer +ui.gadgets.panes tetris tetris.game combinators generalizations +multiline sequences.private ; +IN: otug-talk + +USING: cairo cairo.samples cairo.ffi cairo.gadgets accessors +io.backend ui.gadgets ; + +TUPLE: png-gadget < cairo-gadget surface ; + +: ( file -- gadget ) + png-gadget new-gadget + swap normalize-path + cairo_image_surface_create_from_png >>surface ; inline + +M: png-gadget pref-dim* ( gadget -- ) + surface>> + [ cairo_image_surface_get_width ] + [ cairo_image_surface_get_height ] + bi 2array ; + +M: png-gadget render-cairo* ( gadget -- ) + cr swap surface>> 0 0 cairo_set_source_surface + cr cairo_paint ; + +M: png-gadget ungraft* ( gadget -- ) + surface>> cairo_surface_destroy ; + +: $bitmap ( element -- ) + [ first gadget. ] ($block) ; + +: $tetris ( element -- ) + drop [ gadget. ] ($block) ; + +: otug-slides +{ + { $slide "Factor!" + { $url "http://factorcode.org" } + "Development started in 2003" + "Open source (BSD license)" + "Influenced by Forth, Lisp, and Smalltalk" + "Blurs the line between language and library" + "Interactive development" + } + { $slide "Part 1: the language" } + { $slide "Basics" + "Stack based, dynamically typed" + { "A " { $emphasis "word" } " is a named piece of code" } + { "Values are passed between words on a " { $emphasis "stack" } } + "Code evaluates left to right" + "Example:" + { $code "2 3 + ." } + } + { $slide "Quotations" + { "A " { $emphasis "quotation" } " is a block of code pushed on the stack" } + { "Syntax: " { $snippet "[ ... ]" } } + "Example:" + { $code + "\"/etc/passwd\" ascii file-lines" + "[ \"#\" head? not ] filter" + "[ \":\" split first ] map" + "." + } + } + { $slide "Words" + { "We can define new words with " { $snippet ": name ... ;" } " syntax" } + { $code ": remove-comments ( lines -- lines' )" " [ \"#\" head? not ] filter ;" } + { "Words are grouped into " { $emphasis "vocabularies" } } + { $link "vocab-index" } + "Libraries and applications are vocabularies" + { $vocab-link "spheres" } + } + { $slide "Constructing quotations" + { "Suppose we want a " { $snippet "remove-comments*" } " word" } + { $code ": remove-comments* ( lines string -- lines' )" " [ ??? head? not ] filter ;" } + { "We use " { $link POSTPONE: '[ } " instead of " { $link POSTPONE: [ } } + { "Create “holes” with " { $link _ } } + "Holes filled in left to right when quotation pushed on the stack" + } + { $slide "Constructing quotations" + { $code ": remove-comments* ( lines string -- lines' )" " '[ _ head? not ] filter ;" "" ": remove-comments ( lines -- lines' )" " \"#\" remove-comments* ;" } + { { $link @ } " inserts a quotation" } + { $code ": replicate ( n quot -- seq )" " '[ drop @ ] map ;" } + { $code "10 [ 1 10 [a,b] random ] replicate ." } + } + { $slide "Combinators" + { "A " { $emphasis "combinator" } " is a word taking quotations as input" } + { "Used for control flow, data flow, iteration" } + { $code "100 [ 5 mod 3 = [ \"Fizz!\" print ] when ] each" } + { "Control flow: " { $link if } ", " { $link when } ", " { $link unless } ", " { $link cond } } + { "Iteration: " { $link map } ", " { $link filter } ", " { $link all? } ", ..." } + } + { $slide "Data flow combinators - simple example" + "All examples so far used “pipeline style”" + "What about using a value more than once, or operating on values not at top of stack?" + { $code "{ 10 70 54 } [ sum ] [ length ] bi / ." } + { $code "5 [ 1 + ] [ sqrt ] [ 1 - ] tri 3array ." } + } + { $slide "Data flow combinators - cleave family" + { { $link bi } ", " { $link tri } ", " { $link cleave } } + { $bitmap "resource:extra/otug-slides/bi.png" } + } + { $slide "Data flow combinators - cleave family" + { { $link 2bi } ", " { $link 2tri } ", " { $link 2cleave } } + { $bitmap "resource:extra/otug-slides/2bi.png" } + } + { $slide "Data flow combinators" + "First, let's define a data type:" + { $code "TUPLE: person first-name last-name ;" } + "Make an instance:" + { $code "person new" " \"Joe\" >>first-name" " \"Sixpack\" >>last-name" } + } + { $slide "Data flow combinators" + "Let's do stuff with it:" + { $code + "[ first-name>> ] [ last-name>> ] bi" + "[ 2 head ] [ 5 head ] bi*" + "[ >upper ] bi@" + "\".\" glue ." + } + } + { $slide "Data flow combinators - spread family" + { { $link bi* } ", " { $link tri* } ", " { $link spread } } + { $bitmap "resource:extra/otug-slides/bi_star.png" } + } + { $slide "Data flow combinators - spread family" + { { $link 2bi* } } + { $bitmap "resource:extra/otug-slides/2bi_star.png" } + } + { $slide "Data flow combinators - apply family" + { { $link bi@ } ", " { $link tri@ } ", " { $link napply } } + { $bitmap "resource:extra/otug-slides/bi_at.png" } + } + { $slide "Data flow combinators - apply family" + { { $link 2bi@ } } + { $bitmap "resource:extra/otug-slides/2bi_at.png" } + } + { $slide "Shuffle words" + "When data flow combinators are not enough" + { $link "shuffle-words" } + "Lower-level, Forth/PostScript-style stack manipulation" + } + { $slide "Locals" + "When data flow combinators and shuffle words are not enough" + "Name your input parameters" + "Used in about 1% of all words" + } + { $slide "Locals example" + "Area of a triangle using Heron's formula" + { $code + <" :: area ( a b c -- x ) + a b c + + 2 / :> p + p + p a - * + p b - * + p c - * sqrt ;"> + } + } + { $slide "Previous example without locals" + "A bit unweildy..." + { $code + <" : area ( a b c -- x ) + [ ] [ + + 2 / ] 3bi + [ '[ _ - ] tri@ ] [ neg ] bi + * * * sqrt ;"> } + } + { $slide "More idiomatic version" + "But there's a trick: put the points in an array" + { $code <" : v-n ( v n -- w ) '[ _ - ] map ; + +: area ( points -- x ) + [ 0 suffix ] [ sum 2 / ] bi + v-n product sqrt ;"> } + } + ! { $slide "The parser" + ! "All data types have a literal syntax" + ! "Literal hashtables and arrays are very useful in data-driven code" + ! { $code "H{ { \"cookies\" 12 } { \"milk\" 10 } }" } + ! "Libraries can define new parsing words" + ! } + { $slide "Programming without named values" + "Minimal glue between words" + "Easy multiple return values" + { "Avoid useless variable names: " { $snippet "x" } ", " { $snippet "n" } ", " { $snippet "a" } ", ..." } + { { $link at } " and " { $link at* } } + { $code "at* [ ... ] [ ... ] if" } + } + { $slide "Stack language idioms" + "Enables new idioms not possible before" + "We get the effect of “keyword parameters” for free" + { $vocab-link "smtp-example" } + } + { $slide "“Perfect” factoring" + { $table + { { $link head } { $link head-slice } } + { { $link tail } { $link tail-slice } } + } + { "Modifier: " { $link from-end } } + { "Modifier: " { $link short } } + "4*2*2=16 operations, 6 words!" + } + { $slide "Modifiers" + "“Modifiers” can express MN combinations using M+N words" + { $code + "\"Hello, Joe\" 4 head ." + "\"Hello, Joe\" 3 tail ." + "\"Hello, Joe\" 3 from-end tail ." + } + { $code + "\"Hello world\" 5 short head ." + "\"Hi\" 5 short tail ." + } + } + { $slide "Modifiers" + { "C-style " { $snippet "while" } " and " { $snippet "do while" } " loops" } + } + { $slide "Modifiers" + { $code ": bank ( n -- n )" " readln string>number +" " dup \"Balance: $\" write . ;" } + { $code "0 [ dup 0 > ] [ bank ] [ ] while" } + } + { $slide "Modifiers" + { $code "0 [ dup 0 > ] [ bank ] [ ] do while" } + { { $link do } " executes one iteration of a " { $link while } " loop" } + { { $link while } " calls " { $link do } } + } + { $slide "More “pipeline style” code" + { "Suppose we want to get the price of the customer's first order, but any one of the steps along the way could be a nil value (" { $link f } " in Factor):" } + { $code + "dup [ orders>> ] when" + "dup [ first ] when" + "dup [ price>> ] when" + } + } + { $slide "This is hard with mainstream syntax!" + { $code + <" var customer = ...; +var orders = (customer == null ? null : customer.orders); +var order = (orders == null ? null : orders[0]); +var price = (order == null ? null : order.price);"> } + } + { $slide "An ad-hoc solution" + "Something like..." + { $code "var price = customer.?orders.?[0].?price;" } + } + ! { $slide "Stack languages are fundamental" + ! "Very simple semantics" + ! "Easy to generate stack code programatically" + ! "Everything is almost entirely library code in Factor" + ! "Factor is easy to extend" + ! } + { $slide "Part 2: the implementation" } + { $slide "Interactive development" + { $tetris } + } + { $slide "Application deployment" + { $vocab-link "webkit-demo" } + "Demonstrates Cocoa binding" + "Let's deploy a stand-alone binary with the deploy tool" + "Deploy tool generates binaries with no external dependencies" + } + { $slide "The UI" + "Renders with OpenGL" + "Backends for Cocoa, Windows, X11: managing windows, input events, clipboard" + "Cross-platform API" + } + { $slide "UI example" + { $code + <" + { 5 5 } >>gap + 1 >>fill + "Hello world!"