www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Entry (main) method inside a class?

reply Dejan Lekic <dejan.lekic gmail.com> writes:
Is there particular reason why we are not able to have entry (main) method
inside a class, like is possible in JAVA for an example?
Even though I am not a big JAVA fan, I must say I like that feature... :)

Kind regards

Dejan
Mar 16 2007
next sibling parent reply Frits van Bommel <fvbommel REMwOVExCAPSs.nl> writes:
Dejan Lekic wrote:
 Is there particular reason why we are not able to have entry (main) method
inside a class, like is possible in JAVA for an example?
 Even though I am not a big JAVA fan, I must say I like that feature... :)
AFAIK the only reason Java has that "feature" is its complete inability to have functions *outside* of classes :). Though I could see uses for this, like to run unittests (similarly to what running Python modules "stand-alone" often does). D has gone another way there though, using explicit unittest {} blocks. Unfortunately, there is currently no way to run these separately (esp. right after compilation) that I know of.
Mar 16 2007
next sibling parent reply Benji Smith <dlanguage benjismith.net> writes:
Frits van Bommel wrote:
 Dejan Lekic wrote:
 Is there particular reason why we are not able to have entry (main) 
 method inside a class, like is possible in JAVA for an example?
 Even though I am not a big JAVA fan, I must say I like that feature... :)
AFAIK the only reason Java has that "feature" is its complete inability to have functions *outside* of classes :). Though I could see uses for this, like to run unittests (similarly to what running Python modules "stand-alone" often does). D has gone another way there though, using explicit unittest {} blocks. Unfortunately, there is currently no way to run these separately (esp. right after compilation) that I know of.
It can be convenient to package up a JAR file with multiple executable classes. Then you can run multiple different applications with the same binary just by passing a different app name on the commandline. It doesn't really apply to D, though. Without a runtime classloader, it doesn't make any sense to have a single EXE with multiple entry points. --benji
Mar 16 2007
parent reply Frits van Bommel <fvbommel REMwOVExCAPSs.nl> writes:
Benji Smith wrote:
 Frits van Bommel wrote:
 Dejan Lekic wrote:
 Is there particular reason why we are not able to have entry (main) 
 method inside a class, like is possible in JAVA for an example?
 Even though I am not a big JAVA fan, I must say I like that 
 feature... :)
[snip]
 It can be convenient to package up a JAR file with multiple executable 
 classes. Then you can run multiple different applications with the same 
 binary just by passing a different app name on the commandline.
 
 It doesn't really apply to D, though. Without a runtime classloader, it 
 doesn't make any sense to have a single EXE with multiple entry points.
I can think of several programs on my system that change their behavior depending on the value of argv[0]... Though perhaps not multiple entry points, that check + symlinks probably gets pretty close for compiled programs. Or you could use dynamic libraries (OS-native or DDL) together with small executables that load those libraries, saving you from having multiple versions of the shared code. Combining the techniques, I could even see a program that just loads argv[0] ~ ".so", looks up "void run()" in it and calls it. Then even the loader code is shared... However, the first technique doesn't work on Windows because it lacks symlinks (to files, at least). Though a few batch files that all run the same executable, each with a different --version=whatever (or some such) would look similar to the user.
Mar 16 2007
parent reply Manfred Nowak <svv1999 hotmail.com> writes:
Frits van Bommel wrote

 However, the first technique doesn't work on Windows because it
 lacks symlinks (to files, at least).
XP supports hard links. -manfred
Mar 16 2007
parent Daniel Keep <daniel.keep.lists gmail.com> writes:
Manfred Nowak wrote:
 Frits van Bommel wrote
 
 However, the first technique doesn't work on Windows because it
 lacks symlinks (to files, at least).
XP supports hard links. -manfred
Yeah, but they suck. You need to download a third-party tool to use them, for starters. Secondly, almost nothing written for Windows even knows about them, not even *Explorer*, so it's impossible to tell if something is a link or not. And of course, they can't span drives. I'm fairly sure that one version of Windows could only hard-link folders, but not files. Not sure if that was 2k or XP. I once planned on using hard links to make migrating stuff between drives easier. Obviously I couldn't do that, but what really scared me was when I realised that deleting the link deleted the original as well; I just backed away slowly, avoiding eye contact. Vista has, I believe, *proper* symlinks... but then I'm moving to Linux before I touch Vista with a 50ft barge pole, so I don't care :) -- Daniel -- Unlike Knuth, I have neither proven or tried the above; it may not even make sense. v2sw5+8Yhw5ln4+5pr6OFPma8u6+7Lw4Tm6+7l6+7D i28a2Xs3MSr2e4/6+7t4TNSMb6HTOp5en5g6RAHCP http://hackerkey.com/
Mar 16 2007
prev sibling parent reply Thomas Kuehne <thomas-dloop kuehne.cn> writes:
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Frits van Bommel schrieb am 2007-03-16:
 Dejan Lekic wrote:
 Is there particular reason why we are not able to have entry (main) method
