On 12/09/2010 12:48 PM, Luke Jordan wrote:
I will look at for and in-range and spend some more time exploring the
built-ins.  But I want to talk about the do-times solution, because that
was the first thing I tried, but I couldn't make it work.  In chapter 11
expression arguments are applied to something that builds up a result
(as a list or an arithmetic operation).  I don't understand how that
applies to what I'm trying to do here since I'm not building anything,
just calling it over and over and ignoring the result.  Following what I
learned from chapter 11 the code would look something like this, which
doesn't make sense.

(define (do-times n expr)
   (cond
     [(< n 1) evaluate-expr-last-time]
     [else ?? evaluate-expr (do-times (sub1 n) expr)]))

Let me rewrite that a little bit:

;; do-times : Nat (-> Void) -> Void
;; Applies the given thunk n times.
(define (do-times n action)
  (cond [(zero? n) <BASE>]
        [else
         (<COMBINE> action (do-times (sub1 n) action)]))

What to put in the base case? Well, how many times should (do-times 0 action) apply the action? None. So <BASE> shouldn't involve action at all. In Racket, the value that represents "nothing", "the commands have been executed", etc is called the void value---but unlike in C and Java, it actually is a value. You can get the void value by calling (void). Note that the only thing special about the void value is that the REPL printer doesn't print it; you could design this function using any value to represent "I'm done, nothing else to report".

So now how to <COMBINE>? It should perform the action (represented by a procedure of no arguments returning void) and then recur. The idiomatic Racket way is to use 'begin':

  (begin (action) (do-times (sub1 n) action))

But if you don't know 'begin', you can also do it using 'local' (or 'let', etc):

  (local [(define do-not-care (action))]
    (do-times (sub1 n) action))

Finally, it is still important to test such functions. It's harder, but it's possible to test actions by their effect on data. (Mutation is covered in Part VII.) Here's one way:

;; test-do-times : Nat -> boolean
;; Should always return #t, if do-times is working.
(define (test-do-times n)
  (let ([counter 0])
    (begin (do-times n (lambda () (set! counter (add1 counter))))
           (= n counter))))

Or adapt that to your testing framework of choice (check-expect, rackunit, etc).

Ryan


On Thu, Dec 9, 2010 at 13:08, Ryan Culpepper <[email protected]
<mailto:[email protected]>> wrote:

    On 12/09/2010 11:51 AM, Luke Jordan wrote:

          Here's a rookie question that stems from HtDP 29.3.2.

        The idea is to test an expression a number of times while timing
        it and
        compare to another version of the same function.  The expression
        finds a
        route in a vector (graph) from node 0 to node 4.  The way I would do
        this in C/Python is with a while loop, while the counter is not zero
        execute the expression (ignore return value), and wrap it in the
        timer.
          In Racket I came up with:

        (time (for-each
                (lambda (dest) (find-route 0 dest Graph))
                (make-list 1000 4)))

        It seems unnecessarily tricky, but I couldn't think of a better
        way.  Am
        I missing a piece?  Does it only seem tricky because Racket is
        my first
        functional language.


    To the student of functional programming:

    You're right, it is unnecessary. You're using a list because you
    know someone has already provided "loop" functions for lists. But
    you just want to repeat an action N times---that's a natural number.
    Refresh yourself on Section 11 (Natural Numbers) and design this
    function:

    ;; do-times : Nat (-> Void) -> Void
    ;; Applies the given thunk N times.


    To the aspiring Racketeer:

    Racket has loop support for natural numbers, just not as a single
    function like 'for-each'. Look at 'for' and 'in-range'.

    Ryan


_________________________________________________
 For list-related administrative tasks:
 http://lists.racket-lang.org/listinfo/users

Reply via email to