Fennel's got a problem with identifiers.
Our multisym rules are strange and inconsistent with regards to special
characters. For example, consider the multisym `foo.&`.
```fnl
(local foo {:& 10})
(print foo.&) ;; valid,
(set foo.& 10) ;; syntax error, & is apparently not allowed here
```
Intsead of being inconsistent about whether & is allowed, we should
allow multisyms that have & in their tail. Specifically, the rules
I'm suggesting for multisyms are:
* The "head" of a multisym has to be a valid identifier.
* The "tail" pieces of a multisym have to be valid `:shorthand` strings.
This means that, for example, `foo.&`, `foo.#`, `foo.a&b`, `foo.\`, and
`foo.0123.4567` are valid multisyms, as "foo" is a valid identifier,
and `:&`, `:#`, `:a&b`, `:\`, `:0123`, and `:4567` are valid shorthand
strings.
To change fennel to match this proposal, we would just need to change
the code to allow leading digits in the tail, and make (set) not
complain about `&` in the tail.
We also need to discuss symbols that end in `.`. Right now, symbols like
`foo.bar.` or `$...` are valid identifiers (and aren't multisyms).
Whenever there's a dot at the end, it tricks fennel into skipping the
multisym checks. I think the intent is to reserve symbols like `.`,
`..`, `...`, and `?.`, but it covers far more than it should.
I think the easiest way to solve this is to start treating `foo.bar.`
as a multisym. (breaking change!! but probably doesn't effect much)
Ie, `foo.bar.` parses as `(. foo :bar.)`. Also, we'd need to add `$...`
to the special case list.
What are other people's thoughts on this?
XeroOl
XeroOl <xerool@protonmail.com> writes:
> Intsead of being inconsistent about whether & is allowed, we should
> allow multisyms that have & in their tail. Specifically, the rules
> I'm suggesting for multisyms are:
>
> * The "head" of a multisym has to be a valid identifier.
> * The "tail" pieces of a multisym have to be valid `:shorthand` strings.
Thanks for bringing this up. I think this is probably the simplest rule set
we could make that accurately describe how most Fennel is written today,
so I believe it's worth nailing this down in the docs and aligning the
implementation to be consistent with it, with the one caveat below.
> We also need to discuss symbols that end in `.`. Right now, symbols like
> `foo.bar.` or `$...` are valid identifiers (and aren't multisyms).
> Whenever there's a dot at the end, it tricks fennel into skipping the
> multisym checks. I think the intent is to reserve symbols like `.`,
> `..`, `...`, and `?.`, but it covers far more than it should.
>
> I think the easiest way to solve this is to start treating `foo.bar.`
> as a multisym. (breaking change!! but probably doesn't effect much)
> Ie, `foo.bar.` parses as `(. foo :bar.)`.
Indeed this is technically a breaking change, but I tried it across all
the codebases in the Fennel Anthology[1] and it didn't cause any
problems. I consider it a bug that this gets treated just like a normal
sym right now.
I agree that treating `foo.bar.` as `(. foo :bar.)` would be an
improvement over what we have today. However, I think we should also
consider making `foo.bar.` a compiler error since it's not clear at a
glance what the right behavior is there, and `:bar.` is a very strange
key to use in a table that's unlikely anyone would ever use except
by accident.
But I'm kind of on the fence; I don't feel strongly either way and would
like to hear what others think about it.
-Phil
1 - https://git.sr.ht/~technomancy/fennel-anthology