Closed ziman closed 4 years ago
I think this is lovely, and a feature that has been occasionally requested but nobody has thought through how it would fit with the rest of the language until now. Thanks for doing it!
As far as I can see, the only thing that's incompatible with existing code is the requirement for an upper case letter at the start of a module name, which is a convention that people seem to use anyway. And we've kind of committed to the case of the initial letter having some meaning already anyway, so I'm not worried about that new requirement.
I'll leave this a little bit for any further comments, but I think I'm happy to merge if you think it's ready to go.
To be that person, once this PR has been merged then let's take @ziman original comment explaining the change and add it to the documentation!
Hmm, the test failure here is odd. Is it related to the recent patch to fix number display?
I have one more annoying request (sorry!) - please could you add the details to the CHANGELOG? Just to say record dot syntax is added is fine, I'll refine it later with a link to the docs. Not that that's stopping the merge, but I'd like to encourage the habit in everyone now that we've had a releaase :).
Oh dear, my occurs check fix broke the test output here. Let's see if I've fixed the conflicts successfully...
Apparently I didn't. I'm going to merge anyway and then push a fix. Thanks for your work on this!
Here's one way of doing it. I mostly wanted to hack up something to start a discussion from (and to toy with) so my choices are definitely not final or anything. But they seem to work together.
Discussion and suggestions on any aspect are welcome.
Overview
Long story short,
.field
is a postfix projection operator that binds tighter than function application.Lexical structure:
.foo
is a valid name, which stands for record fields (newName
constructorRF "foo"
)Foo.bar.baz
starting with uppercaseF
is one lexeme, a namespaced identifier:NSIdent ["baz", "bar", "Foo"]
foo.bar.baz
starting with lowercasef
is three lexemes:foo
,.bar
,.baz
.foo.bar.baz
is three lexemes:.foo
,.bar
,.baz
Constructor.field
, you have to write(Constructor).field
.New syntax of
simpleExpr
:Expressions binding tighter than application (
simpleExpr
), such as variables or parenthesised expressions, have been renamed tosimplerExpr
, and an extra layer of syntax has been inserted.(.foo)
is a name, so you can use it to e.g. define a function called.foo
(see.squared
below)(.foo.bar)
is a parenthesised expressionDesugaring rules
(.field1 .field2 .field3)
desugars to(\x => .field3 (.field2 (.field1 x)))
(simpleExpr .field1 .field2 .field3)
desugars to((.field .field2 .field3) simpleExpr)
Record elaboration
%undotted_record_projections
, which ison
by defaultf
of a recordR
, we get:f
in namespaceR
(exactly like now), unless%undotted_record_projections
isoff
.f
in namespaceR
with the same definitionExample code
This record creates two projections:
.x : Point -> Double
.y : Point -> Double
Because
%undotted_record_projections
areon
by default, we also get:x : Point -> Double
y : Point -> Double
To prevent cluttering the ordinary global name space with short identifiers, we can do this:
For
Rect
, we don't get the undotted projections:Let's define some constants:
User-defined projections work, too. (Should they?)
Finally, the examples:
Parses but does not typecheck: