CSC153 2004S, Class 25: Detour: Miscellaneous Scheme Stuff Admin: * Whoops! Exam 1 still not graded. I'm sorry. Sleep won. * Exam 2 assigned nonetheless. * Bring questions tomorrow, Friday, Monday * Reminder: Disco is this weekend (as are two good plays) so you should start the exam NOW * Reading for tomorrow, too. (Randomness and simulation) * Mondays's outline updated to reflect actual events * Due to popular request, Erik need not attend class on Friday the 12th * Cool convo tomorrow Overview: * Consider how to apply the "divide and conquer" technique to sorting * Key ideas in merge sort. * Key ideas in Quicksort * Lab Detour (what, detours in this class?): Tell us about eqv?. * For strings, vectors, pairs, and procedures, it's mostly like eq? * For numbers, symbols, some other types, it's mostly like equal? * Like eq? it is pretty fast. (Although not quite as fast as eq?) * Like equal?, it handles numbers well. Further detour: > (eq? (expt 2 10000) (expt 2 10000)) #f > (eqv? (expt 2 10000) (expt 2 10000)) #t > (eq? (expt 2 10) (expt 2 10)) #t > (eqv? (expt 2 10) (expt 2 10)) #t Why? * There's only a certain range of numbers for which eq? behaves as we'd like. * But Scheme permits arbitrarily large numbers. Hmmmm .... * The guarantee: if eq? returns true, eqv? must return true * The opposite does not hold (at least if you read the report carefully): eqv? can return true and eq? return false. * Sam's guess: It has to do with the representation of particularly large numbers. * "Small" numbers fit into one "memory unit" (e.g., word) * "Large" numbers are probably implemented as lists or vectors. Since the comparison of such numbers is not as predictable (and may be harder to implement), DrScheme's eq? doesn't handle them. So, what should you use in writing procedures? * Depends on your goal: * If you don't care about deep recursion and your numbers are small, use eq? * If you want to handle strings and such, use equal? * If you want a compromise, use eqv? * Sometimes you need to write your own intermediate form More confusion: > (eq? 'hello 'HELLO) #t > (eq? (string->symbol "hello") 'hello) #t > (eq? (string->symbol "HELLO") 'hello) #f Why? * If you build a symbol with quote, it lowercases automatically * If you build a symbol with string->symbol, it may not More fun > (string->symbol "HELLO") |HELLO| > (symbol->string '|HELLO|) "HELLO" Question: Can you clone procedures? Related question: Can your procedures modify themselves? Probably not. Can we do something else fun? Significant Detour: Continuations * Idea: At any step of computation, you have an "environment" that represents * The current memory locations associated with all symbols * The call stack (what you have to do when step finishes) * For example, in (+ (* x x) 1), the "environment" for (* x x) is "I have to add 1 next" * In Scheme, these environments are called "continuations" and are first-class values. * By first-class, I mean that you can obtain them and use them. * You get them with (call-with-current-continuation proc-that-expects-continuation) * A continuation is a one-parameter procedure * The really odd part: The continuation often implicitly includes "print the result and stop" * Why is this useful? * It's one way to implement error. * It's like a *more powerful* long jump. * It provides a great step in turning recursive procedures into tail-recursive procedures: Set up a stack of continuations (blah (recursive-call ...)) => (new-recursive-call ... (lambda (x) (blah x))) ; The lambda(x) (blah x) is essentially a continuation ;Base case for new procedure is "call my explicit continuation, which isnow a parameter" Example to be expanded tomorrow