! 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 ui.gadgets.panes tetris tetris.game combinators generalizations multiline sequences.private ; IN: otug-talk USING: cairo 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-talk/bi.png" } } { $slide "Data flow combinators - cleave family" { { $link 2bi } ", " { $link 2tri } ", " { $link 2cleave } } { $bitmap "resource:extra/otug-talk/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-talk/bi_star.png" } } { $slide "Data flow combinators - spread family" { { $link 2bi* } } { $bitmap "resource:extra/otug-talk/2bi_star.png" } } { $slide "Data flow combinators - apply family" { { $link bi@ } ", " { $link tri@ } ", " { $link napply } } { $bitmap "resource:extra/otug-talk/bi_at.png" } } { $slide "Data flow combinators - apply family" { { $link 2bi@ } } { $bitmap "resource:extra/otug-talk/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 unwieldy..." { $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!"