Hacker News new | past | comments | ask | show | jobs | submit login

Actually on closer examination the bug was subtler than that. I did check whether the incoming request was allowed to modify each field it was trying to modify. But the code that decided whether a field was modifiable was using a four variable list to destructure on a five value description of the field. This caused the variable determining whether a field was modifiable to be bound instead to the value saying whether or not it should be displayed. Which meant every field that was displayed was modifiable.



That's actually pretty interesting to me. I didn't notice that when I was looking at the Hacker News code. Perhaps Arc shouldn't allow a list to be destructured except with a list of the same length? Allowing differing lengths seems likely to cause subtle bugs like this.


I generally tried to err on the side of flexibility, and it seemed more flexible not to require the lengths to match. I could imagine cases where you might want to use patterns both longer and shorter than the lists they were matched against. On the other hand, I'm not sure I've ever ended up taking advantage of this.


Maybe you could use something along the lines of &rest to optionally support a pattern shorter than the matched list?


You could do that with a dot now. The trouble is, you end up creating a junk variable:

    arc> (let (x . y) '(a b c) y)
    (b c)


Making users create junk variables seems to me like better behavior than the current implicit behavior. It's your decision, though, of course.

Anyway, is it safe to assume that you're not going to try to get me arrested or anything?


I feel like unnecessary variables are extra bad; in cognitive terms they feel like they add more than one token to the length of a program.

Do you mean your username is actually descriptive? Since you are obviously a Lisp hacker, I'd be happy to have a truce. Can you send me an email?


Thank you. I've sent you an email.


You don't have to name it. It could be _.

    (let (x . _) '(a b c) x)
It sounds like you're treating list destructuring like CL's mvbind. While it's subjective of course, I'm more comfortable with the runtime doing what I mean when I control the number of values (modulo `(apply values ...)').

I'm not comfortable with destructuring values "flexibly" when I don't control the data coming in.


Except "_" is a perfectly good name for a symbol in Arc.

"nil" could be used instead, since nil isn't allowed to be rebound.

  (let (x . nil) '(a b c) x)
even works already, since (unless it's been changed in some newer version of Arc I haven't installed yet) Arc just silently ignores the let-ing of nil:

  (let nil t nil) ---> nil


But at the same time this junk variable is code-as-documentation professing the incomplete destructuring is intentional.

You could go a step further and have a special ignore symbol, (for instance * ) like most pattern matching languages/libraries have with the property that it can appear multiple times:

  arc> (let (x * y . *) '(a b c d e f) y)
  c


For a language of my own design I'd agree, but I think that would be rather severely contrary to the spirit of Arc.


For all people who say good programmers don't make type errors, here's a counterexample.


It's an interesting question whether it's really a type error to mismatch the sizes of things. I feel like sometimes it is and sometimes it isn't.


In a strongly typed language one would normally want to reify the number in the type system whenever possible, i.e. the use of (a,b,c,d,e) rather than [a,b,c,d,e] in Haskell (that's a 5-tuple rather than a 5 element list).

I think that people used to dynamic programming languages would normally pick the list rather than the tuple simply because it at first appears easier. I think Dijkstra had something to say on that particular subject :)


Agreed. But it sounded like, in this case, you were using a list to represent that which would have been represented by a record in a statically typed language.

I'm imagining you'd have some kind of Field record type, with isDisplayable and isModifyable fields. Instead of destructuring as a list (or tuple), you would explicitly look for isDisplayable and isModifyable.

But, of course, you could still make the same mistake in a statically typed language if you chose not to set up the data structure this way.




Consider applying for YC's W25 batch! Applications are open till Nov 12.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: