digitalmars.D - More than one main
- bearophile (44/44) Mar 24 2011 I have discussed this is little problem about three years ago; in the me...
- spir (17/58) Mar 24 2011 I support finding a solution for this issue. Very annoying esp. during
- Jacob Carlborg (4/91) Mar 24 2011 Doesn't rdmd have an option to add a main function?
- Kagamin (2/4) Mar 24 2011 unittests should be able to be a demo code for the module. Sometimes the...
- bearophile (12/17) Mar 24 2011 The linker probably has zero knowledge of what a "first module" is.
- Kagamin (8/14) Mar 24 2011 you can switch on version matching the module name, or something similar...
- bearophile (5/13) Mar 24 2011 I have explained Walter why that's not good:
- Kagamin (2/5) Mar 24 2011 Specific tasks are done with specific tools. If such a tool is adopted t...
- Jonathan M Davis (16/88) Mar 24 2011 I had _never_ heard of anyone ever even sugesting that something like th...
- Walter Bright (12/24) Mar 24 2011 Yes, there is. It's the one that defines main().
- bearophile (7/21) Mar 24 2011 It's very common in well designed Python modules. Probably you don't see...
- Walter Bright (3/8) Mar 24 2011 rdmd takes command line switches, which you can use to set the version f...
- bearophile (21/23) Mar 24 2011 You are missing the point still, I was talking about a single standard v...
- Jonathan M Davis (7/16) Mar 24 2011 I really don't understand what you're trying to do with a module "demo."...
I have discussed this is little problem about three years ago; in the meantime the situation is changed (rdmd has appeared, DMD has grown the -deps switch, etc). I have a little module named "modu": module modu; import std.stdio; int foo() { return 0; } int main() { writeln("modu.main"); return 1; } I create a second module named "somemodule", and import just the foo() function from mod: module somemodule; import std.stdio; import modu: foo; int main() { writeln("somemodule.main"); return foo(); } Now if I compile somemodule normally, with: rdmd somemodule.d I receive an error like: OPTLINK (R) for Win32 Release 8.00.12 Copyright (C) Digital Mars 1989-2010 All rights reserved. http://www.digitalmars.com/ctg/optlink.html ... Offset 00137H Record Type 00C3 Error 1: Previous Definition Different : __Dmain --- errorlevel 1 To avoid this problem in Python there is a common idiom: if __name__ == '__main__': This idiom allows to define and run a "main" only for the main module. Currently in D there is no notion of "main module", but I see a simple way to avoid this problem in D too, defining a new standard version name that tools like rdmd, bud, etc define for just the first module (like for the only module name given to rdmd), and don't define for all other modules found and compiled recursively: module mod; int foo() { return 0; } version (main_module) int main() { return 1; } The usage of main_module is optional. I like to keep a main() in most modules, even the ones that are usually not supposed to be the main modules of a program, because I put in their main() some demo code that shows what this module does (and a main is useful to run unittests too, rdmd has the --main switch for this). Most of my Python modules have such demo main code, that runs only if you run them as main modules. Bye, bearophile
Mar 24 2011
On 03/24/2011 12:07 PM, bearophile wrote:I have discussed this is little problem about three years ago; in the meantime the situation is changed (rdmd has appeared, DMD has grown the -deps switch, etc). I have a little module named "modu": module modu; import std.stdio; int foo() { return 0; } int main() { writeln("modu.main"); return 1; } I create a second module named "somemodule", and import just the foo() function from mod: module somemodule; import std.stdio; import modu: foo; int main() { writeln("somemodule.main"); return foo(); } Now if I compile somemodule normally, with: rdmd somemodule.d I receive an error like: OPTLINK (R) for Win32 Release 8.00.12 Copyright (C) Digital Mars 1989-2010 All rights reserved. http://www.digitalmars.com/ctg/optlink.html ... Offset 00137H Record Type 00C3 Error 1: Previous Definition Different : __Dmain --- errorlevel 1 To avoid this problem in Python there is a common idiom: if __name__ == '__main__': This idiom allows to define and run a "main" only for the main module. Currently in D there is no notion of "main module", but I see a simple way to avoid this problem in D too, defining a new standard version name that tools like rdmd, bud, etc define for just the first module (like for the only module name given to rdmd), and don't define for all other modules found and compiled recursively: module mod; int foo() { return 0; } version (main_module) int main() { return 1; } The usage of main_module is optional. I like to keep a main() in most modules, even the ones that are usually not supposed to be the main modules of a program, because I put in their main() some demo code that shows what this module does (and a main is useful to run unittests too, rdmd has the --main switch for this). Most of my Python modules have such demo main code, that runs only if you run them as main modules.I support finding a solution for this issue. Very annoying esp. during development since running unittests on a module, or set of modules, requires a main() func. But the module(s) one needs to run the unittests of are not always (conceptualy) the main app's module; there may even be none, if it's a lib. So, we need stupidly need to add a fake & empty main() func -- that will later generate linking error when building the whole app ;-) But I do not like your solution, which i find uselessly complicated. In order of preference: * the linker automatically adds an empty main() to the first module if needed * allow empty main() in every module, more than one beeing just ignored * your solution Denis -- _________________ vita es estrany spir.wikidot.com
Mar 24 2011
On 2011-03-24 14:05, spir wrote:On 03/24/2011 12:07 PM, bearophile wrote:Doesn't rdmd have an option to add a main function? -- /Jacob CarlborgI have discussed this is little problem about three years ago; in the meantime the situation is changed (rdmd has appeared, DMD has grown the -deps switch, etc). I have a little module named "modu": module modu; import std.stdio; int foo() { return 0; } int main() { writeln("modu.main"); return 1; } I create a second module named "somemodule", and import just the foo() function from mod: module somemodule; import std.stdio; import modu: foo; int main() { writeln("somemodule.main"); return foo(); } Now if I compile somemodule normally, with: rdmd somemodule.d I receive an error like: OPTLINK (R) for Win32 Release 8.00.12 Copyright (C) Digital Mars 1989-2010 All rights reserved. http://www.digitalmars.com/ctg/optlink.html ... Offset 00137H Record Type 00C3 Error 1: Previous Definition Different : __Dmain --- errorlevel 1 To avoid this problem in Python there is a common idiom: if __name__ == '__main__': This idiom allows to define and run a "main" only for the main module. Currently in D there is no notion of "main module", but I see a simple way to avoid this problem in D too, defining a new standard version name that tools like rdmd, bud, etc define for just the first module (like for the only module name given to rdmd), and don't define for all other modules found and compiled recursively: module mod; int foo() { return 0; } version (main_module) int main() { return 1; } The usage of main_module is optional. I like to keep a main() in most modules, even the ones that are usually not supposed to be the main modules of a program, because I put in their main() some demo code that shows what this module does (and a main is useful to run unittests too, rdmd has the --main switch for this). Most of my Python modules have such demo main code, that runs only if you run them as main modules.I support finding a solution for this issue. Very annoying esp. during development since running unittests on a module, or set of modules, requires a main() func. But the module(s) one needs to run the unittests of are not always (conceptualy) the main app's module; there may even be none, if it's a lib. So, we need stupidly need to add a fake & empty main() func -- that will later generate linking error when building the whole app ;-) But I do not like your solution, which i find uselessly complicated. In order of preference: * the linker automatically adds an empty main() to the first module if needed * allow empty main() in every module, more than one beeing just ignored * your solution Denis
Mar 24 2011
bearophile Wrote:I put in their main() some demo code that shows what this module does (and a main is useful to run unittests too, rdmd has the --main switch for this). Most of my Python modules have such demo main code, that runs only if you run them as main modules.unittests should be able to be a demo code for the module. Sometimes they say that unittests do demonstrate, how the module should work.
Mar 24 2011
spir:Very annoying esp. during development since running unittests on a module, or set of modules, requires a main() func.<This is not so bad, because rdmd has a --main switch.* the linker automatically adds an empty main() to the first module if needed<The linker probably has zero knowledge of what a "first module" is.* allow empty main() in every module, more than one beeing just ignored<I don't need just empty mains, I need demo code in them. ------------------------------ Jacob Carlborg:Doesn't rdmd have an option to add a main function?Right, I have said it in my original post too. ------------------------------ Kagamin:unittests should be able to be a demo code for the module. Sometimes they say that unittests do demonstrate, how the module should work.<For me the code inside unittests and the demo code inside the main (and the functions called just by the main) have different purposes. A demo may open a GUI, interact on the command line with the user, allow the module to be used stand alone with some kind of little interface, show graphs on the screen, etc. While unittests are mostly to test the module is working correctly and they are not supposed to be interactive or to be show graphs, etc. One my real example: in a module that plots functions on the screen, in the main I generate and show some function plots to the user. This is not done in unittests. Bye, bearophile
Mar 24 2011
bearophile Wrote:Kagamin:you can switch on version matching the module name, or something similar that will be easy to switch in a makefile. module modu; version(modu) void main() { //... }unittests should be able to be a demo code for the module. Sometimes they say that unittests do demonstrate, how the module should work.<For me the code inside unittests and the demo code inside the main (and the functions called just by the main) have different purposes. A demo may open a GUI, interact on the command line with the user, allow the module to be used stand alone with some kind of little interface, show graphs on the screen, etc. While unittests are mostly to test the module is working correctly and they are not supposed to be interactive or to be show graphs, etc. One my real example: in a module that plots functions on the screen, in the main I generate and show some function plots to the user. This is not done in unittests.
Mar 24 2011
Kagamin:you can switch on version matching the module name, or something similar that will be easy to switch in a makefile. module modu; version(modu) void main() { //... }I have explained Walter why that's not good: http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D&article_id=132693 Bye, bearophile
Mar 24 2011
bearophile Wrote:I have explained Walter why that's not good: http://www.digitalmars.com/webnews/newsgroups.php?art_group=digitalmars.D&article_id=132693Specific tasks are done with specific tools. If such a tool is adopted there will be no discrepancy.
Mar 24 2011
I have discussed this is little problem about three years ago; in the meantime the situation is changed (rdmd has appeared, DMD has grown the -deps switch, etc). I have a little module named "modu": module modu; import std.stdio; int foo() { return 0; } int main() { writeln("modu.main"); return 1; } I create a second module named "somemodule", and import just the foo() function from mod: module somemodule; import std.stdio; import modu: foo; int main() { writeln("somemodule.main"); return foo(); } Now if I compile somemodule normally, with: rdmd somemodule.d I receive an error like: OPTLINK (R) for Win32 Release 8.00.12 Copyright (C) Digital Mars 1989-2010 All rights reserved. http://www.digitalmars.com/ctg/optlink.html ... Offset 00137H Record Type 00C3 Error 1: Previous Definition Different : __Dmain --- errorlevel 1 To avoid this problem in Python there is a common idiom: if __name__ == '__main__': This idiom allows to define and run a "main" only for the main module. Currently in D there is no notion of "main module", but I see a simple way to avoid this problem in D too, defining a new standard version name that tools like rdmd, bud, etc define for just the first module (like for the only module name given to rdmd), and don't define for all other modules found and compiled recursively: module mod; int foo() { return 0; } version (main_module) int main() { return 1; } The usage of main_module is optional. I like to keep a main() in most modules, even the ones that are usually not supposed to be the main modules of a program, because I put in their main() some demo code that shows what this module does (and a main is useful to run unittests too, rdmd has the --main switch for this). Most of my Python modules have such demo main code, that runs only if you run them as main modules.I had _never_ heard of anyone ever even sugesting that something like this was an issue until reading about Python. Typically, you have modules which contain code which is called and may or may not be specific to any program, and then you have a module which contains main and _is_ specific to that program. If you want a different program, you just create a new module with a main in it and compile that new program. You don't typically treat modules as runnable in any real sense. They just contain related code. So, honestly, I don't see this as an issue at all. If you _do_ consider to be an issue (as you appear to), then you can just have a function which you put in all of your modules which runs whatever you want to run for that module. Then you just write quick program which calls that module's run function and there you go. But honestly, what you're trying to do just strikes me as plain weird. Maybe it's a typical thing to do in scripting languages, but it definitely isn't in compiled languages. - Jonathan M Davis
Mar 24 2011
On 3/24/2011 4:07 AM, bearophile wrote:I receive an error like: OPTLINK (R) for Win32 Release 8.00.12 Copyright (C) Digital Mars 1989-2010 All rights reserved. http://www.digitalmars.com/ctg/optlink.html ... Offset 00137H Record Type 00C3 Error 1: Previous Definition Different : __Dmain --- errorlevel 1No mystery there. You have two main()'s. There can be only one.Currently in D there is no notion of "main module",Yes, there is. It's the one that defines main().I like to keep a main() in most modules, even the ones that are usually not supposed to be the main modules of a program, because I put in their main() some demo code that shows what this module does (and a main is useful to run unittests too, rdmd has the --main switch for this). Most of my Python modules have such demo main code, that runs only if you run them as main modules.That's what the version statement is for: version (My_Demo) { void main() { ... } } There's no reason to add more features to duplicate that.
Mar 24 2011
Jonathan M Davis:But honestly, what you're trying to do just strikes me as plain weird. Maybe it's a typical thing to do in scripting languages, but it definitely isn't in compiled languages.It's very common in well designed Python modules. Probably you don't see it in compiled languages like C/C++ because they don't have a good module system. D has modules related to Python ones, so I am using this Python idiom in D too. Most D1 modules of dlibs1 have demo code :-) --------------------------- Walter:That's what the version statement is for: version (My_Demo) { void main() { ... } } There's no reason to add more features to duplicate that.I too have suggested to use the version() statement, but My_Demo is not a _standard_ version generated automatically by tools like rdmd. In a project you usually use many modules, and some of them have demo code in their main. If you use rdmd or similar tools, you want only one of those mains to be compiled, the right one. Bye, bearophile
Mar 24 2011
On 3/24/2011 11:47 AM, bearophile wrote:I too have suggested to use the version() statement, but My_Demo is not a _standard_ version generated automatically by tools like rdmd. In a project you usually use many modules, and some of them have demo code in their main. If you use rdmd or similar tools, you want only one of those mains to be compiled, the right one.rdmd takes command line switches, which you can use to set the version for which main you want.
Mar 24 2011
Walter:rdmd takes command line switches, which you can use to set the version for which main you want.You are missing the point still, I was talking about a single standard version that works in all cases. Here is an example. I have a project (program) P, it contains many modules, its main is inside the module M. Among the modules used by P there are the general-purpose modules A, B, C, D. The modules B and C and D contain a main with demo code. The module A imports the module B, and the module D important C and a less commonly useful module E that has no main and no demo. Now I want to compile the program P with a helper, so it has to compile the main contained inside M. I use: rdmd --build-only M.d rdmd defined a version named like main_module for just the module M.d, so only its main gets compiled. Later I want to try the demos inside A, I use: rdmd A.d Now main_module is defined only for the module A.d and it's not defined inside the module B that A has required rdmd to compile. So only the main of A.d gets compiled. If I use a single My_Demo inside every module M, A, B, C, D, and I give: rdmd -version=My_Demo --build-only M.d Then all mains are visible and the linker gives the error. Similar things happen if I use this, because both the main of A and B are active: rdmd -version=My_Demo A.d If I use a different version for each module, like My_Demo_A inside A.d, My_Demo_B inside B.d, etc, I then later have to compile the code like this: rdmd -version=My_Demo_M --build-only M.d rdmd -version=My_Demo_A A.d This works, but is not as handy as what I have asked. And I have stressed the word _standard_ because a version like My_Demo_M becomes a convention just of my code, while my point was the usefulness of a standard that's supposed to work with other build tools too, etc, so if I take some D modules from another person I don't later have to use all different version names like: rdmd -version=My_NiceDemo_foo foo_bar.d A standard solution avoids this. Bye, bearophile
Mar 24 2011
Jonathan M Davis:I really don't understand what you're trying to do with a module "demo." The unit tests test the code in the module. They also provide examples on how to use the code in the module. Also, well-written modules have good examples in their documentation (which is generally tested in the unit tests as well). What is a module demo supposed to achieve that good unit tests and documentation don't? - Jonathan M DavisBut honestly, what you're trying to do just strikes me as plain weird. Maybe it's a typical thing to do in scripting languages, but it definitely isn't in compiled languages.It's very common in well designed Python modules. Probably you don't see it in compiled languages like C/C++ because they don't have a good module system. D has modules related to Python ones, so I am using this Python idiom in D too. Most D1 modules of dlibs1 have demo code :-)
Mar 24 2011