2/20 note: contains potentially useful information not presented during lecture -- such lines are marked with !s. announcements + catch-up review session this sun, 3pm, kimball b11 + E5 was due online at 8am; solutions already posted + course & prelim online evaluation form -- hopefully available thu or fri reminders + P5 due online 8am thu + online lecture evaluation + turn in questions in lecture for bonus + there are lots of unused office hours topics + arrays as lookups + chars as array indices + demo of loop invariant for max example in 2/15 lecture + setting matlab Path + matlab scripts + matlab functions _______________________________________________________________________________ array as lookup table + suppose given $mm$ in range 1..12, we want to print 3 letter abbreviation of the month + could use big conditional (if-elseif-elseif-....else end) + (could use $switch$) + easier to just look it up in a table: monthname = 'JanFebMarAprMayJunJulAugSepOctNovDec'; i = 3*mm; monthname(i-2:i) chars as array indices + recall: a char is internally represented as a small integer + therefore, should be able to use a char as an index into an array + matlab unhappy: doesn't understand using a char as an index + so, convert from char to integer using $double$ or $0+$, e.g. $double('a')$ or $0+'a'$ example: given array $y$ of digits 1..9 (e.g. y = [3 1 4 1 5 9 2 6 5 3 5], print the string where each digit is subsituted with letters as follows: 1 2 3 4 5 6 7 8 9 f e e d f a c e s + can do with a loop and conditionals + better way: map = 'feedfaces'; map(y) _______________________________________________________________________________ notes about the online loop invariant demo !should work under netscape, might need plug-in for internet explorer !code at top ! !+ refer to code from 2/15 lecture for full code, e.g. here ! + $prompt$ initialization not shown ! + $stopping = 0$ not shown !+ $maxsofar$ is a conceptual, mathematical quantity, not a program variable !+ black arrow: points to line of code that was just executed ! + cyan (light blue) line of code: guard of loop or conditional is true ! + magenta (purple) line of code: guard of loop or conditional is false ! + blue line of code: "regular" line of code (not loop, not conditional) !+ green box, green "maxsofar", green "curmax": loop invariant is true !+ red box, red "maxsofar", red "curmax": loop invariant is false ! ! !"maxsofar", "num", "input", "curmax", numbers at bottom of gray rectangle: ! !+ blue line above numbers: input values preceding num (excluding num) !+ "maxsofar" above a number: ! $maxsofar$ is above the maximum input value preceding num (excluding num) ! !+ "num", yellow line above a number: above the latest number read from input ! !+ "input": input values typed in one by one by user ! !+ "curmax" below a number, blue line below numbers: ! $curmax$ is under the maximum input value of the underlined numbers, ! which are the input values preceding $num$ and also possibly including $num$ _______________________________________________________________________________ motivation for scripts consider this code: a = 5; x = linspace(-pi,pi,397); y = rem(x.^2,sin(a*x)); plot(x,y) ...other code... a = 10; x = linspace(-pi,pi,397); y = rem(x.^2,sin(a*x)); plot(x,y) ...other code... a = 50; x = linspace(-pi,pi,397); y = rem(x.^2,sin(a*x)); plot(x,y) ...other code... a = 100; x = linspace(-pi,pi,397); y = rem(x.^2,sin(a*x)); plot(x,y) ...other code... a = 500; x = linspace(-pi,pi,397); y = rem(x.^2,sin(a*x)); plot(x,y) + because of the "other code", cannot use a loop to reduce redundancy. instead, we can write a script $myplot.m$: $x = linspace(-pi,pi,397); y = rem(x.^2,sin(a*x)); plot(x,y)$ and modify the original code to be: a = 5; ...other code... a = 10; myplot ...other code... a = 50; myplot ...other code... a = 100; myplot ...other code... a = 500; myplot observe: to *call* or *invoke$ the script, simply type in script name caveat: need to let matlab know where to look for scripts and functions + use Set Path in File menu or $path$ command _______________________________________________________________________________ motivation for functions suppose now we want to have code like this: x = 17; y = 6*6; fred = rem(x^3, y); % plot with a <-- 17 * fred x = fred; bob = sqrt(x) - y; % plot with a <-- bob x = x + y; % plot with a <-- x-1 that is, like the earlier code, except + "other code" is complicated code that computes various constants, some of which we wish to use as $a$, but $a$ is not set by other code + $x$, $y$ are now variables used by "other code" + script $myplot$ is no good: + $a$ is not set, and even if it were, still have the problem that + script $myplot$ would clobber values of $x$, $y$ used by "other code" solution: use functions + *arguments* (values) are *passed in* to functions and are automatically assigned to the function's *parameters* (variables) + functions have variables in a different *scope* + a scope is sort of like a room (not perfect analogy) + idea: code is run in a scope (room), using the variables there + therefore, variables in different scopes are different, but can have the same name and be used without confusion ! + functions can also *return* values back to caller, ! e.g. probably a good idea to return $x$ and $y$ from $myplot$. modify myplot.m to now be a function: _________________________________________________________________ | | | function [x,y] = myplot(a) | | x = linspace(-pi,pi,397); y = rem(x.^2,sin(a*x)); plot(x,y) | |_________________________________________________________________| + calling code is now: x = 17; y = 6*6; fred = rem(x^3, y); myplot(17 * fred); % plot with a <-- 17 * fred x = fred; bob = sqrt(x) - y; myplot(bob); % plot with a <-- bob x = x + y; myplot(x-1); % plot with a <-- x-1 _______________________________________________________________________________ preview of next lecture: ! returning versus printing a value ! tracing with function calls ! ! to find an identifier (variable or function name): ! + look inside current scope ! (but do not look inside scopes within current scope) ! + if found, great ! + else, move to immediately enclosing scope. repeat. ! + if there is no enclosing scope, then identifier is not known/visible ! ! box scope diagrams for function call ! 1. evaluate arguments ! 2. draw activation record --function name, box-- ! at same scope the function is found ! 3. inside activation record: write in parameters, fill in with argument values ! (1st parameter <-- 1st value, 2nd <-- 2nd, 3rd <-- 3rd, etc.) ! 4. inside activation record: run function body ! 5. copy out return values ! 6. tear down activation record: cross out _______________________________________________________________________________ answers to questions asked in lecture -- important! ! Q: why do you multiply $mm$ by 3 in the name of month example? ! A: each abbreviation is 3 letters long. here is what we want: ! A: mm = 1: monthname(1:3) = 'Jan' ! A: mm = 2: monthname(4:6) = 'Feb' ! A: mm = 3: monthname(7:9) = 'Mar' ! A: mm = 4: monthname(10:12) = 'Apr' ! A: etc. Q: how does $monthname((3*mm-2):3*mm)$ know the value of $mm$? A: the problem statement says "given $mm$", A: which means "assume somehow has already somehow given $mm$ a value". Q: are there spaces in $monthname$? A: no Q: can you lookup an entire array of letters or just one letter at a time? A: yes, you can lookup an entire array. ! Q: what is the advantage of using a lookup table? ! A: it is less verbose/redundant than using lots of conditionals; ! A: it can also be much faster than computing the answer ! Q: how do you initialize an array to store $'t'$ at $x('a')$? ! A: $x(0+'a') = 't';$ ! A: ! A: note: you don't have to pre-allocate an array before storing ! A: values into it. for example, if you start up matlab fresh, you ! A: can immediately run ! A: ! A: >> x(5) = 27; ! A: ! A: and matlab will store 27 at position 5 in $x$; when you assign to part ! A: of a vector, matlab will automatically extend the vector (with 0s) to ! A: be large enough to hold that element. ! A: ! A: note: remember the rules for assignment $lhs <-- rhs$: ! A: 1. evaluate $lhs$ to get a (potential) location ! A: 2. evaluate $rhs$ to get a value ! A: 3. if location $lhs$ does not exist, then *declare* (create) it ! A: 4. put value into location, erasing the old value ! A: ! A: since step 2 occurs before step 3, if $x$ does not exist, ! A: then $x(2) = x(2)+1;$ is an error: ! A: ! A: step 1: the location "position 2 of x" ! A: step 2: "add 1 to value at position 2 of x", oops! no such location yet! Q: does a loop invariant have to say what the loop is doing, Q: or just something that is "unchanging" Q: (true every time the loop guard is checked)? A: technically: only something true every time the loop guard is checked. A: pragmatically, to be useful: what the loop is doing Q: is the stopping value always 0? A: no, which is why good programming style requires us to define a A: constant (e.g. $stopping$) to hold the value, so that we can easily A: change the stopping value if need be. ! A: ideally, we would compute $prompt$ from $stopping$, e.g. ! A: $prompt = ['value (' num2str(stopping) ' to stop)? '];$ ! A: this way, when $stopping$ is changed, $prompt$ is automatically ! A: changed, without any further programming effort. Q: what is $maxsofar$? what is its point? A: it is a conceptual variable, a mathematical definition, used to A: give a definition to $curmax$ for use in the loop invariant Q: why do use a $while$ loop in the max example, not a $for$ loop? A: a $for$ loop is used when you know all the values in advance. A: here, we are reading input that the user types in, so we have A: no idea or control over what the values are; we must keep looping A: until we see the stopping value Q: why exclude current input value $num$ from the definition of $maxsofar$? A: because the stopping value is not part of the input sequence, so A: including $num$ could improperly affect the answer. for example, A: suppose all the input numbers were negative. then at the end of the A: program, $maxsofar$ should be the largest negative value seen. however, A: if $num$ is included, then $maxsofar$ would be set to 0, which is wrong. ! Q: stylewise, should you indent the body of a function? ! A, revised: yes. (not required for P3, but required from now on) ! A, revised: this is because the body is a substructure of the function.