Arc Forumnew | comments | leaders | submitlogin
1 point by rkts 6020 days ago | link | parent

Yep. I wouldn't call it elegant, but it works.

I feel like there ought to be a better way to do this--something that's less complex but handles more cases. In particular I'd like to be able to alternate OO and pattern-matching styles on the same datatypes. However, I haven't been able to come up with a solution that really satisfies me.

One other thing: wouldn't it be better to raise an error when an invariant is violated, instead of returning nil?



1 point by absz 6020 days ago | link

You can use OO structure-access semantics with tagged unions: (tu 'slot-name) and (= (tu 'slot-name) new-value). That's not the interesting part of OO, of course :)

I thought about returning an error, but Arc seems to be a little calmer about such things: (is (car nil) (cdr nil) nil), for instance. Of course, (car 'sym) errors. ::shrug:: I'm not sure about this, and it might change.

-----

3 points by rkts 6020 days ago | link

The purpose of a type system is to help find errors by failing early instead of letting bugs propagate through a system and show up in mysterious ways. Right now, you're actually making debugging harder because you're just wrapping bugs inside other bugs. Instead of figuring out why his binary tree turned into a cheeseburger, a programmer now has to determine (a) why his binary tree is nil (or why mutating it seems to have no effect), (b) which invariant he violated, and (c) what error caused the invariant to be violated.

Regarding (car nil) and (cdr nil), these return nil because it's sometimes convenient. For instance, here's a function that collects every other item in a list:

  (def foo (xs)
    (if xs
      (cons car.xs (foo cddr.xs))))
If (cdr nil) raised an error, we would have to check the cdr before we could recur:

  (def foo (xs)
    (if xs
      (cons car.xs (if cdr.xs (foo cddr.xs)))))
Not a huge difference, obviously, but a difference nevertheless. I can't see any comparable reason to return nil in your case.

-----

1 point by absz 6020 days ago | link

Fair enough, you've convinced me.

EDIT: Creation, reading (defcall), and writing (sref) all give errors if invariants are violated/nonexistent keys are accessed. Is there anything I missed?

-----