CPY – Code C/C++ with no redundancy
github.com
github.com
The problem with (essentially) replacing the C/C++ syntax with a more lightweight (pythonic) one was already mentioned here in the threads: There will be a lot of corner cases which the CPY compiler does not understand.
In my impression, most of the redundancy in the C world comes from the header/code seperation, i.e. all the signatures are repeated. Another level of redundancy was added by C++ templates where one quickly needs to write lengthy expressions, but the newer C++ standards resolved much of that thanks to the "auto a = b" type keyword or the "use X = Y" definitions.
Note that "CPY" addresses none of these issues.
This problem is avoided at no cost in Go, where an external tool can be used to get the same concise view of all of the function types that you like, without needing to manually create and update header files.
Most of my work these days is in JavaScript (Node).
I agree it is annoying to write, but I find well documented headers to be more usable than the other environments, if the project is large enough that I cannot read everything.
For deduced types you can do
auto a = 10;
auto b = a;
And not have to mess with known.For multiple return types you can do structured binding and make_tuple.
auto [a,b] = func();
Where func is auto func(){return std::make_tuple(1.5, 3);}
Using a loop, you can use boost::irange for(auto i: irange(0,10)){
For the output stuff, you can use fmt (https://github.com/fmtlib/fmt/blob/master/README.rst) which is on track for standardization. fmt::print("{} {} {} ", a,b,c);
Overall most of the problems that CPY implies have pretty good solutions in C++ without the pain of another pre-processorI don't like decisions like implicit << and >> for cin, cout. Too much magic for me.
(cout "hello") confuses the hell out of those with some C++ experience. It changes semantics if a known object for little gain (cout is callable, a statement)? Like someone else said, a "printout" new statement or function would be better.
It's the kind of things that makes me question the design of the whole language.
Don't think that one is actually needed, simple static analysis should be able to tell one variable is just an alias of another -- which (presumably) they already do to figure out the variable types.
The reasoning behind it is also kind of confusing, used to tell the preprocessor the variable is in local scope as opposed to...?
--edit--
Or maybe it's used for class local variables?
Problem solved (at least partially) in other languages by requesting the `this` or `self` to be explicitly mentioned.
# t.def
page: t, basic_frame
module: c
a=10
b=a
$dump a, b
$ mydef_run t.def
PAGE: t
--> [./t.c]
gcc -std=c99 -O2 -o./t ./t.c && ./t
:a=10, b=10
I didn't introduce `known` keyword. If I want straight C code passthrough I simply append semicolons.MyDef is a general preprocessor, so I need the page and module declarations to tell what file and types I am generating. It always shows the command it actually runs, so there is no magic. And it does not pretend to replace C. It always produces `.c` file for debugging or merging with existing workflow.
As long as MyDef is strictly preprocessor, it is purely complementary. If you prefer straight C/C++ at places, just use straight C. If you have questions on what MyDef syntax does, just read the C output.
It does pose some restrictions on the C I write. I do not write long statements in multiple lines and rely on my editor to softwrap the lines. Long lines are difficult to read anyway with or without splitting and soft-wrapped lines are not much difficult to read anyway. I often can avoid long lines by refactoring. In rare cases that lines still end up too long, I leave it as is to remind me that it needs further work.
Sometimes I need import third-party raw c code during a progress of refactoring or code digesting. MyDef has template construct to quote them directly.
MyDef: https://github.com/hzhou/MyDef output_c: https://github.com/hzhou/output_c
I, like everyone else who has the need, wound up writing my own C++ preprocessor. I think there is a lot of merit to the idea of having a low level base language which is machine independent and using a high level syntactic sugar over it.
What I am hoping for is conversation. With conversation, I can have the motivation for documentation and others can understand and the barrier may dissolve.
I am a firm believer that the compiler should do as much work as possible, no matter the time it takes. I think the compiler ought to generate default pretty printers for structs and unions on its own, that may be overridden. Same for serialization formats and so on. The C++ compiler has more than enough information to make programmers lives more convenient at no added runtime expense, and I would be very willing to eat the compile time cost.
I wound up having to write my own preprocessor for C++ to automatically generate structure metadata for an embedded application. I wish there was more of a push for general preprocessors in this direction.
// CPY loop to iterate from a down to b, c at a time
for i a b -c
// For comparison: pure C++11 and boost
for(auto i : irange(a, b, -c))
After CPY removes redundancy to this extent, sure there's still enough information for a compiler to parse this, but there's not enough information for me to parse this. Remember that you spend a lot more time reading code than pressing buttons on the keyboard, so the number of characters you need to type is pretty irrelevant to your productivity.Maybe I'm getting too caught up on the name, which suggests a Python-like experience, which CPY definitely not. If anything it is less like Python than C++! Sure it has the indentation vs braces thing, but that is probably one of the least important reasons why Python is so readable. A more important reason is the excellent visual cues in the syntax, and forcing you to spell things out e.g. with named parameters; "explicit is better than implicit". CPY seems to strip out visual cues, as shown above, by its four print functions that are cryptically called !, !!, ? and ??, and by the fact that it's even harder to spot function declarations in CPY than in C++.
In c++17 you can sort of do that but you still have to unpack the whole tuple (and the caller has to make one instead of simply doing ‘return a, b, c;’ to return three values. I understand why the C++ committee didn’t make this change (it would break valid programs, though there are likely few to none of them).
return {1, "42", '2'};
seems like a fair trade-off to me. Btw, this is already implemented from c++11.
1. Act as a preprocessing step for any existing C++ file
2. Output perfectly servicable C++ in the case where you want to move away.
Additions like the "known" keyword make this look badly thought out.
In any case, the weakness of C++ in most cases is compilation speed, not typing speed. Even in the ideal case I can't see this adding more value than it detracts (preprocessing speed + buildsystem complication + extra dependency).
I'm probably a minority in the C++ world, partially because I don't have a powerful IDE, but I tend to write everything in .h and only split it out later on, which gets annoying.
It is in fact able to output perfectly servicable C++ code by simply using a flag (-ex)
CPY also helps with the compilation speed problem by doing a makefile-like compilation, were it only recompiles edited parts of the code.
It can also be used upon complete c++ projects and it would only actually execute the compilation step.
- Pure functional style (Haskell subset that is usable from C++)
- GC'd higher level gluing code (calls C++ but maybe not necessarily callable from it)
Am sure others are more qualified for suggestions, but I imagine other subsets like some for interfacing with representing relational data querying, different concurrency models (like Go, Erlang...)
Is this a sane suggestion?
Was it ever widely uses? I was glad we did it and am glad to see that someone appreciated it!
I.e. nesting information is repeatedly encoded into every line. Nope, no redundancy here, move along!
I’m not sure I agree that the input is more readable, but good nonetheless.
If I had the choice, I’d move the syntax closer to Haskell do-notation than Python, but that’s just me.