shakeshuck
shakeshuck

Reputation: 125

Struggling to think Functionally in Racket

I always have problems thinking functionally and here is a typical example.

(define tally_table (make-hash))

(define (process-each-line)
    (define actual_percent 5)
    (define new_record (list 0))
    (define add_record (list 1))
    (define (tally-records hash_value to-be-added)
      (map (lambda (number1 number2)
        (+ number1 number2)) hash_value to-be-added))
    (if (hash-has-key? tally_table actual_percent)
      (let* ([hash_value (hash-ref tally_table actual_percent)])
        hash-set! tally_table actual_percent (tally-records hash_value add_record)
      )
      (hash-set! tally_table actual_percent new_record)
    )
)

What I expected the code to do was add a new value to an empty hash table the first time run (which it does), then add to the hash table value on successive runs (which it doesn't - instead it returns a list of '(1) and the hash table value remains the same). I'm guessing it might be to do with the scope of let*, but I'm certainly confused as to why the two sides of 'if' (appear to) behave differently.

Upvotes: 0

Views: 58

Answers (1)

Sorawee Porncharoenwase
Sorawee Porncharoenwase

Reputation: 6502

You want to make a function call, but you missed parentheses around hash-set! in the "then" branch of if. Parentheses is the syntax for function call. Since you missed it, it doesn't perform function call.

To compare it with other languages like JS, instead of writing f(x, y, z), you are (roughly) writing:

f;
x;
y;
return z;

In this case, it evaluates hash-set!, ..., (tally-records hash_value add_record), and returns the evaluation result of (tally-records hash_value add_record).

FYI, there's a function hash-update! which does both hash-set! and hash-ref at the same time, and it could also deal with when hash-has-key? returns #f, too. That means you don't need that if expression at all. You could just write this instead:

(hash-update! tally-table actual-percent
              (λ (current-value) (tally-records current-value add-record))
              new-record)

EDITED: with hash-update!, tally-records will be applied when hash-has-key? is #f too. You probably need to adjust the value of new-record to preserve the existing behavior. Alternatively, just use the regular if that you had before.

Upvotes: 1

Related Questions