Life after D -- M for metaprogramming
Quote from Dave Voorhis on March 24, 2021, 9:26 amQuote from dandl on March 23, 2021, 11:07 pmThere's an argument that the desire for a macro language is always an indication that your host language isn't good enough. Anything you want a macro language to do, you should be able to do without macros as a "native" language facility.
Not so. The more common reason is that the language is powerful but verbose. Macros (as the name implied) let you get more done with less writing. They're also great for cross-cutting, like logging, asserts, test hooks, mocks, where you want what's included in the generated code to change according to settings.
Again, that's really only viable via transpilation -- where you're working in an entirely separate language -- not via macro generation, where you inevitably mix macro and native language, resulting in contradictory, potentially confusing, and potentially unsafe results. Macros get more done with less writing only up to the point where they cause more complexity and gotchas than they solve, at which point modern languages solve the same problems better with in-language features like genericity, more sophisticated type systems, and general in-language expressivity.
In short a good language shouldn't need macros to simplify code. Ordinary procedures/functions should be sufficient.
IMO it's trivially easy to come up with examples where that just isn't so. I've given a few already.
It's virtually true by definition. Every requirement for which a macro facility is a solution, is inherently a requirement for a (better) non-macro language feature.
For some (wrong/old) definition of 'macro'.
I'm using macro as a shorthand to refer to meta-programming, nothing more.
I've been using "macro" in precisely the way it is normally (and has always been, and still is) meant. As Antc helpfully pointed out, macro expansion is not the same thing as meta-programming or generic programming. Macro expansion means rule-based text conversion; sometimes language syntax-aware, often not. It is not semantics-aware, except (unusually) where semantics can be reliably inferred from syntax.
The only language in widespread use with simple text substitution macros is C (and inherited unchanged by C++). Macros were the only solution to a range of problems in the early 1970s. Some (but not all) of those problems have been solved in later languages by other means. Many have not.
My assertion is that there are problems for which the only reasonable solution is meta-programming (aka macros on steroids). Java has failed totally to realise this, C# does a little better, but neither of them offer any kind of user-written compile-time logic. Generics are just alternative implementations of the same code, and Java annotations/C# attributes are just metadata, not metaprogramming.
I quoted Powerflex to give a flavour of the power of compile-time logic, not because I want to go back to the 1980s, but because I want to bring macros into the 2020s.
I think macros -- per the usual definition -- are not what you want.
Except for purely-syntactic language x to language y text generation -- an example I gave was generating programming language code from configuration files, for which tools like M4 and ML/1 are often used -- macros are unsuited to implementing in-language semantic mechanisms. There are better approaches, which are integrated into the language and do not involve some external, exposed raw source text conversion.
Quote from dandl on March 23, 2021, 11:07 pmThere's an argument that the desire for a macro language is always an indication that your host language isn't good enough. Anything you want a macro language to do, you should be able to do without macros as a "native" language facility.
Not so. The more common reason is that the language is powerful but verbose. Macros (as the name implied) let you get more done with less writing. They're also great for cross-cutting, like logging, asserts, test hooks, mocks, where you want what's included in the generated code to change according to settings.
Again, that's really only viable via transpilation -- where you're working in an entirely separate language -- not via macro generation, where you inevitably mix macro and native language, resulting in contradictory, potentially confusing, and potentially unsafe results. Macros get more done with less writing only up to the point where they cause more complexity and gotchas than they solve, at which point modern languages solve the same problems better with in-language features like genericity, more sophisticated type systems, and general in-language expressivity.
In short a good language shouldn't need macros to simplify code. Ordinary procedures/functions should be sufficient.
IMO it's trivially easy to come up with examples where that just isn't so. I've given a few already.
It's virtually true by definition. Every requirement for which a macro facility is a solution, is inherently a requirement for a (better) non-macro language feature.
For some (wrong/old) definition of 'macro'.
I'm using macro as a shorthand to refer to meta-programming, nothing more.
I've been using "macro" in precisely the way it is normally (and has always been, and still is) meant. As Antc helpfully pointed out, macro expansion is not the same thing as meta-programming or generic programming. Macro expansion means rule-based text conversion; sometimes language syntax-aware, often not. It is not semantics-aware, except (unusually) where semantics can be reliably inferred from syntax.
The only language in widespread use with simple text substitution macros is C (and inherited unchanged by C++). Macros were the only solution to a range of problems in the early 1970s. Some (but not all) of those problems have been solved in later languages by other means. Many have not.
My assertion is that there are problems for which the only reasonable solution is meta-programming (aka macros on steroids). Java has failed totally to realise this, C# does a little better, but neither of them offer any kind of user-written compile-time logic. Generics are just alternative implementations of the same code, and Java annotations/C# attributes are just metadata, not metaprogramming.
I quoted Powerflex to give a flavour of the power of compile-time logic, not because I want to go back to the 1980s, but because I want to bring macros into the 2020s.
I think macros -- per the usual definition -- are not what you want.
Except for purely-syntactic language x to language y text generation -- an example I gave was generating programming language code from configuration files, for which tools like M4 and ML/1 are often used -- macros are unsuited to implementing in-language semantic mechanisms. There are better approaches, which are integrated into the language and do not involve some external, exposed raw source text conversion.
Quote from dandl on March 24, 2021, 10:12 amFor some (wrong/old) definition of 'macro'.
I'm using macro as a shorthand to refer to meta-programming, nothing more.
(Like Erwin, I'm barely bothering to follow these threads, but on a general point ...)
'Macro' vs 'meta-programming' vs 'generic programming' are not the same thing. (Though I'd take issue with some of each of those wikis.) Do not use abbreviations or 'shorthands' round here. If you're talking about meta-programming then use 'meta-programming'.
Actually, I was wrong and you're wronger. I'm using macro to refer to the topics covered by https://en.wikipedia.org/wiki/Macro_(computer_science). I'm clear in my mind that the input is text and the output is text, Java in this case. A competent programmer can see what is being done by examining the output source code, which is in all cases standard Java. I shall use the term macro to refer to this, as does Wikipedia.
The only language in widespread use with simple text substitution macros is C (and inherited unchanged by C++). Macros were the only solution to a range of problems in the early 1970s. Some (but not all) of those problems have been solved in later languages by other means. Many have not.
My assertion is that there are problems for which the only reasonable solution is meta-programming (aka macros on steroids). Java has failed totally to realise this, C# does a little better, but neither of them offer any kind of user-written compile-time logic. Generics are just alternative implementations of the same code, and Java annotations/C# attributes are just metadata, not metaprogramming.
I quoted Powerflex to give a flavour of the power of compile-time logic, not because I want to go back to the 1980s, but because I want to bring macros into the 2020s.
If you want to demonstrate compile-time logic, suggest you look at 'Dependent typing', and the commonalities with theorem-proving/programs correct by construction.
No, I really don't want to go there. This is code written by the programmer but executed during compilation to generate types and check for compliance.
Side-note: I had no idea PL/I had a macro language which was a subset of PL/I itself. Such prescience!
For some (wrong/old) definition of 'macro'.
I'm using macro as a shorthand to refer to meta-programming, nothing more.
(Like Erwin, I'm barely bothering to follow these threads, but on a general point ...)
'Macro' vs 'meta-programming' vs 'generic programming' are not the same thing. (Though I'd take issue with some of each of those wikis.) Do not use abbreviations or 'shorthands' round here. If you're talking about meta-programming then use 'meta-programming'.
Actually, I was wrong and you're wronger. I'm using macro to refer to the topics covered by https://en.wikipedia.org/wiki/Macro_(computer_science). I'm clear in my mind that the input is text and the output is text, Java in this case. A competent programmer can see what is being done by examining the output source code, which is in all cases standard Java. I shall use the term macro to refer to this, as does Wikipedia.
The only language in widespread use with simple text substitution macros is C (and inherited unchanged by C++). Macros were the only solution to a range of problems in the early 1970s. Some (but not all) of those problems have been solved in later languages by other means. Many have not.
My assertion is that there are problems for which the only reasonable solution is meta-programming (aka macros on steroids). Java has failed totally to realise this, C# does a little better, but neither of them offer any kind of user-written compile-time logic. Generics are just alternative implementations of the same code, and Java annotations/C# attributes are just metadata, not metaprogramming.
I quoted Powerflex to give a flavour of the power of compile-time logic, not because I want to go back to the 1980s, but because I want to bring macros into the 2020s.
If you want to demonstrate compile-time logic, suggest you look at 'Dependent typing', and the commonalities with theorem-proving/programs correct by construction.
No, I really don't want to go there. This is code written by the programmer but executed during compilation to generate types and check for compliance.
Side-note: I had no idea PL/I had a macro language which was a subset of PL/I itself. Such prescience!
Quote from dandl on March 24, 2021, 10:25 amogic, not because I want to go back to the 1980s, but because I want to bring macros into the 2020s.
I think macros -- per the usual definition -- are not what you want.
I think macros per the Wikipedia definition are exactly what I want.
Except for purely-syntactic language x to language y text generation -- an example I gave was generating programming language code from configuration files, for which tools like M4 and ML/1 are often used -- macros are unsuited to implementing in-language semantic mechanisms. There are better approaches, which are integrated into the language and do not involve some external, exposed raw source text conversion.
There is no such limitation. I do not propose to modify a Java (or C#) compiler or create a new language to compete with them. The M proposal is specifically about implementing language features similar to TTM by generating bog standard Java code that is guaranteed to be type-safe at runtime. And striking a blow for shorter-safer-higher.
Again:
- can you point to any attempts to design or implement modernised macros (say in the past 10-20 years) that have failed?
- can you point to any other language features with the prospect of making programs 10x shorter?
ogic, not because I want to go back to the 1980s, but because I want to bring macros into the 2020s.
I think macros -- per the usual definition -- are not what you want.
I think macros per the Wikipedia definition are exactly what I want.
Except for purely-syntactic language x to language y text generation -- an example I gave was generating programming language code from configuration files, for which tools like M4 and ML/1 are often used -- macros are unsuited to implementing in-language semantic mechanisms. There are better approaches, which are integrated into the language and do not involve some external, exposed raw source text conversion.
There is no such limitation. I do not propose to modify a Java (or C#) compiler or create a new language to compete with them. The M proposal is specifically about implementing language features similar to TTM by generating bog standard Java code that is guaranteed to be type-safe at runtime. And striking a blow for shorter-safer-higher.
Again:
- can you point to any attempts to design or implement modernised macros (say in the past 10-20 years) that have failed?
- can you point to any other language features with the prospect of making programs 10x shorter?
Quote from Dave Voorhis on March 24, 2021, 12:06 pmQuote from dandl on March 24, 2021, 10:12 amFor some (wrong/old) definition of 'macro'.
I'm using macro as a shorthand to refer to meta-programming, nothing more.
(Like Erwin, I'm barely bothering to follow these threads, but on a general point ...)
'Macro' vs 'meta-programming' vs 'generic programming' are not the same thing. (Though I'd take issue with some of each of those wikis.) Do not use abbreviations or 'shorthands' round here. If you're talking about meta-programming then use 'meta-programming'.
Actually, I was wrong and you're wronger. I'm using macro to refer to the topics covered by https://en.wikipedia.org/wiki/Macro_(computer_science). I'm clear in my mind that the input is text and the output is text, Java in this case. A competent programmer can see what is being done by examining the output source code, which is in all cases standard Java. I shall use the term macro to refer to this, as does Wikipedia.
The only language in widespread use with simple text substitution macros is C (and inherited unchanged by C++). Macros were the only solution to a range of problems in the early 1970s. Some (but not all) of those problems have been solved in later languages by other means. Many have not.
My assertion is that there are problems for which the only reasonable solution is meta-programming (aka macros on steroids). Java has failed totally to realise this, C# does a little better, but neither of them offer any kind of user-written compile-time logic. Generics are just alternative implementations of the same code, and Java annotations/C# attributes are just metadata, not metaprogramming.
I quoted Powerflex to give a flavour of the power of compile-time logic, not because I want to go back to the 1980s, but because I want to bring macros into the 2020s.
If you want to demonstrate compile-time logic, suggest you look at 'Dependent typing', and the commonalities with theorem-proving/programs correct by construction.
No, I really don't want to go there. This is code written by the programmer but executed during compilation to generate types and check for compliance.
That is the right way to do it, as it's fully safe. Mere macro text expansion is essentially like having an assistant write some code for you, but it leaves all the unsafety intact in the target language. If the text expansion generates all the text for you such that the generated code is essentially inaccessible (or, at least you never need to manipulate it) that's better, but macro expansion is generally insufficient to express it, as it uses simple rule-based string-search or AST-based expansion.
It also has no semantics -- and thus no checking -- beyond whatever is possible for string-search or AST-based expansion so all error checking winds up coming from the target language. That means you write in language x, but get almost all your error messages for (generated, and invisible) language y.
Instead, transpilation -- with both syntactic and semantic checking of the source language code -- is preferred, but as a subset of compilation, is well beyond the scope of macro systems.
Side-note: I had no idea PL/I had a macro language which was a subset of PL/I itself. Such prescience!
It's a very poor cousin to Lisp, whose macro language is no more or less than the entire Lisp in which it is used. That includes whatever functions the user has defined, with as much or as little semantic awareness as is needed.
The Lisp macro facility is almost completely beyond anything conceivable with conventional text-expansion macro capabilities in conventional languages. It's not really comparable to anything else.
Quote from dandl on March 24, 2021, 10:12 amFor some (wrong/old) definition of 'macro'.
I'm using macro as a shorthand to refer to meta-programming, nothing more.
(Like Erwin, I'm barely bothering to follow these threads, but on a general point ...)
'Macro' vs 'meta-programming' vs 'generic programming' are not the same thing. (Though I'd take issue with some of each of those wikis.) Do not use abbreviations or 'shorthands' round here. If you're talking about meta-programming then use 'meta-programming'.
Actually, I was wrong and you're wronger. I'm using macro to refer to the topics covered by https://en.wikipedia.org/wiki/Macro_(computer_science). I'm clear in my mind that the input is text and the output is text, Java in this case. A competent programmer can see what is being done by examining the output source code, which is in all cases standard Java. I shall use the term macro to refer to this, as does Wikipedia.
The only language in widespread use with simple text substitution macros is C (and inherited unchanged by C++). Macros were the only solution to a range of problems in the early 1970s. Some (but not all) of those problems have been solved in later languages by other means. Many have not.
My assertion is that there are problems for which the only reasonable solution is meta-programming (aka macros on steroids). Java has failed totally to realise this, C# does a little better, but neither of them offer any kind of user-written compile-time logic. Generics are just alternative implementations of the same code, and Java annotations/C# attributes are just metadata, not metaprogramming.
I quoted Powerflex to give a flavour of the power of compile-time logic, not because I want to go back to the 1980s, but because I want to bring macros into the 2020s.
If you want to demonstrate compile-time logic, suggest you look at 'Dependent typing', and the commonalities with theorem-proving/programs correct by construction.
No, I really don't want to go there. This is code written by the programmer but executed during compilation to generate types and check for compliance.
That is the right way to do it, as it's fully safe. Mere macro text expansion is essentially like having an assistant write some code for you, but it leaves all the unsafety intact in the target language. If the text expansion generates all the text for you such that the generated code is essentially inaccessible (or, at least you never need to manipulate it) that's better, but macro expansion is generally insufficient to express it, as it uses simple rule-based string-search or AST-based expansion.
It also has no semantics -- and thus no checking -- beyond whatever is possible for string-search or AST-based expansion so all error checking winds up coming from the target language. That means you write in language x, but get almost all your error messages for (generated, and invisible) language y.
Instead, transpilation -- with both syntactic and semantic checking of the source language code -- is preferred, but as a subset of compilation, is well beyond the scope of macro systems.
Side-note: I had no idea PL/I had a macro language which was a subset of PL/I itself. Such prescience!
It's a very poor cousin to Lisp, whose macro language is no more or less than the entire Lisp in which it is used. That includes whatever functions the user has defined, with as much or as little semantic awareness as is needed.
The Lisp macro facility is almost completely beyond anything conceivable with conventional text-expansion macro capabilities in conventional languages. It's not really comparable to anything else.
Quote from Dave Voorhis on March 24, 2021, 12:24 pmQuote from dandl on March 24, 2021, 10:25 amogic, not because I want to go back to the 1980s, but because I want to bring macros into the 2020s.
I think macros -- per the usual definition -- are not what you want.
I think macros per the Wikipedia definition are exactly what I want.
Except for purely-syntactic language x to language y text generation -- an example I gave was generating programming language code from configuration files, for which tools like M4 and ML/1 are often used -- macros are unsuited to implementing in-language semantic mechanisms. There are better approaches, which are integrated into the language and do not involve some external, exposed raw source text conversion.
There is no such limitation. I do not propose to modify a Java (or C#) compiler or create a new language to compete with them. The M proposal is specifically about implementing language features similar to TTM by generating bog standard Java code that is guaranteed to be type-safe at runtime. And striking a blow for shorter-safer-higher.
Again:
- can you point to any attempts to design or implement modernised macros (say in the past 10-20 years) that have failed?
- can you point to any other language features with the prospect of making programs 10x shorter?
What does "modernised macros" mean?
Text expansion macros haven't been considered viable since C, and they weren't a good idea there.
The intent of "modernised macros" is accomplished without text replacement macros at all. Instead, we have functions/procedures/classes/methods, lambdas, templates, and type systems.
For making programs 10x shorter, we write functions/procedures/methods and libraries of functions/procedures/classes/methods to do things we often need to do or might need to do in the future. Then we invoke functions/procedures/methods -- typically with a single line of code apiece -- but inside the function/procedure/method literally thousands and thousands of lines may be invoked.
If you can't make a program 10x shorter with a function/procedure/method, and can only do it with a text-replacement macro, then there's something wrong with the choice of language or how it's being used. In either case, solving it with a macro is like solving mechanical problem needing a small screwdriver with a big hammer.
Quote from dandl on March 24, 2021, 10:25 amogic, not because I want to go back to the 1980s, but because I want to bring macros into the 2020s.
I think macros -- per the usual definition -- are not what you want.
I think macros per the Wikipedia definition are exactly what I want.
Except for purely-syntactic language x to language y text generation -- an example I gave was generating programming language code from configuration files, for which tools like M4 and ML/1 are often used -- macros are unsuited to implementing in-language semantic mechanisms. There are better approaches, which are integrated into the language and do not involve some external, exposed raw source text conversion.
There is no such limitation. I do not propose to modify a Java (or C#) compiler or create a new language to compete with them. The M proposal is specifically about implementing language features similar to TTM by generating bog standard Java code that is guaranteed to be type-safe at runtime. And striking a blow for shorter-safer-higher.
Again:
- can you point to any attempts to design or implement modernised macros (say in the past 10-20 years) that have failed?
- can you point to any other language features with the prospect of making programs 10x shorter?
What does "modernised macros" mean?
Text expansion macros haven't been considered viable since C, and they weren't a good idea there.
The intent of "modernised macros" is accomplished without text replacement macros at all. Instead, we have functions/procedures/classes/methods, lambdas, templates, and type systems.
For making programs 10x shorter, we write functions/procedures/methods and libraries of functions/procedures/classes/methods to do things we often need to do or might need to do in the future. Then we invoke functions/procedures/methods -- typically with a single line of code apiece -- but inside the function/procedure/method literally thousands and thousands of lines may be invoked.
If you can't make a program 10x shorter with a function/procedure/method, and can only do it with a text-replacement macro, then there's something wrong with the choice of language or how it's being used. In either case, solving it with a macro is like solving mechanical problem needing a small screwdriver with a big hammer.