Jump to page: 1 2
Thread overview
Entry (main) method inside a class?
Mar 16, 2007
Dejan Lekic
Mar 16, 2007
Frits van Bommel
Mar 16, 2007
Benji Smith
Mar 16, 2007
Frits van Bommel
Mar 17, 2007
Manfred Nowak
Mar 17, 2007
Daniel Keep
Mar 17, 2007
Thomas Kuehne
Mar 17, 2007
Frits van Bommel
Mar 18, 2007
Thomas Kuehne
Mar 18, 2007
Frits van Bommel
Mar 19, 2007
Thomas Kuehne
Mar 19, 2007
Frits van Bommel
March 16, 2007
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
March 16, 2007
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.
March 16, 2007
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
March 16, 2007
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.
March 17, 2007
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
March 17, 2007

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/
March 17, 2007
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


March 17, 2007
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 .
March 18, 2007
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


March 18, 2007
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())
« First   ‹ Prev
1 2