inside a class, like is possible in JAVA for an example?
 Even though I am not a big JAVA fan, I must say I like that feature... :)
AFAIK the only reason Java has that "feature" is its complete inability to have functions *outside* of classes :). Though I could see uses for this, like to run unittests (similarly to what running Python modules "stand-alone" often does). D has gone another way there though, using explicit unittest {} blocks. Unfortunately, there is currently no way to run these separately (esp. right after compilation) that I know of.
Flectioned's unittest walker does exactly that: dmd -unittest -g -c <your source> dmd flectioned.d unittest_walker.d -ofwhatever <your objects> ./whatever http://flectioned.kuehne.cn Thomas -----BEGIN PGP SIGNATURE----- iD8DBQFF+9PRLK5blCcjpWoRAoiGAJ91UUkumd3LfoFb771S1Z/Y42ADowCfaqqT JN5WpxZdThF7LTl906mSs04= =R0ZY -----END PGP SIGNATURE-----
Mar 17 2007
parent reply Frits van Bommel <fvbommel REMwOVExCAPSs.nl> writes:
Thomas Kuehne wrote:
 Frits van Bommel schrieb am 2007-03-16:
 Though I could see uses for this, like to run unittests (similarly to 
 what running Python modules "stand-alone" often does).
 D has gone another way there though, using explicit unittest {} blocks. 
 Unfortunately, there is currently no way to run these separately (esp. 
 right after compilation) that I know of.
Flectioned's unittest walker does exactly that: dmd -unittest -g -c <your source> dmd flectioned.d unittest_walker.d -ofwhatever <your objects> ./whatever http://flectioned.kuehne.cn
Interesting, I wasn't aware of that. Looking at the source though, is there any particular reason the code is in a static this() instead of in the empty void main() at the end? Shouldn't unit tests be performed after all static constructors have been completed, so that the modules being tested have been initialized? That, to me, indicates that the code should be in main(). Though with the recommended lines the code linked from .ctors probably links the ModuleInfo in the right order (from what I remember, it links each module at the head of the linked list, reversing the order), that doesn't look very robust. And why the empty main()? Is that to make sure that one gets linked instead of any main() provided in the other object files? And a static constructor that shuts down the gc and ends the program also just seems a bit fishy :), though in this case (given that the code is in a static this()) it seems to be what you want to do. But what exactly is the use case here? To just run the unit tests and avoid running main()? Wouldn't that be more easily accomplished by just letting the unit tests run "manually" and providing an empty main()? Of course, that wouldn't provide as nice an example of flectioned use :P .
Mar 17 2007
parent reply Thomas Kuehne <thomas-dloop kuehne.cn> writes:
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Frits van Bommel schrieb am 2007-03-17:
 Thomas Kuehne wrote:
 Frits van Bommel schrieb am 2007-03-16:
 Though I could see uses for this, like to run unittests (similarly to 
 what running Python modules "stand-alone" often does).
 D has gone another way there though, using explicit unittest {} blocks. 
 Unfortunately, there is currently no way to run these separately (esp. 
 right after compilation) that I know of.
Flectioned's unittest walker does exactly that: dmd -unittest -g -c <your source> dmd flectioned.d unittest_walker.d -ofwhatever <your objects> ./whatever http://flectioned.kuehne.cn
Interesting, I wasn't aware of that. Looking at the source though, is there any particular reason the code is in a static this() instead of in the empty void main() at the end?
Yes, "int main(char[][])" isn't executed until after the unittests are run.
 Shouldn't unit tests be performed after all static constructors have 
 been completed, so that the modules being tested have been initialized?
Fixed.
 But what exactly is the use case here? To just run the unit tests and 
 avoid running main()?
 Wouldn't that be more easily accomplished by just letting the unit tests 
 run "manually" and providing an empty main()?
 Of course, that wouldn't provide as nice an example of flectioned use :P .
Normaly the first failing unittest would terminate the programm, unittest_walker however executes all unittests and displays their failure/success. Thomas -----BEGIN PGP SIGNATURE----- iD8DBQFF/WDHLK5blCcjpWoRApitAJ9pcL+SBhFasCR0OsYzwFP3z5gP7ACfdW77 4EtvBlKRjhcsqCdPmWyuDR0= =M526 -----END PGP SIGNATURE-----
Mar 18 2007
parent reply Frits van Bommel <fvbommel REMwOVExCAPSs.nl> writes:
Thomas Kuehne wrote:
 
 Frits van Bommel schrieb am 2007-03-17:
 Shouldn't unit tests be performed after all static constructors have 
 been completed, so that the modules being tested have been initialized?
