4 ms·
This is a silly argument, of course de-sugaring language leads to a less nice type signature. C functions compiles down to assembly and C++ or Java hide vtables
by dtech 7y ago
This is a silly argument, of course de-sugaring language leads to a less nice type signature. C functions compiles down to assembly and C++ or Java hide vtables and such when you do method calls.
If you go lower in the abstraction level you get more complicated mechanics, and that says nothing over the validity of the high level semantics.
- fauigerzigerk 7y ago>C functions compiles down to assembly and C++ or Java hide vtables and such when you do method calls. I don't think it makes sense to compare the output of Rust macros to assembly code generated by a C compiler or to vtables. Macros are part of the Rust language, as is their output. Understanding Rust means understanding both input and output. So this abstraction boundary is intentionally leaky to some degree. Generated assembly and vtables on the other hand are compiler implementation details subject to change without notice. Any abstraction leakage is unintended and undesirable (even if developers sometimes benefit from understanding that output) Your line of reasoning makes all debates about language complexity completely pointless.
- likeliv 7y agoI disagree that the user of the macro needs to understand its output. The output of a macro is an implementation detail, and the documentation of the macro should be enough to use the macro without even looking at its output. For example, no need to understand the magic behind the 'quote!' or the #[async_trait] macros to use them.
- fauigerzigerk 7y agoNot every user has to understand every macro. But the output of a Rust macro is valid Rust code whereas the output of a C compiler is not valid C code. As a consequence, criticising the complexity of whatever a C compiler generates cannot possibly be valid criticism of C's complexity on a _semantic_ level whereas criticising the output of a Rust macro can be valid criticism of Rust on a semantic level.
- dtech 7y agoNearly all C compilers allow inline assembly. Macros are similar to inline assembly in that they step outside the normal bounds/use case of the language and are a complicated but valid and useful tool. Most C programmers won't have to write or understand inline assembly often, if ever. Of course you can encounter it in production problem or something, so you could make an argument that all C programmers need to understand "C with inline assembly", which you are making for Rust macros. As long as you just use Rust macro's and not write your own you are solidly in "C without inline assembly" territory.
- fauigerzigerk 7y ago>Nearly all C compilers allow inline assembly. Macros are similar to inline assembly in that they step outside the normal bounds/use case of the language and are a complicated but valid and useful tool. I couldn't disagree more. Macros are not similar to inline assembly at all precisely because they do _not_ step outside the bounds of the language. Whatever similarities you may find, it's simply not helpful to deny the fundamental distinction between language A generating code in language A and language A invoking/generating code in language B. It's futile to debate the properties of a particular language if you can't make a distinction between that language and anything it can generate or embed in some opaque way.
- dtech 7y agoWhat I fail to understand is why it's so important to you whether a pre-processing/compiler/de-sugaring of language A results in a valid snippet of language A or another language for complexity of language A. Take Objective-C automatic reference counting [1], implemented as a transformation of the original code to valid code of the same language (similar to a Lisp/Rust/Scala style macro) by automatically adding the appropriate statements. If I understand your argument correctly, according to you this increases the complexity of "Objective-C with ARC", but would not have done so if the compiler would have implemented it as a direct transformation to its compilation target instead. To me, that is an implementation detail which does not matter. "Objective-C with ARC" is exactly as complex in both cases. I'd argue it's even a little bit less complex with the "macro" implementation since you don't need to know assembly to know what ARC is doing. Similar to ARC, Rust implements some things with macro's, which first "compiles" something to valid Rust. To me this is not more difficult for users than it would be if the compiler would directly generate LLVM IR without this intermediate step. The inclusion of macro's in a language do make the language more complex of course! And creating macros is notoriously difficult since you're basically implementing a small compiler step! But for the user using something is not suddenly more difficult because it's implemented using a macro. [1] https://en.wikipedia.org/wiki/Automatic_Reference_Counting https://en.wikipedia.org/wiki/Automatic_Reference_Counting
- deleted 7y ago[deleted]