#lang at-exp slideshow (system "/Applications/plt/bin/raco pkg install staged-slide") #| Run this slideshow by: (a) download the staged-slide library (first time only): from the command-line: `raco pkg install staged-slide` (where `bin/raco` is in the same directory as DrRacket). (b1) from command line: `racket [filename.rkt]`, or (b2) from inside DrRacket: Racket > Run. To generate a pdf, from the commandline `slideshow --pdf [filename.rkt]`, where `bin/slideshow` is in the same directory as DrRacket. |# ; to find `raco`: (explode-path (find-system-path 'exec-file)) (require (only-in racket/draw the-color-database)) (require slideshow/code) ;(require unstable/gui/slideshow) (require slideshow/staged-slide) (require pict/conditional) (define (s title . content) (apply slide #:title title content)) ;(define p para) (define -> "→") ;(define blue (send the-color-database find-color "blue")) (define formula-color (send the-color-database find-color "blue")) (define defn-term-color (send the-color-database find-color "firebrick")) (define defn-body-color (send the-color-database find-color "sienna")) (define (formula . strs) (colorize (para " " (apply it* strs)) formula-color)) ; rectify a string to a pict. ; (define (to-pict blob) (cond [(pict? blob) blob] [(string? blob) (t blob)] [else (raise-type-error 'to-pict "string-or-pict" blob)])) ; Convert any number of strings-or-picts to a single pict (horizontally) ; (define (span #:combine-with [combiner hb-append] . elems) (apply combiner (map to-pict elems))) (define (define-term the-term . the-defn) (ht-append (term the-term) (it ": ") (apply term-defn the-defn))) (define (term t) (colorize (it t) defn-term-color)) (define (term-defn . defn) (colorize (apply para defn) defn-body-color)) ; accept-multiple-strings : (string -> any) -> (string... -> any) ; Accept any number of strings, append them, and then apply `f`. ; (define (accept-multiple-strings f) (λ args (f (apply string-append args)))) ; E.g. (it "hello" "there"), (it "hello" @-> "there). (define it* (accept-multiple-strings it)) (define t* (accept-multiple-strings t)) ;------------------------------------------------------------------- (s "Three useful categories" @para{Learning a programming language involves:} @define-term{Syntax The grammar rules defining a program fragment.} @define-term{Semantics The meaning of various programming fragments.} @define-term{Pragmatics How to @it{effectively} use language features, libraries, IDEs, ...} @para{All three of these are important in how easy it is to easily write high-quality software.} @para{For all categories, consider the principle of least surprise.} ) #| Syntax examples, taken from (simplified) Java: [id-decl] ::= [modifier...] [type] [ident]; | [modifier...] [type] [ident] = [expr]; [modifier] ::= final | static | public | private | protected | synchronized [method-call] ::= [expr] . [name] ( ... ) In particular, note that the syntax does *not* require an object before the '.', as in `"hello".substring(2,5)` or `("hello".substring(2,5)).toUpperCase()` Although syntax tends to be very precisely defined, semantics tends to be described in English, in the language specs. And being in English, it is possible that it's ambiguous. The Algol-60 language spec had inconsistencies. |# #| Pragmatics might also include: file organization (e.g. Java class/file equivalence), how/where to best comment (e.g. javadoc, literate programming), code conventions (e.g. ending predicates with `?`, types start with upper-case, ...) how to organize tests (JUnit, or submodule named `test`, or ...) |# (slide/staged [termlist value variable type expression] #:title "Some vocabulary" (para "Do" @it{not} "confuse the following four!" (item (ht-append @term{value} @it{: } (show @term-defn{a datum -- the fundamental piece of information that can be represented in the program} (after termlist))) (show @para{E.g. @code[37] or @code["hi"]. Values can be passed to functions, returned, stored in variables.} (after termlist))) (item (ht-append @term{variable} @it{: } (show @term-defn{an identifer which, at run time, evaluates to some particular value.} (after value) ))) (item (ht-append @term{type} @it{: } (show @term-defn{a set of values} (after variable))) (show @para{E.g. Java's @tt{short} = {-32768,..., -1,0,+1,+2, ..., +32767}.} (after variable))) (item (ht-append @term{expression} @it{: } (show @term-defn{a piece of syntax which evaluates to some particular value.} (after type) )) (show @para{E.g. @tt{3+4*5} or @tt{sqrt(16)}.} (after type))) )) #| So the syntax of a Java assignment statement (sep. from init) is: [var] = [expr]; This includes: x = 17; x = y; x = y+4; x = Math.sqrt(y+4); In all cases, the bit between `=` and `;` is an expression. Note that really both "+" and "sqrt" are functions: sqrt : double -> double + : int, int -> int compare notation to math/calc: f : R -> R |# (s "Some vocabulary (cont.)" @item{@define-term["literal"]{a piece of syntax which evaluates immediately to a particular value.} E.g. Java @tt{37} or @tt{045} are both literals representing the value 37, which is of @it{type} @tt{int}. And @tt{37.}, @tt{37d}, @tt{37e0} are each literal @tt{double}s. } @para{(We @it{will} often conflate a literal with the value it represents, and only say ``literal'' when we're emphasizing that we're dealing with syntax.)} ) (slide/staged [q1 a1 q2 a2 q3 a3 q4 a4 q5 a5] #:title "trivia: Interning Java string-literals" @para{Literals occur in the source-code text, and can be processed at compile-time. In Java, string literals are ``interned'': If the same string-literal occurs twice, the the compiler is smart enough to only make one object(*), and use the same reference in both places. } @vl-append[ (show (span @tt{"Cathay".substring(3).equals("hay")} (show @tt{ // true} (> stage 1))) (> stage 0)) (show (span @tt{"Cathay".substring(3) == "hay" } (show @tt{ // false} (> stage 3))) (> stage 2)) (show (span @tt{"Cathay" == "Cathay") } (show @tt{ // true (!)} (> stage 5))) (> stage 4)) ] @para{Morever: string-literals with @tt{+} are computed at compile-time. } @vl-append[ (show (span @tt{"Cat" + "hay" == "Cathay" } (show @tt{ // true (!)} (> stage 7))) (> stage 6)) (show (span @tt{"Cat".concat("hay") == "Cathay"} (show @tt{ // false } (> stage 9))) (> stage 8)) #| int n = 35; "hmm" + 35 == "hmm35" "hmm" + n != "hmm35" |# ] (scale @t{(*) This optimization is only safe because Java strings are immutable.} 0.6) ) (s "typing: when?" @define-term{statically-typed At compile-time, the types of all declared names are known.} @para{Can be provided by programmer and checked by type-system, or inferred by the language (ML, Haskell). (C# allows simple @tt{var n = 5;} and infers @tt{n} ∈ int).} @define-term{dynamically-typed Language knows the type of every value.} @para{But a variable might hold values of different types, over its lifetime. php, javascript, racket. Each value may include some extra bits, indicating its type.} ) (s "typing: other approaches" @define-term{duck typing Care about an object having a field/method, not any inheritance.} @para{E.g. javascript} @define-term{untyped} @para{E.g. assembly} @define-term{type-safe Any type error is caught (either dynamically or statically).} @para{Note that C is not type-safe, due to casting. Java's casting @it{is} type-safe (since a bad cast will fail at run-time).} ) (s "typing: strong/weak/non" @t{These terms are often used in different ways:} @define-term{strongly typed @vl-append{@t{no/few implicit type conversions,}@span{@it{or} statically typed}}} @define-term{weakly typed @vl-append{@t{many implicit type conversions,}@span{@it{or} dynamically typed}}} @para{Consider Java @tt{Math.sqrt(16)}, and Java vs php @tt{"50" + 60}. } ; php @tt{50+"60huzzah"}, or @tt{50+"huzzah60"}. ; Recall: Pragmatics, and principle of least surprise. ) (s "Compiling vs Interpreting" @item{A compiler is a function @formula{compile : source-code → machine-code} The resulting machine-code, when executed, runs the program which produces a resulting value.} @item{An interpreter is a function @formula{eval : expr @-> value} which evaluates an expression, producing a resulting value.} ) (s "Compiling vs Interpreting (cont.)" @item{Running interpreted code, you are running the interpreter, which is looking at the source-expression as if it were data.} @item{Running compiled code, you are running the program directly.} @item{Compiled code: faster, but platform-specific.} @para{The distinction is practical, but not fundamental: You can even claim that CPUs are simply interpreters: they read compiled-code as data (from memory), and update their internal state accordingly. @;{ is just an @it{interpreter} for compiled-code! --- treating each op-code as data (loading it from memory).} } @item{A compromise: compile to @it{byte code} (or, javascript), and run an interpreter for that byte code. A speed/platform-dependence trade-off.} )