Hacker News new | ask | show | jobs
by dang 1816 days ago
This is a bit silly, but ok, since you don't want to use HN as intended , we'll ban the account.

https://news.ycombinator.com/newsguidelines.html

1 comments

Hey Dan,

This is a bit unusual, but I wanted to let you know about a very strange Racket issue. I'm not sure if HN is still running on Racket or not, or if the CL port has finished. But...

For many years, HN has been running just fine with ac.scm looking like this:

  (define x-set-car!
    (let ((fn (namespace-variable-value 'set-car! #t (lambda () #f))))
      (if (procedure? fn)
          fn
          (lambda (p x)
            (if (pair? p)
                (unsafe-set-mcar! p x)
                (raise-type-error 'set-car! "pair" p))))))

  (define x-set-cdr!
    (let ((fn (namespace-variable-value 'set-cdr! #t (lambda () #f))))
      (if (procedure? fn)
          fn
          (lambda (p x)
            (if (pair? p)
                (unsafe-set-mcdr! p x)
                (raise-type-error 'set-cdr! "pair" p))))))

The only reason I know that, is thanks to Scott. It was one of the first tips he shared with me. Vanilla arc3.1 looks like this:

  (xdef scar (lambda (x val) 
                (if (string? x) 
                    (string-set! x 0 val)
                    (x-set-car! x val))
                val))

  (xdef scdr (lambda (x val) 
                (if (string? x)
                    (err "Can't set cdr of a string" x)
                    (x-set-cdr! x val))
                val))
which became unreliable years ago.

Scott explained that unsafe-set-mcar! was a bit of a hack, but that it worked due to a few assumptions about the code. I upgraded to this and never gave it a second thought.

Fast forward to a week or two ago. Arc kept throwing very strange errors. As far as I could tell, nothing whatsoever had changed.

But Racket had changed. The latest shipped version, for whatever reason, causes #<garbage> to be inserted to the `car` if you try to do (scar '(x y) '(a b))

(It took a long time to track that down...)

After poking around the racket source code, I noticed there was a function called unsafe-set-immutable-car!

On a whim, I tried switching unsafe-set-mcar! to unsafe-set-immutable-car! and everything worked perfectly.

I don't know why, or whether it's stable long term. But I wanted to let you know, in case someone on your team is running into strange Racket errors, that this is the fix:

  (define x-set-car!
    (let ((fn (namespace-variable-value 'set-car! #t (lambda () #f))))
      (if (procedure? fn)
          fn
          (lambda (p x)
            (if (pair? p)
                (unsafe-set-immutable-car! p x)
                (raise-type-error 'set-car! "pair" p))))))

  (define x-set-cdr!
    (let ((fn (namespace-variable-value 'set-cdr! #t (lambda () #f))))
      (if (procedure? fn)
          fn
          (lambda (p x)
            (if (pair? p)
                (unsafe-set-immutable-cdr! p x)
                (raise-type-error 'set-cdr! "pair" p))))))

I hope that saves someone a little bit of time.

Thanks for taking care of the troll. (And the HN API, and a thousand other things.) Best of luck.