Hacker News new | ask | show | jobs
by bad_login 3396 days ago
"If I lied, you are allowed to insult me abundantly through your favorite channel."

Haha racket can here is how.

    #lang racket
    
    (define (foo a [methods empty])
      (let ([methods
             (append methods
                     (for/list ([i (range 3)])
                       (lambda (x) (+ x i))))])
        (for/sum ([m methods])
          (m a))))
    
    (foo 0)  ;; Should be 3
    (foo 1)  ;; Should be 6
    (foo 2)  ;; Should be 9
    (foo 2 (list (lambda (x) x)))  ;; Should be 11
    (foo 0)
    (foo 1)
    (foo 2)


    ;; Now the wrong way

    ;; The lambda capturing wrong
    (define (foo a [methods empty])
      (define i 0)
      (let ([methods
             (append methods
                     (for/list ([z (range 3)])
                       ;; modifying the variable i
                       (set! i z) 
                       (lambda (x) (+ x i))))])
        (for/sum ([m methods])
          (m a))))

    ;; this one doesn't do the default parameter wrong, because
    ;; methods and methods-default share an imutable list and we
    ;; modify only methods so beside "empty" they won't share the same
    ;; reference anymore, to get it wrong we should use a mutable list
    ;; (doesn't exist in racket).
    (define foo
      (let ([methods-default empty])
        (lambda (a [methods methods-default])
          ;; (printf "~a ~a\n" (length methods) (length methods-default))
          (define i 0)
          (for ([z (range 3)])
            (set! i z)
            (set! methods (cons (lambda (x) (+ x i))
                                        methods)))
          (for/sum ([m (append methods methods-default)])
          (m a)))))

    ;; So i use a box to make it mutable.
    (define foo
      (let ([methods-default (box empty)])
        (lambda (a [methods methods-default])
          ;; (printf "~a ~a\n" (length (unbox methods)) (length (unbox methods-default)))
          (define i 0)
          (for ([z (range 3)])
            (set! i z)
            ;; methods and methods-default share the same reference of box.
            (set-box! methods (cons (lambda (x) (+ x i))
                                    (unbox methods))))
          (for/sum ([m (unbox methods)])
            (m a)))))

The moral of the story, language design matter, immutable by default is good, lexical scoping is good, binding over variable is good, ruby, python, php and javascript (the languages the author mention) are bad in that regards.

One thing php, ruby, python (but not javascript) has good over racket their identatation tend to be flat and racket (let form, no return statement) tend to go all the way to the right.

1 comments

I'm glad I haven't been insulted yet