Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

syntactic marker for binding sites #219

Open
gelisam opened this issue Aug 5, 2023 · 0 comments
Open

syntactic marker for binding sites #219

gelisam opened this issue Aug 5, 2023 · 0 comments

Comments

@gelisam
Copy link
Owner

gelisam commented Aug 5, 2023

Can you spot the bug in the following code?

(defun sum (xs)
  (case xs
    [nil 0]
    [(:: x xs) (+ x (sum xs))]))
(example
  (the (-> (List Integer) Integer) sum))

The program type-checks but always returns zero, because the pattern for matching on the empty list is (nil), not nil. nil instead binds the list to a new identifier, nil, which shadows the (nil) data constructor.

I think this is very error-prone, not just for case, but in general: in a language in which a ton of custom macros use whatever syntax they want, it is easy to assume one syntax when the macro expects something else. For most of those mistakes, either the macro's parser will tell me that what I wrote is ill-formed, or the type-checker will tell me that what I wrote is ill-typed. But for this particular mistake, any identifier is well-formed and (if it isn't used in the body) well-typed, so the mistake is both common and not easily caught.

Thus, I propose to make most identifiers ill-formed, by using the convention (bind x) and the shorthand $x wherever identifiers are bound. For example:

(defun $sum ($xs)
  (case xs
    [nil 0]
    [(:: $x $xs) (+ x (sum xs))]))
(example
  (the (-> (List Integer) Integer) sum))

I know this is quite a sharp departure from traditional Scheme/Racket syntax. But remember, at the beginning of the project we were willing to experiment with bold syntactic choices, in order to improve over that conventional syntax! We tried using [] vs () to distinguishing between the places in a macro's syntax where an unlimited number of arguments is allowed, vs the places where a fixed number of arguments is allowed, e.g. [let ([x 0] [y 1]) [+ x y]]. We ended up deciding this was a mistake. I think we still have room for more experiments and mistakes :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant