COP 4020 Lecture -*- Outline -*- * Introduction to Programming Concepts (Chapter 1) Based on Peter van Roy and Seif Haridi's book, "Concepts, Techniques, and Models of Computer Programming" (MIT Press, 2004), where all references that are not otherwise attributed are found. ** Working with Mozart/Oz (1.1, Appendix A) You can install your own copy from mozart-oz.org See the course's "Running Oz" web page for details. *** Show where the documentation is In my Windows install it's in \doc\Mozart.chm It's also on the mozart-oz.org web site. *** Browse ------------------------------------------ BROWSE AND SHOW {Browse 3} {Show 3} {Browse true} {Browse fiddle} ------------------------------------------ show how to do feed line, feed region, feed buffer from Oz menu What do these mistakes tell you: {show 3}, Show{3}, Show(3) ? (See mistakes.oz) *** declare **** variables ------------------------------------------ VARIABLES declare X X=20 {Browse (X + X)*100+X} declare Y=25 {Show Y} declare Sum = X+Y {Browse Sum} ------------------------------------------ Note the 3 forms of declaration What does the following mistake tell you: declare z {Show z+3} ? That variable names start with an upper case letter! What does the following mistake tell you: declare Q Q=7 Q=Q+1 {Show Q} ? Can't assign to a variable more than once. Q: What's the difference between a variable in Oz and one in Java? Hence the Oz variables are sometimes called "dataflow variables" **** functions ------------------------------------------ FUNCTION DECLARATIONS declare fun {Inc N} N+1 end declare fun {Fact N} if N==0 then 1 else N*{Fact N-1} end end FOR YOU TO DO Code the Fibonacci function defined by: Fib(0) = 1 Fib(1) = 1 Fib(n) = Fib(n-1) + Fib(n-2), if n >= 2 ------------------------------------------ Note: use =< instead of <= for "less than or equal to" Q: What's the complexity of your solution? It's possible to make this faster by constructing a lazy list of Fibonacci numbers. See Fib.oz. ** Data (Appendix B) See appendix B for details. ------------------------------------------ ATOMIC DATA (APPENDIX B) Numbers: ~5 is minus 5 Character Literals &c is the literal for 'c' == 99 &\n is newline &\012 is also a newline Atoms (like Lisp symbols) an_atom anotherOne ':=' 'if' ------------------------------------------ Note that atoms are either: names that start with a lower case letter, or strings enclosed in single quotation marks ------------------------------------------ STRUCTURED DATA (RECORDS) Records tree(key:I value:Y left:LT right:RT) labeled "tree" with 4 features, whose values are the values of the dataflow variables I, Y, LT, RT truck(maker:gm weight:4020 doors:4) person(name:joe weight:179) message(contents: type(3)) signal() atom Special cases: Tuples (numbered features = no names) triple(1:a 2:b 3:c) == triple(a b c) pair(1:a 2:b) == pair(a b) '#'(a b c) == a#b#c Lists (either nil or tuple with label '|' and 2 features) nil '|'(1:a 2:'|'(1:b 2:nil)) == '|'(a '|'(b nil)) == a|b|nil == [a b] Strings (lists of characters) nil == "" '|'(1:&c 2:'|'(1:&h 2:'|'(1:&a 2:'|'(1:&r 2:'|'(1:&s 2:nil))))) == '|'(&c '|'(&h '|'(&a '|'(&r '|'(&s nil)))) == &c|&h|&a|&r|&s|nil == [&c &h &a &r &s] == "chars" "strings are lists of characters" ------------------------------------------ see the file transcript1.oz Q: What does the result of {Browse song(artist: beatles name:"all you need is love") == song(name:"all you need is love" artist: beatles) } tell you? Q: Does order matter in records? In tuples? no, not named features in records but the order does matter for unnamed features (hence in tuples) Q: How would you define a list recursively? The following (about strings) is adapted from http://www.ling.gu.se/~lager/kurser/Programming/Exercises/warmup.htm: Browse a string like "foo". To display the string as a string in the Browser, do Options->Representation and check the box Strings. Then mark the list of ints (chars) and do Selection->Rebrowse. To show strings as text in the emulator use System.showInfo instead of Show. ** Pattern Matching ------------------------------------------ PATTERN MATCHING Syntax: case of then else end Example: Write ListLength, so that {ListLength nil} = 0 {ListLength [a b c d]} = 4 ------------------------------------------ What is a related simpler example? {ListLength [b c d]} = 3 How can we use that to solve the problem? declare ListLength fun {ListLength L} case L of _|T then 1 + {ListLength T} else 0 end end Note that the pattern variables are really dataflow variables. Thus they all have to start with capital letters. If you don't use a name, use _ instead of a normal variable name % Some tests of ListLength {Browse {ListLength [a b c]}} declare L L = [a#1 b#2 c#3 d#4 e#5 f#6] {Browse {ListLength L}} ------------------------------------------ FOR YOU TO DO Write a function Assoc that takes a list of key-value pairs and a key K, and returns the element in the list associated with K, if any. Examples {Assoc [c#3] c} = 3 {Assoc [a#1 b#2 c#3] b} = 2 {Assoc nil z} = nil {Assoc [a#1 b#2 c#3] z} = nil ------------------------------------------ Q: What is the induction over? Lists Q: What's a related simpler example to the second one? ... and how does that help? ** Higher Order Functions ------------------------------------------ HIGHER-ORDER FUNCTIONS Def: a *higher-order function* Example: Write a function Map that takes a function F and a list Lst and returns the list of the results of applying F to each element of Lst, in order. {Map Add2 nil} = nil {Map Add1 [1 2 3]} = [2 3 4] ------------------------------------------ (There is a Map.oz in the code examples page.) ** threads and dataflow execution *** threads (1.10) ------------------------------------------ THREADS (1.10) Models concurrency in "real world" declare proc {GeneKelly} thread {Dance} end thread {Sing} end end proc {Dance} {Browse im_dancing} {Delay 3} {Browse im_dancing} end proc {Sing} {Browse and_singing} {Delay 3} {Browse in_the_rain} end {GeneKelly} ------------------------------------------ See GeneKelly.oz *** dataflow execution (1.11) ------------------------------------------ DATAFLOW EXECUTION What should happen if we do: declare A B C C = A+B {Browse C} Waits (suspends) % then later feeding... A=10 B=20 Makes the browser show it ------------------------------------------ See tests.oz "Programming errors often result in dataflow suspensions." p. 89 ------------------------------------------ DATAFLOW AND THREADS % The following suspends, % if fed all at once declare L1 {Browse {ListLength L1}} L1 = [a b] % But with threads this works... declare L2 thread {Browse {ListLength L2}} end L2 = [a b c d e] % What's going on here? declare L3 thread {Browse {ListLength L3}} end thread L3 = a|b|c|L4 end L4 = d|nil ------------------------------------------ See tests.oz ** Explicit State (1.12) Q: Why have explicit state? (Gee, I thought I knew the answer to that... :-) To have a memory of what happened previously. Q: How does the book model state? Memory cells with {NewCell X} and access via @ and assignment via := ------------------------------------------ CELLS declare Toggle = {NewCell true} Toggle := {Not @Toggle} {Browse @Toggle} ------------------------------------------ See test2.oz Note that most of the semester we won't use cells, except to contrast with other ways of programming. ** Objects and Classes (skip if low on time) *** Objects (1.13) ------------------------------------------ OBJECTS Object = functions + shared state declare local V in V = {NewCell true} fun {Flip} V := {Not @V} @V end fun {Value} @V end end {Browse {Value}} {Browse {Flip}} {Browse {Value}} ------------------------------------------ See test2.oz Q: Is the state necessarily encapsulated? usually, but doesn't have to be to be considered an object :-( *** Classes (1.14) ------------------------------------------ CLASSES Classes are factories that make objects declare fun {NewToggle} V Flip Value in V = {NewCell true} fun {Flip} V := {Not @V} @V end fun {Value} @V end toggle(flip:Flip value:Value) end declare T1 = {NewToggle} T2 = {NewToggle} _ = if {T1.value} then {T2.flip} else {T1.flip} end {Browse {T2.value}} {Browse {T1.value}} ------------------------------------------ See test2.oz ------------------------------------------ FOR YOU TO DO Write a class Point that implements 2D points with operations Move, GetX, GetY. ------------------------------------------ Q: This is object-based programming. What other feature(s) is needed for OOP? inheritance. ** Concurrency Problems *** Nondeterminism and time (1.15) Q: What happens if you combine concurrency and state? ------------------------------------------ RACE CONDITIONS declare fun {NewMovingAverage} local Old = {NewCell 0.0} New = {NewCell 0.0} Avg = {NewCell 0.0} proc {Put X} Old := @New New := X Avg := (@Old + @New) / 2.0 end fun {Average} @Avg end in movingAvg(put: Put average: Average) end end MA = {NewMovingAverage} thread {MA.put 10.0} end thread {MA.put 20.0} end {Browse {MA.average}} ------------------------------------------ see MovingAverage.oz with the threads I get 0.0, not 15.0 as expected! *** Atomicity (1.16) Q: How can we prevent these problems? Use locks, monitors, transactions, etc. Q: Why is that good? Bad? It's efficient, but it's hard to program (delicate) ** Relational Model (preview of chapter 9) This adds choice, fail, and Solve ------------------------------------------ RELATIONAL EXAMPLE declare fun {Keyword} choice "java" [] "modeling" [] "language" [] "verification" [] "environment" [] "tool" [] "system" [] "project" [] "extensible" [] "advanced" end end fun {Acronym N} if N =< 0 then nil else local First={Keyword}.1 Rest={Acronym N-1} in if {Member First Rest} then fail else First|Rest end end end end fun {FourLetter} {Acronym 4} end {Browse starting} {Browse {List.take {Solve Keyword} 5}} {Browse {List.take {Solve FourLetter} 5}} ------------------------------------------ See FourLetter.oz and FourLetterTest.oz You have to use Solve to get a lazy list of possible solutions, and since it's lazy you have to force some of them, which is what List.take does (gives the first 5 in this case) The idea is to separate out the searching and backtracking logic, which is handled by Solve, from the specification of what the search space is (using choice) and what you want or don't want (using fail)