Fixed.
Interesting solution, just replacing the _moduleUnitTests() that normally runs them :). (I guess that's the natural place to put it though) Unfortunate about the ugly warning this produces ("usr/bin/ld: Warning: size of symbol `_moduleUnitTests' changed from 1084 in unittest_walker.o to 58 [...]").
 But what exactly is the use case here? To just run the unit tests and 
 avoid running main()?
 Wouldn't that be more easily accomplished by just letting the unit tests 
 run "manually" and providing an empty main()?
 Of course, that wouldn't provide as nice an example of flectioned use :P .
Normaly the first failing unittest would terminate the programm, unittest_walker however executes all unittests and displays their failure/success.
Ah yes, forgot about that (failed unit tests aborting the program). About your sample.d: It thinks I'm a Windows user who didn't compile Phobos with debug symbols :P. In reality, I'm using GDC 0.23 on amd64 Linux. It turns out GDC's std/math.d only declares isnormal() itself if on x86, otherwise it aliases gcc.config.isnormal() to do the job... (Adding "version(GNU) if(!funcs) { funcs = "gcc.config.isnormal" in functions; }" right after the lookup should fix it) Also, your struct example seems to have a typo (0x13_45_67_AB != 0x1234567AB). And some unit tests in flectioned.d fail: --- $ gdmd -L--allow-multiple-definition -fall-sources -unittest -oftest test.d cn/kuehne/flectioned.d cn/kuehne/unittest_walker.d /usr/bin/ld: Warning: size of symbol `_moduleUnitTests' changed from 1084 in unittest_walker.o to 58 in /home/urxae/opt/gdc/bin/../lib/gcc/x86_64-unknown-linux-gnu/4.1.1/../../../../lib64/libgphobos.a(moduleinit.o) $ ./test [snip] testing cn.kuehne.flectioned.TracedException.__unittest21 ... FAILED: (std.asserterror.AssertError) AssertError Failure cn/kuehne/flectioned.d(991) testing cn.kuehne.flectioned.Trace.__unittest18 ... FAILED: (std.asserterror.AssertError) AssertError Failure cn/kuehne/flectioned.d(654) testing cn.kuehne.flectioned.Trace.__unittest19 ... FAILED: (std.asserterror.AssertError) AssertError Failure cn/kuehne/flectioned.d(654) testing cn.kuehne.flectioned.TracedException.__unittest22 ... FAILED: (std.asserterror.AssertError) AssertError Failure cn/kuehne/flectioned.d(654) testing cn.kuehne.flectioned.Trace.__unittest17 ... FAILED: (std.asserterror.AssertError) AssertError Failure cn/kuehne/flectioned.d(654) [snip] Summary: 29/5/34 (succeeded/failed/total) --- (test.d contains only an empty main())
Mar 18 2007
parent reply Thomas Kuehne <thomas-dloop kuehne.cn> writes:
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Frits van Bommel schrieb am 2007-03-18:
[snip]
 About your sample.d: It thinks I'm a Windows user who didn't compile 
 Phobos with debug symbols :P.
 In reality, I'm using GDC 0.23 on amd64 Linux.
 It turns out GDC's std/math.d only declares isnormal() itself if on x86, 
 otherwise it aliases gcc.config.isnormal() to do the job...
 (Adding "version(GNU) if(!funcs) { funcs = "gcc.config.isnormal" in 
 functions; }" right after the lookup should fix it)

 Also, your struct example seems to have a typo (0x13_45_67_AB != 
 0x1234567AB).
Fixed
 And some unit tests in flectioned.d fail:
 ---
 $ gdmd -L--allow-multiple-definition -fall-sources -unittest -oftest 
 test.d cn/kuehne/flectioned.d cn/kuehne/unittest_walker.d
 /usr/bin/ld: Warning: size of symbol `_moduleUnitTests' changed from 
 1084 in unittest_walker.o to 58 in 
 /home/urxae/opt/gdc/bin/../lib/gcc/x86_64-unknown-linux-gnu/4.1.1/../../../../lib64/libgphobos.a(moduleinit.o)
 $ ./test
 [snip]
 testing cn.kuehne.flectioned.TracedException.__unittest21 ... FAILED: 
 (std.asserterror.AssertError) AssertError Failure 
 cn/kuehne/flectioned.d(991)
Strange, this unittest succeds if it is put in a seperate file!?
 testing cn.kuehne.flectioned.Trace.__unittest18 ... FAILED: 
 (std.asserterror.AssertError) AssertError Failure 
 cn/kuehne/flectioned.d(654)
 testing cn.kuehne.flectioned.Trace.__unittest19 ... FAILED: 
 (std.asserterror.AssertError) AssertError Failure 
 cn/kuehne/flectioned.d(654)
 testing cn.kuehne.flectioned.TracedException.__unittest22 ... FAILED: 
 (std.asserterror.AssertError) AssertError Failure 
 cn/kuehne/flectioned.d(654)
 testing cn.kuehne.flectioned.Trace.__unittest17 ... FAILED: 
 (std.asserterror.AssertError) AssertError Failure 
 cn/kuehne/flectioned.d(654)
Removed this test because it may hide the real problems. Thomas -----BEGIN PGP SIGNATURE----- iD8DBQFF/morLK5blCcjpWoRAmceAKCAz1m8nziIv8XGd42L4EurE7qYLwCfUFCn Z/yF3T0DW25wcBmmSF0HmZA= =AvLO -----END PGP SIGNATURE-----
Mar 19 2007
parent Frits van Bommel <fvbommel REMwOVExCAPSs.nl> writes:
Thomas Kuehne wrote:
 
 Frits van Bommel schrieb am 2007-03-18:
 And some unit tests in flectioned.d fail:
 ---
 $ gdmd -L--allow-multiple-definition -fall-sources -unittest -oftest 
 test.d cn/kuehne/flectioned.d cn/kuehne/unittest_walker.d
 /usr/bin/ld: Warning: size of symbol `_moduleUnitTests' changed from 
 1084 in unittest_walker.o to 58 in 
 /home/urxae/opt/gdc/bin/../lib/gcc/x86_64-unknown-linux-gnu/4.1.1/../../../../lib64/libgphobos.a(moduleinit.o)
 $ ./test
 [snip]
 testing cn.kuehne.flectioned.TracedException.__unittest21 ... FAILED: 
 (std.asserterror.AssertError) AssertError Failure 
 cn/kuehne/flectioned.d(991)
Strange, this unittest succeds if it is put in a seperate file!?
No, still fails if I put it in test.d (and qualify some of the names of static members).
 testing cn.kuehne.flectioned.Trace.__unittest18 ... FAILED: 
 (std.asserterror.AssertError) AssertError Failure 
 cn/kuehne/flectioned.d(654)
 testing cn.kuehne.flectioned.Trace.__unittest19 ... FAILED: 
 (std.asserterror.AssertError) AssertError Failure 
 cn/kuehne/flectioned.d(654)
 testing cn.kuehne.flectioned.TracedException.__unittest22 ... FAILED: 
 (std.asserterror.AssertError) AssertError Failure 
 cn/kuehne/flectioned.d(654)
 testing cn.kuehne.flectioned.Trace.__unittest17 ... FAILED: 
 (std.asserterror.AssertError) AssertError Failure 
 cn/kuehne/flectioned.d(654)
Removed this test because it may hide the real problems.
If I comment that assert out, cn.kuehne.flectioned.Trace.__unittest20 (which seems to be the test for Trace.findSymbol, the function whose postcondition contains that assertion) fails with a segfault. However, the first test, that I copied to test.d, now succeeds... (Even though that wasn't the assertion that failed for that test)
Mar 19 2007
prev sibling next sibling parent reply Stewart Gordon <smjg_1998 yahoo.com> writes:
Daniel Keep Wrote:

 Manfred Nowak wrote:
<snip>
 XP supports hard links.
Yeah, but they suck. You need to download a third-party tool to use them, for starters. Secondly, almost nothing written for Windows even knows about them, not even *Explorer*, so it's impossible to tell if something is a link or not. And of course, they can't span drives.
Nor can Unix hard links. It would conflict somewhat with the way hard links work.
 I'm fairly sure that one version of Windows could only hard-link 
 folders, but not files.  Not sure if that was 2k or XP.
 
 I once planned on using hard links to make migrating stuff between 
 drives easier.  Obviously I couldn't do that, but what really 
 scared me was when I realised that deleting the link deleted the 
 original as well; I just backed away slowly, avoiding eye contact.
<snip> Strange. I wonder just how these hard links work. Does deleting one of them delete the whole lot in one fell swoop, or produce loads of dead links? Or do they disappear as and when you try to determine their existence? Stewart.
Mar 17 2007
next sibling parent reply Daniel Keep <daniel.keep.lists gmail.com> writes:
Stewart Gordon wrote:
 Daniel Keep Wrote:
 
 Manfred Nowak wrote:
<snip>
 XP supports hard links.
Yeah, but they suck. You need to download a third-party tool to use them, for starters. Secondly, almost nothing written for Windows even knows about them, not even *Explorer*, so it's impossible to tell if something is a link or not. And of course, they can't span drives.
Nor can Unix hard links. It would conflict somewhat with the way hard links work.
 I'm fairly sure that one version of Windows could only hard-link 
 folders, but not files.  Not sure if that was 2k or XP.

 I once planned on using hard links to make migrating stuff between 
 drives easier.  Obviously I couldn't do that, but what really 
 scared me was when I realised that deleting the link deleted the 
 original as well; I just backed away slowly, avoiding eye contact.
<snip> Strange. I wonder just how these hard links work. Does deleting one of them delete the whole lot in one fell swoop, or produce loads of dead links? Or do they disappear as and when you try to determine their existence? Stewart.
This is speculation, but I think that UNIX hard links are like... ref-counted objects in Python, whereas Windows hard links are like un-counted objects in C++. In UNIX, deleting one ref doesn't affect the others, deleting an object in C++... well, you get the idea :P I realise that UNIX hard links share many of the same limitations, but the difference is that soft symlinks aren't available on Windows as an alternative. Interesting side note: Cygwin actually uses normal Windows shortcuts for its soft symlinks: Cygwin actually does a better job of supporting shortcuts than Windows itself does! -- Daniel -- Unlike Knuth, I have neither proven or tried the above; it may not even make sense. v2sw5+8Yhw5ln4+5pr6OFPma8u6+7Lw4Tm6+7l6+7D i28a2Xs3MSr2e4/6+7t4TNSMb6HTOp5en5g6RAHCP http://hackerkey.com/
Mar 17 2007
parent Stewart Gordon <smjg_1998 yahoo.com> writes:
Daniel Keep Wrote:

<snip>
 This is speculation, but I think that UNIX hard links are like...
 ref-counted objects in Python, 
<snip> I'm not familiar with Python, but ref-counted objects is correct. On Unix there are three aspects to a file: the path (hard link), the inode and the contents. A hard link points to an inode, which contains the reference count; the inode in turn points to the file contents. No two inodes can point to the same contents, but a given inode can have many hard links to it. Interesting fact: The Unix rm command, in at least some versions, has a flag to zero the file's contents. (Well, it either sets all bits to 0, then 1, then 0, or the other way round, I'm not sure which.) But it doesn't check for multiple hard links, and so any that remain will just point to the blankness it has created. I once wrote a C++ vector class that works in much the same way - having a class Vector, which the user works with, and VectorData, which stores the data itself and the reference count. Stewart.
Mar 18 2007
prev sibling parent "Joel C. Salomon" <JoelCSalomon Gmail.com> writes:
Stewart Gordon wrote:
 Strange.  I wonder just how these hard links work.  Does deleting one of them
delete the whole lot in one fell swoop, or produce loads of dead links?  Or do
they disappear as and when you try to determine their existence?
On UNIX and Windows (NTFS), hard links are reference-counted; the directory entry (the datum that has the file’s name and position in the directory tree) has a “link” to the actual file data. The “delete” operation is called “unlink” under UNIX because it unlinks a directory entry from a file — and, if there are no other links to the file, deletes the file. --Joel
Mar 18 2007
prev sibling parent reply Dejan Lekic <dejan.lekic gmail.com> writes:
Well, I think it is very good to have main _inside_ a class I am currently
"playing with" during the development process (of the class). Sure I can have a
main() function in the same module and play with the class there, but somehow I
"feel" it belongs to the class block. Obviously this is a matter of taste, so
it does not really matter whether we will have this "feature" in D or not. I
just started this thread because I thought it is somehow possible to do it... :)
Mar 18 2007
parent Bill Baxter <dnewsgroup billbaxter.com> writes:
Dejan Lekic wrote:

 Well, I think it is very good to have main _inside_ a class I am
 currently "playing with" during the development process (of the
 class). Sure I can have a main() function in the same module and play
 with the class there, but somehow I "feel" it belongs to the class
 block. Obviously this is a matter of taste, so it does not really
 matter whether we will have this "feature" in D or not. I just started
 this thread because I thought it is somehow possible to do it...  :)
I don't get it. If you like having main in a class so much just put it there and call it. If you like Java, then apparently you like typing and this way you get to do even more of it! :-) class MyClass { public static void main(char[][] args) { writefln("Whee I'm main now!"); } } void main(char[][] args) { MyClass.main(); }
Mar 18 2007