carbon-lang
carbon-lang copied to clipboard
Standard library and prelude naming
Short version: we should pick a scheme for naming things in the prelude of Carbon, and to a limited extent in the standard library more generally as they overlap. I'm suggesting the rough following scheme:
- The prelude works exactly as an import of one (or more) packages from the standard library.
- The prelude itself doesn't introduce aliases or other functionality.
- Everything imported by the prelude works just like a normally imported Carbon package, and the package name must be used to reference it.
- The prelude should at least cover the standard library types that are directly referenced, used, or connected to language constructs.
- Developers shouldn't need to import something to use language syntax, and language syntax shouldn't require the power to reference un-imported names.
- We provide keywords and literal syntaxes in the language that give brief syntax for the sufficiently common entities (regardless of what package-qualified name they otherwise need).
- This builds on #543 which suggests
bool
,i32
, and so on. - For example, a keyword
foo
might refer toSomePackageName.Foo
.
- This builds on #543 which suggests
This raises two more questions: what package names should the Carbon standard library use? (Or at least, the parts of the standard library we need to consider to establish what is in or not-in the prelude?) And how much of the standard library should be imported by the prelude?
For the first, after a bunch of thought, I'm being persuaded that Carbon's standard library shouldn't try to live in a single package, and the package names should -- to the extent possible -- be tied to the purpose or utility provided by that part of the standard library.
For example (but not suggested in this issue):
-
Math
package for things like the definition of π. -
Containers
package maybe for ... well ... containers - ...
I'd like to suggest that to start with, the only part of the standard library we put in the prelude are the parts of the standard library that are directly connected to the language itself: things like bool
as that's the return type of and
operators, all other types with dedicated syntax (i32
, etc), and interfaces used by language syntax like CommonType
and Add
.
Note that these wouldn't get any preferential syntax by being in the prelude with this suggestion, just be available without any explicit import.
My suggestion is that we have a single package that is only the constructs that directly interact with the syntax in some way as part of the prelude to start. We can expand this in the future if desired, but I think its a safe place to start. I think its reasonable for all of those constructs to be in one package, and the fact that they're part of the language itself helps suggest how to name that package. Some options seem especially appealing to me:
- a)
Core
, as in interacting with the core language. - b)
Base
, as in the base of the library dependency graph. - c)
Language
, due to being part of the language. - d)
Prelude
, as it is the contents of the prelude.
Of these, I like the idea of (c) best but I think it is a bit long. I like (a) more than (b), but that seems potentially just an aesthetic preference and not really based on anything. I'm not a huge fan of (d) because I worry about tying ourselves to never having other package names in the prelude.
So the net of this issue suggests that the prelude be an import of the Core
package, and nothing else, for now.
This package should at least contain:
- All the types we give dedicated language syntax:
bool
,iN
,uN
,fN
, pointer types, (potentially) array types, and any other types that have dedicated syntax or language construct affordances like pattern matching. - Interfaces and constraints used by syntax (
CommonType
stuff,Add
, etc.) - A
Print
function used when debugging code written in the language. - An
Assert
function, whenever we have a design for one, as it will likely be used by any contract or invariant language features added.
The package should not contain:
- Anything dependent on heap memory allocation (although it might include an allocation interface that is, for example, shareable between stack and heap allocations as stack allocations are part of the language).
- Hash maps, or other higher level containers, data structures, or algorithms.
- etc...
How do folks feel about this approach? (Marking it as an issue for leads to eventually resolve.)
Comment to collect reactions for the package name specifically Core
.
Comment to collect reactions for the package name specifically Base
.
Comment to collect reactions for the package name specifically Language
.
Comment to collect reactions for the package name specifically Prelude
.
My preference is actually multiple packages are imported automatically by the prelude, each of which has a more-specific name: Types
, Ops
My preference is actually multiple packages are imported automatically by the prelude, each of which has a more-specific name:
Types
,Ops
.
Hmmm, what would these packages contain? What would they not contain? Where would CommonType
go?
-
Types
would haveInt
,Float
, etc. -
Ops
would have interfaces likeAdd
,CommonType
, etc. -
Debug
would havePrint
,Assert
, maybe some constants describing the build mode
Where would Ptr
or whatever we are calling pointers go?
Where would
Ptr
or whatever we are calling pointers go?
I would put it in Types
.
What about Bootstrap
as a name for the parts that interact with the language instead of Core
or Base
? Disadvantage is a bit long, advantage is that it is very clearly part of a privileged low-level thing.
It surprises me a bit that we'd have multiple packages in the standard library, since it seems to contravene the rule of thumb that one git repo is one package. It also risks creating annoying taxonomy problems where we have to classify every library into exactly one package.
That said, if we are going to have multiple packages, it seems like a very appealing simplification to have one package that contains all of the prelude, and only the prelude. I can imagine that not working out, but it seems worth a try.
I think we shouldn't have the prelude boundary cut across package boundaries without a very compelling reason, because it will be harder to teach.
After taking some time to think about it, I'm not really opposed to splitting up even the language-supporting stuff into finer grained packages. But I'm not sure it adds a lot of value and so I'm left a bit ambivalent.
One specific observation:
Ops
would have interfaces likeAdd
,CommonType
, etc.
Ops.Add.Op
seems pretty awkward. And I worry this will come up as: x.(Ops.Add.Op)
.
I wonder if there is a bitter name for this specific case?
I wonder if there is a bitter name for this specific case?
Routines? Doesn't abbreviate well though.
What about Init
? It sounds just like Prelude
, but shorter. And unlike Core
and Base
it tells exactly what's happening - it's the very beginning.
"Init" sounds a lot more like it is about initialization.
What about Init? It sounds just like Prelude, but shorter. And unlike Core and Base it tells exactly what's happening - it's the very beginning.
On #2360 it's suggested that this issue will decide the design of Type
, in particular "At this time, that issue
is still open, but it might conclude that Type
is renamed Core.Type
, with a keyword alias type
."
bool
is another similar scenario, already mentioned. The title of this issue is currently "Standard library and prelude naming"; should it be renamed that this is not just about naming but will also get into details such as this?
Just wanted to say that the leads have gone through this in a reasonable amount of detail and we're all happy with the direction here, so closing this as decided.
Specifically:
- ✅ The guidelines in the original issue for what is and isn't included in the prelude.
- ✅ Using a single package for the prelude (for now).
- ✅ Naming that package
Core
.
We'll definitely need a proposal to update and fully define the design of the prelude here, but this should allow other proposals and provisional things (like the provisional parts of the design overview and examples that have never been through a proposal) to update their plans and code to reflect this.
I'll file a specific tracking issue to get the prelude itself defined and the core design updated.
On #2360 it's suggested that this issue will decide the design of
Type
, in particular "At this time, that issue is still open, but it might conclude thatType
is renamedCore.Type
, with a keyword aliastype
."
After some discussion, this issue should not pick a specific spelling for any of these or say how they work.
If we have a keyword though, it should be all lowercase.
If it is going to alias something in the prelude, that should be Core.SomeNameHere
.
But either #2360 or some other proposal or issue should sort out the exact spelling and how it is defined.
I'll update #2360 with some of the thoughts that came up in the discussion of this aspect.
bool
is another similar scenario, already mentioned. The title of this issue is currently "Standard library and prelude naming"; should it be renamed that this is not just about naming but will also get into details such as this?
Tried to update title to be a bit more encompassing. =] Hopefully its better, but we should also have a pretty clear proposal that hammers this out in the design too.