Some ideas and best wishes. #1572
Replies: 3 comments 5 replies
-
I moved this to our discussion forum as it seems to fit better there than as a single issue. Thanks for all your interest, some thoughts inline from me at least.
Generally agree about prioritizing readability. We try to look at this carefully with each part of the design. Of course, sometimes we end up with different solutions, but we're definitely looking at readabality. If you spot specific things in the design that still end up with a significant readability issue, definitely flag them in issues.
Not sure why We use We are definitely looking at different keyboard layouts (especially in different geographies and languages) when considering what symbols to use.
I feel like this conflates two things. We're definitely trying to have introducer keywords to make it unambiguous what construct is being entered at any point. Whether to rigidly structure things in a outside-in or inside-out or other things I think depends more on the individual. Different people learn things differently. We're trying to strike a reasonable compromise of building up the design description systematically, but if you have a concrete suggestion to change the structure, you could make that? We also have a few C++ trainers / teachers / instructors in the community that are likely to be heavily involved in shaping any user-guides we end up with. But it's much too early for user-facing documentation. =] Still early design days.
I think our design docs do this, but if you spot things missing, you can flag those with issues.
Our plan is to rely on tool-assisted upgrade strategies to make sure we can bring users along with updates to the language.
We're definitely thinking about this, and have tooling's importance both in our goals and in design discussions.
Yep, this is also in our goals.
We're definitely thinking a lot about metaprogramming and how to expose that. I think similarly to what you're mentioning, we want to strike a balance. Too much metaprogramming of things that should be core features of the language makes it harder to learn and harder to build tooling for the language. But it remains an important use case, and one we'll definitely invest in.
We definitely plan to have a rich semantic representation specifically for Carbon, and will use that for upgrade tooling and other kinds of tooling. We're not going to reuse the C++ AST itself, we'll have our own representation. Many folks working on Carbon have worked on Clang which uses its rich C++ AST for many of the things you mention. =]
Definitely trying to avoid surprise.
All things being equal, we do like to use clean keywords that easy to read and as you mention search for. There are still times and places where the visual density of punctuation is important, but we think carefully about the tradeoff each time. |
Beta Was this translation helpful? Give feedback.
-
On my phone, these are rendered as → and ⇔: maybe the comment is about using a standard ascii set in the language? I generally support this, though e.g. I do like how haskell allows for unicode characters in variable names
I don't agree that a language should "rely heavily on IDE". Rather, I think it is more important to have strong tooling that supported/maintained by the language team. e.g. linter, formatter, LSP implementation. If done correctly, it should be relatively easy for any given IDE to integrate this tooling for a great experience (for those that prefer using an IDE). As an extreme example, I personally was put off from learning Agda because it seemed compulsory to use emacs. This was a few years ago, so things might have changed, but the point stands - I don't think it will help with adoption to force users into an IDE if they prefer a different workflow. |
Beta Was this translation helpful? Give feedback.
-
The best way to go about 6 would be to provide a language server like clang does with clangd. The language server can then be used by plug-in developers to provide language support to editors (ex. https://marketplace.visualstudio.com/items?itemName=llvm-vs-code-extensions.vscode-clangd) |
Beta Was this translation helpful? Give feedback.
-
I just came from https://isocpp.org/blog/2022/07/an-experimental-successor-to-cpp
I also have some personal preference for a modern programming language. Here are some of my ideas.
1, Always readable.
function foo(return type)(param list)(other flags such as const and static and nodiscard){code}
is more readable than:
[[nodiscard]]auto foo(int a, int b)const{code}
lambda(=)(auto e){code}
is more readable than:
[](auto e){code}
int[] vec;
is more readable than:
int vec[];
This readability enhancement works both for human and compiler. After a function keyword, only a function can be parsed. If no valid function is parsed, the compiling error can come with a link to a tutorial page.
2, Somewhat easy to write with a main stream keyboard.
def, var, std, cast, -=, ==, // are easy to write.
->, <=>, are not easy to write.
Easier to write means people can write slightly longer with less time. This also may contribute to readability.
3, Always Dedicated Scope.
As mentioned in the 1, a function definition always starts with the keyword function. Lambda expressions start with lambda, variable definitions start with var or anything you prefer.
The top default scope accepts only namespace keyword. Then nested namespace or class or functions. In this way, the tutorial is possible to cover every detail in this language. Otherwise people have to search a lot in youtube and stackoverflow. You should not rely on the community to provide enough tutorial.
An example, in class scope, it's not possible to write any math definition, so
some_name * other_name;
is always a variable definition. No need to add a typename keyword or class keyword in front of it.
If the nesting relationship is like:
namespace
-variable
-function
-class
--function inside class
--variable inside class
The tutorial can also be organized in this way. It's possible for people to systematically learn the language.
4, Always tell the reason you design a feature and how it is supposed to be used in the documentations.
Don't force people to guess.
5, Never encourage the combination of features.
Enforce people to do everything with feature and grammar as simple and plain as possible. Or you are heading to a blackhole where you have to invent a lot new feature to handle all the intersections from different subsystem when they combine. Also, less content means faster and easier to learn.
You can tell people, the plain code is guaranteed to work for at least 3 years or 10 years, while the fancy code is not guaranteed at all. If it works, it works, if it doesn't, it doesn't. This simplifies the job you are gonna do when you try upgrading Carbon. You don't have to study the super fancy situation and care that much. This reduce legacy. Things like crtp are completely gone. Or at least you didn't promise.
6, Rely heavily on IDE.
Add specification for IDE in the language specification. IDE is definitely at least half of a language. Ask the IDE providers to provide super powerful intellisence.
Also, when you design the language, consider how the IDE can help.
7, This language should not be new comer friendly that much.
They already have python and js and probably are very happy with these languages.
8, Optional idea, maybe harmful: let people script for the compiler to control how to compile.
Since constexpr is a thing, people keep struggling with this. Also, a lot language feature are added to help people move jobs to compile time as much. But this extra keyword works pretty similar to macro works in modern c++. But if people have directly control to the compiler, this can be specified with plain code, but the code is for the compiler to run rather to be packed into the output execution file.
Typescript are also making similar mistakes. They added specific keywords to help people deal with super narrow case. This leads to hidden features which are hard for people to find or systematically learn.
Some examples:
Case1:
In UE4, we have to add some macros like
class SomeClass{
GENERATED_DEFINATION()
and then all the code}
But with another layer to control how the code is compile, it can be done like:
{compile_scirpt:
SomeClass.add_member_variable(type::int, L"GCIndex", Compile_Script::variable_appending_style::default);
SomeClass.add_member_variable(type::UE4Editor::DebugHook, L"EngineHook", Compile_Script::variable_appending_style::default);
some_common_function.foreach(SomeClass.add_function(...))
Also, this compile_scirpt thing separates c++20concepts and constrains from instruction code which may bring more readability.
}
//Then, outside the compile_scirpt segment, it's plain instruction code.
class SomeClass{
//GENERATED_DEFINATION() macro is not needed anymore.
and then all the code}
This idea may also helps the UPROPERTY like macro. Emm, This example isn't very good.
Case2:
This compiling script structure also helps with readability and reduce a lot guesswork(which sucks so hard)
Example:
//inside a class
static inline consteval [[nodiscard]][[some_other_flag]]auto foo()const{}
vs
function foo(){}
{compile_scirpt: foo.return("auto").static(true).inline(true).supress_inline_fail_warning(false).const(true).nodiscard(true).some_other_flag(true);}
The advantage is that, the sequence is very casual. People can write it in any prefered sequence. But people can't write:
[[nodiscard]][[some_other_flag]]auto foo()const{}inline static consteval
This also helps with CUDA code.
global void cudafoo(){}
vs
void cudafoo(){}
{compile_scirpt: cudafoo.cuda_global()}
This example is not very good since I can't remember all the flags. But you can do improve it.
Case3:
Accessibility of members. Now we have public, private, protected, friend to control the accessibility. But if we can script for the compiler, we can do anything. I personally don't like this c++accessibility feature, it's literally a macro.
An example is:
{compile_scirpt: AllClass.foreach(function(auto c){
if(c.has_tag("Engine")||c.has_tag("Editor")){
c.add_access(Actor);
}
}}
Super convenient.
9, Rich AST and what it can do.
This idea is optional. But maybe it's the most important, I mean, the top one.
I didn't learn the language, I've absolutely no idea of how it's made. I appologize for this.
I guess Carbon is like:
Carbon grammar >>> ast >>> machine code.
The first step is what this language about. The second step can utilize the good old job people already have done in c++.
But I would like to mention some "rich"ast.
The first thing it can do for us is automatically codebase upgrade. For now, most of the codebase auto upgrade scripts do the character level replacement which is very limited. But if the ast is rich enough, it's possible to generate the human readable code from ast. Then, if some upgrade script is done for the ast, it's possible to upgrade the codebase like:
old code >>> ast in old version >>> ast in new version >>> new code.
In fact, in the same version , code and ast have to chance to generate mutually, if the ast is rich enough. Then all the magic can only be done with the ast. All the intellisence, all the black magic can be done only with the ast.
If codebase can always be upgraded automatically, or almost can, then we can do crazy break upgraded frequently. It's 2022, abi break every 9 years is too slow. Like playing online games with a ping of 2 hours.
The second thing rich ast can do for us, is, emmm, do you still remember languages like scratch2, blueprint in ue4, or any other non-text-based language? Rich ast is probably a great interface for all these techs. Maybe one day, people decide to make some GUI version for Carbon, maybe node base, maybe scratch2-like, if the interface compacts directly to rich ast, it's possible to generate the whole thing into text and edit with some text based IDE. While some other IDE may provide both text and GUI editor for Carbon.
Also, if some other people decide to invent their grammar, then different language can share the same rich ast and translates automatically in any direction. This can lead to a boom, people can choose from them. This speeds up the evolution of programming languages.
The third, the most important reason, is some scifi possibility.
Since Neuralink has a chance to really invent some production level BCI, people may one day edit the ast directly. If we don't need any text or GUI to interact with computer, we can do this literally. This can speed us up like several times I guess, or even dozens or hundreds of times.
10, I don't know how to write this title..
If we have 4 possible grammar to cover 3 features, consider them separately, don't arrange.
I didn't remember, the example is from go lang. They have 3 grammars to cover the by-copy and by-ref, and they arranged. This force people to memorize. Also this bring SURPRISE, which is bad.
11, Always perfer keywords rather than ()[]{}<>~&*|
It's easier to google. Literally.
If someone doesn't know lambda expression in c++, how would s/he search for the info on google? S/he has to describe what's in there, like, "what is square brackets followed by parenthesis and curly braces with some code inside it in c++". If google recognises it, it's good. But this is usually not possible for non-English speakers. I'm Chinese, this case happened to me so many times and it was so painful.
This also leads to the idea always start a scope with keywords rather than symbols, except for some most classic and simple ones.
Not everyone can use English well enough. Please make their lives easier. I really appreciate.
Yeah, thank you for your time. I hope this helps.
Beta Was this translation helpful? Give feedback.
All reactions