digitalmars.D.learn - correct way to create boiler plate code
- dmerrio (40/40) May 16 2011 I am parsing some formulas from a spreadsheet file. To duplicate
- Trass3r (2/6) May 16 2011 That's because funcs is mutable.
- dmerrio (14/14) May 16 2011 changing the relevent code, changes the error, but it still does
- Timon Gehr (15/32) May 16 2011 foreach runs at runtime, while mixin is expanded at compile time.
- Trass3r (9/10) May 16 2011 Not the whole truth though.
- Kai Meyer (25/65) May 16 2011 This works:
- dmerrio (2/2) May 16 2011 Thank you for the reply. Potential, but there still seems to be
- bearophile (9/26) May 16 2011 Mine is not an answer that directly helps you solve your problem. Experi...
- dmerrio (10/36) May 16 2011 Thanks for the formatting tips. Copy and pasting kind of messed up
I am parsing some formulas from a spreadsheet file. To duplicate the behavior of the spreadsheet functions, I am having to create a lot of boiler plate code that maps from the spreadsheet functions to the built-in functions. Mixin would seem to allow me to automate the boiler-plate creation, but i am not utilizing it correctly. What is the correct to call Mixin in this situation, or is their a better way to create the boiler-plate code? For background, i am new to D. D is my second language with my primary experience being a script kiddie in Excel VBA, so take it slow, please. import main; //class definition of rng import std.math; //trig functions import std.conv; //to!double import std.string; //toupper double transFunc(alias transedentalFunc)(rng aRng){ try{return(transedentalFunc(aRng.getCellValue().coerce! (double)));} //cellValue stored as a Variant catch{return(transedentalFunc(to!double(aRng.getCellValue ().coerce!(string))));} //replicate spreadsheet behavior and convert to a number } //Example 1 of boilerplate code double SIN(double aReal){return(sin(aReal));} double SIN(string aStr){return(sin(to!double(aStr)));} double SIN(rng aRng){return(transFunc!(sin)(aRng));} //Example 2 of boilerplate code double COS(double aReal){return(cos(aReal));} double COS(string aStr){return(cos(to!double(aStr)));} double COS(rng aRng){return(transFunc!(cos)(aRng));} string[] funcs = ["tan"]; void createFuncs(){ foreach(func; funcs){ mixin("double " ~ toupper(func) ~ "(double aReal) {return(" ~ func ~ "(aReal));}"); } } calling mixin a compile time has the following error... Error 1 Error: variable func cannot be read at compile time C:\D\SVNProjects\trunk\xcellD\xcell1\trig.d 22 thanks for your help
May 16 2011
string[] funcs = ["tan"];calling mixin a compile time has the following error... Error 1 Error: variable func cannot be read at compile time C:\D\SVNProjects\trunk\xcellD\xcell1\trig.d 22That's because funcs is mutable. Try to make it immutable or enum.
May 16 2011
changing the relevent code, changes the error, but it still does not compile... immutable funcs = ["tan"]; void createFuncs(){ foreach(func; funcs){ mixin("double " ~ toupper(func) ~ "(double aReal) {return(" ~ func ~ "(aReal));}"); } } new error... Error 1 Error: argument to mixin must be a string, not ("double TAN(double aReal){return(" ~ func ~ "(aReal));}") C:\D\SVNProjects\trunk\xcellD\xcell1\trig.d 24 Thanks for the suggestion, any others????
May 16 2011
I am parsing some formulas from a spreadsheet file. To duplicate the behavior of the spreadsheet functions, I am having to create a lot of boiler plate code that maps from the spreadsheet functions to the built-in functions. Mixin would seem to allow me to automate the boiler-plate creation, but i am not utilizing it correctly. What is the correct to call Mixin in this situation, or is their a better way to create the boiler-plate code? For background, i am new to D. D is my second language with my primary experience being a script kiddie in Excel VBA, so take it slow, please.hi, Disregard the other answer, making func immutable won't solve your problem.string[] funcs = ["tan"]; void createFuncs(){ foreach(func; funcs){ mixin("double " ~ toupper(func) ~ "(double aReal) {return(" ~ func ~ "(aReal));}"); } }foreach runs at runtime, while mixin is expanded at compile time. If you want to inject your boilerplate into module namespace, you would rather write a function that generates the code and mixin the result of a call to that function: string[] funcs = ["tan"]; string createFuncs(){ string res; foreach(func; funcs){ res~="double " ~ toupper(func) ~ "(double aReal){return(" ~ func ~ "(aReal));}"; } return res; } mixin(createFuncs());
May 16 2011
foreach runs at runtime, while mixin is expanded at compile time.Not the whole truth though. foreach over tuples gets unrolled at compile time so you can do stuff like: // +=, -=, ... Vector opOpAssign(string op, U)(U s) { foreach (i, _; tuple) mixin("tuple[i] " ~ op ~ "= s;"); return this; }
May 16 2011
On 05/16/2011 01:08 PM, dmerrio wrote:I am parsing some formulas from a spreadsheet file. To duplicate the behavior of the spreadsheet functions, I am having to create a lot of boiler plate code that maps from the spreadsheet functions to the built-in functions. Mixin would seem to allow me to automate the boiler-plate creation, but i am not utilizing it correctly. What is the correct to call Mixin in this situation, or is their a better way to create the boiler-plate code? For background, i am new to D. D is my second language with my primary experience being a script kiddie in Excel VBA, so take it slow, please. import main; //class definition of rng import std.math; //trig functions import std.conv; //to!double import std.string; //toupper double transFunc(alias transedentalFunc)(rng aRng){ try{return(transedentalFunc(aRng.getCellValue().coerce! (double)));} //cellValue stored as a Variant catch{return(transedentalFunc(to!double(aRng.getCellValue ().coerce!(string))));} //replicate spreadsheet behavior and convert to a number } //Example 1 of boilerplate code double SIN(double aReal){return(sin(aReal));} double SIN(string aStr){return(sin(to!double(aStr)));} double SIN(rng aRng){return(transFunc!(sin)(aRng));} //Example 2 of boilerplate code double COS(double aReal){return(cos(aReal));} double COS(string aStr){return(cos(to!double(aStr)));} double COS(rng aRng){return(transFunc!(cos)(aRng));} string[] funcs = ["tan"]; void createFuncs(){ foreach(func; funcs){ mixin("double " ~ toupper(func) ~ "(double aReal) {return(" ~ func ~ "(aReal));}"); } } calling mixin a compile time has the following error... Error 1 Error: variable func cannot be read at compile time C:\D\SVNProjects\trunk\xcellD\xcell1\trig.d 22 thanks for your helpThis works: //import main; //class definition of rng import std.math; //trig functions import std.conv; //to!double import std.string; //toupper import std.stdio; void main() { mixin(createFunc!("sin")); mixin(createFunc!("cos")); mixin(createFunc!("tan")); writeln(SIN(0)); // 0 writeln(COS(0)); // 1 writeln(TAN(0)); // 0 return; } template createFunc(string func){ const char[] createFunc = "double " ~ toupper(func) ~ "(double aReal) {return(" ~ func ~ "(aReal));}"; } Stole it from http://www.digitalmars.com/d/2.0/mixin.html I don't think there's a way to use an array of strings, since (as pointed out by others and your error message) that mixins are done compile-time and foreach are done (mostly) at run-time.
May 16 2011
Thank you for the reply. Potential, but there still seems to be alot of repetitive code.
May 16 2011
dmerrio:import main; //class definition of rng import std.math; //trig functions import std.conv; //to!double import std.string; //toupper double transFunc(alias transedentalFunc)(rng aRng){ try{return(transedentalFunc(aRng.getCellValue().coerce! (double)));} //cellValue stored as a Variant catch{return(transedentalFunc(to!double(aRng.getCellValue ().coerce!(string))));} //replicate spreadsheet behavior and convert to a number } //Example 1 of boilerplate code double SIN(double aReal){return(sin(aReal));} double SIN(string aStr){return(sin(to!double(aStr)));} double SIN(rng aRng){return(transFunc!(sin)(aRng));}Mine is not an answer that directly helps you solve your problem. Experience shows that messy code doesn't help you see your problems, and sometimes it even hides bugs. So I suggest you to reformat your code in a more human way, use more normal naming conventions, and use named imports if you want to import just some names. This means writing: import std.conv: to; Instead of: import std.conv; //to!double To put a newline before the closing brace, to add spaces and newlines where they are belong, and so on. This helps a lot. Bye, bearophile
May 16 2011
Thanks for the formatting tips. Copy and pasting kind of messed up the formatting, not that it was good to start with. I am still developing a coding style. == Quote from bearophile (bearophileHUGS lycos.com)'s articledmerrio:problem. Experience shows that messy code doesn't help you see your problems, and sometimes it even hides bugs. So I suggest you to reformat your code in a more human way, use more normal naming conventions, and use named imports if you want to import just some names.import main; //class definition of rng import std.math; //trig functions import std.conv; //to!double import std.string; //toupper double transFunc(alias transedentalFunc)(rng aRng){ try{return(transedentalFunc(aRng.getCellValue().coerce! (double)));} //cellValue stored as a Variant catch{return(transedentalFunc(to!double(aRng.getCellValue ().coerce!(string))));} //replicate spreadsheet behavior and convert to a number } //Example 1 of boilerplate code double SIN(double aReal){return(sin(aReal));} double SIN(string aStr){return(sin(to!double(aStr)));} double SIN(rng aRng){return(transFunc!(sin)(aRng));}Mine is not an answer that directly helps you solve yourThis means writing: import std.conv: to; Instead of: import std.conv; //to!double To put a newline before the closing brace, to add spaces andnewlines where they are belong, and so on. This helps a lot.Bye, bearophile
May 16 2011