Talk:Modulinos: Difference between revisions

From Rosetta Code
Content added Content deleted
(Fixed nametag)
Line 10: Line 10:
:: This current examples are an awful way to use Python's <tt>__name__ == "__main__"</tt> or Ruby's <tt>__FILE__ == $0</tt>. The Python code exports <tt>scriptedmain.main()</tt> and the Ruby code actually defines a global function <tt>main</tt>, which replaces my global function <tt>main</tt> if I defined one before I required the library. I would like to change the Python and Ruby examples to look like <tt>if __name__ == "main": print "It is %s" % meaning_of_life()</tt>, but I am not sure if the task allows me to do this. --[[User:Kernigh|Kernigh]] 22:40, 6 March 2011 (UTC)
:: This current examples are an awful way to use Python's <tt>__name__ == "__main__"</tt> or Ruby's <tt>__FILE__ == $0</tt>. The Python code exports <tt>scriptedmain.main()</tt> and the Ruby code actually defines a global function <tt>main</tt>, which replaces my global function <tt>main</tt> if I defined one before I required the library. I would like to change the Python and Ruby examples to look like <tt>if __name__ == "main": print "It is %s" % meaning_of_life()</tt>, but I am not sure if the task allows me to do this. --[[User:Kernigh|Kernigh]] 22:40, 6 March 2011 (UTC)


::: Kernigh, requires go at the top of files, not after you've declared a main() method. If you deviate from standard programming layouts, you circumvent the language's built-in capabilities, and you're sure to get strange results.


==Name change?==
==Name change?==

Revision as of 04:57, 13 March 2011

Needs more description

The task description here is missing something. Is this a task to show a main function that will be run from the command line? I've never heard the phrase "scripted main" before, so I'd like some more definition there too. The examples also seem to do lots of stuff that isn't described in the directions. --Mwn3d 00:16, 4 March 2011 (UTC)

Very much agree.
The Github link in the intro text says this:
Programs that only run main() if they're not loaded as libraries by other programs.
Make of that what you will. Clarification definitely needed. -- Erik Siers 07:16, 4 March 2011 (UTC)
I write command line programs with usage info, flags, etc. I like to combine the exported API with a usable program. Some programming languages have well-known syntax; Python's if __name__=="__main__": main() illustrates this behavior. Other languages, such as Common Lisp, require a hack. I want these hacks to be more easily Googled--I had trouble finding them in the first place. --Mcandre
This current examples are an awful way to use Python's __name__ == "__main__" or Ruby's __FILE__ == $0. The Python code exports scriptedmain.main() and the Ruby code actually defines a global function main, which replaces my global function main if I defined one before I required the library. I would like to change the Python and Ruby examples to look like if __name__ == "main": print "It is %s" % meaning_of_life(), but I am not sure if the task allows me to do this. --Kernigh 22:40, 6 March 2011 (UTC)
Kernigh, requires go at the top of files, not after you've declared a main() method. If you deviate from standard programming layouts, you circumvent the language's built-in capabilities, and you're sure to get strange results.

Name change?

Reason being that ScriptedMain , even if changed to the more RC norm of "Scripted main", doesn't mean much, or as much as, say, "Executable library". The task seems to be about having a means of allowing library code - usually imported/included into a larger program; to also function as a useful program in its own right when executed directly.

Use whichever name you like. It's hard to search for this behavior online, so I've decided to give it an itinerant name, "Scripted main", the main() that runs only when a program is run directly, not imported by other programs. --Mcandre

The idea of an executable library (scripted main), has merit for interpreted languages, but seems contrived for compiled languages as in most cases you are further removed from both the library sources and the means to compile them, when actually executing a program using the library. Although many stand alone libraries are available in, for example, C, I have only seen stand-alone utilities that come with those libraries as separate programs with separate source files that link to the libraries at compile time. --Paddy3118 00:39, 4 March 2011 (UTC)

There is some truth to that. But many languages offer scripting and compilation. In any case, it's helpful to know that main() is always executed (C, C++, D), optionally executed (Perl, Python, Ruby, Chicken Scheme), or requires obscure syntactical tricks to even attempt (Bash, Lua, Common Lisp). I could omit the print-current-directory, print-current-program, and print-command-line-arguments sections from the scripted main examples, since Rosetta already has snippets for those behaviors. But programmers are likely to want scripted main and these other behaviors together, and often one is needed in order for the other to be possible. E.g., Chicken Scheme has no built-in way to get the program name, and scripted main won't work in compiled mode unless it can compare its command line arguments and program name.

TL;DR: All four behaviors are useful to know and they're very hard to Google. --Mcandre

... Which is why I would prefer a more descriptive name that might be more likely to be searched for, like "Executable library". --Paddy3118 12:35, 6 March 2011 (UTC)
I think that "library" should be in the page name. I prefer "Library with optional main", where the optional main is what runs only when I directly run the program, not when I load the library. "Library with scripted main" would work if we want to keep the "scripted main" phrase. --Kernigh 22:40, 6 March 2011 (UTC)

Some chat in IRC

There was some discussion in IRC on the subject: http://irclog.perlgeek.de/rosettacode/2011-03-04#i_3355683. --Michael Mol 16:14, 4 March 2011 (UTC)

When a compiled program is run, the compiled program is run. The compiled program cannot be loaded as a library too can it? (I mean that it isn't done normally). If not then only normally interpreted languages could have this property; things like the C example don't fit the task description. --Paddy3118 16:33, 4 March 2011 (UTC)
It can; we do exactly this in one of my employer's products. I was rather surprised myself. I'd venture a guess that, at the OS level, this is exactly what's done with binary images anyway, except that the OS automatically runs a predefined entry point. (On Windows, I believe this is WinMain. I'm not sure what it is on Linux. The CRT wraps these in both cases.) The C example on the page is incorrect to that end, though. I believe the Java example is, too. --Michael Mol 17:37, 4 March 2011 (UTC)
I could change the task to reflect what Python does with, for example its CGIHTTPServer module, where calling it as command python -m CGIHTTPServer starts a web server, and loading it as a module would allow the calling program access to code for setting up a web server. --Paddy3118 16:33, 4 March 2011 (UTC)

C code can use libraries ("shared libraries", "dynamically loaded libraries", whatever...). It's relatively trivial to put all of the logic in a library and have a trivial program that links to that library. That said, this is more about the build process than it is about the C code. (But good practice usually suggests that the "library code" and the "program code" be in separate files.) --Rdm 12:16, 7 March 2011 (UTC)

Can shared libraries be executed without an extra 'trivial program' though? Python not only has that ability, but it is a documented and well used feature of the language. --Paddy3118 17:15, 7 March 2011 (UTC)
I believe that that is an OS issue. Hypothetically speaking: a shared library that defines a "main()" routine, can be treated as an executable. However if the OS requires something else (like: let's say there is a bit you set: when this bit is set you have an executable, when this bit is cleared you have a shared library), then you need a separate file (so that that bit can be set to different values for each of the two purposes). (With Python, the interpreter itself can serve to make this distinction -- in this case it is the "extra 'trivial program'" (or perhaps not-so-trivial program) that you need to make this work.) --Rdm 17:24, 7 March 2011 (UTC)
So far it seems there are a lot of examples with no clear definition of what they are about. To require the presence of a compiler for these examples in statically compiled languages is irregular, as most run-time environments for compiled languages do not have the compiler or the source present.
The task seems to be a way to get RC as the second place that mentions the page title as well as one blog entry all from the same person, without enough thought on what ideas are to come under the title.
Mcandre needs to answer some more of the points put to him on the purpose of the task - maybe by answering all the questions and suggestions on this talk page).
I guess I am against what looks like one persons attempt to popularize their own nebulous idea through RC. Is this a different kind of spam? --Paddy3118 07:34, 8 March 2011 (UTC)
I don't know. It could simply be a case of Tai's Model, or it could be a design pattern without an agreed-upon name. I could be wrong, but I think it's likely to be the latter. The name 'scripted main' is in no way clarifying to me as to what the pattern is supposed to do. However, the README file from mcandre's GitHub hosting of his initial examples describes a simple behavior, "scriptedmain - Programs that only run main() if they're not loaded as libraries by other programs." I really think the better description of this is "write a program which does one thing when executed directly and another thing when loaded as part of a larger program." --Michael Mol 16:21, 8 March 2011 (UTC)

Ambiguities

According to the page history, the C program was the first example, so it should serve to illustrate what this task is about. However, the C implementation has:

<lang c>#include "scriptedmain.h"</lang>

This whole concept of "startup" is an OS issue, and not a language issue. Some operating systems have various ways of starting programs, and "main" may or may not be a part of them. (For example, using drag&drop to start a program might work differently from starting the program from a command line.)

Furthermore, different concepts of what this all means depend very much on how the code is represented. A compiled language may be represented as a shared library, or not, where an interpreted language may be represented as neither. But a compiled language may also be represented as source code. And if you have source code as a set of files, you could perhaps simply ignore the file that defines main (if the language even uses that name -- some might abstract it away even if the OS requires its use).

So, anyways, I think this task needs some work. Specifically, I think it needs some kind of illustration requirement (where the "scripted main" code gets used by some other code that has its own "main").

-- Rdm 17:51, 4 March 2011 (UTC)

Test the C program yourself. As long as scriptedmain.h is missing the main() prototype, a second file test.c will not execute scriptedmain.c's main(). --Mcandre

I see that you have updated the description of the C program, to specify that scriptedmain.h is blank, so I have removed those comments that referred to this issue. However, since the example does not demonstrate the use of any API, I think the example is useless and unclear. (We have to imagine that we know what you are trying to illustrate.)
That said, my current impression is that you are asking us to illustrate putting the API in a separate file from the definition of "main". If that is the case, many of the examples here (including the one I wrote) are incorrect. --Rdm 13:49, 6 March 2011 (UTC)

Is this something like what you want to show?

OK I'm still not clear on this, so I've kind of been avoiding it and hoping that everyone else can figure it out. I have a guess for what I think this is trying to show, though. I'll show it in Java: <lang java5>package RC.test; import java.util.Arrays;

public class MainClass{

   public static void main(String[] args){
       System.out.println(Arrays.toString(args));
   }

}</lang>

<lang java5>import RC.test.MainClass; import java.util.Arrays;

public class TestClass{

   public static void main(String[] args){
       MainClass.main({"this", "is", "a", "test"});
   }

}</lang> If I would run java MainClass testing 1 2 3 it would print:

testing
1
2
3

If I would run java TestClass it would print:

this
is
a
test

So the main method in MainClass is callable from another class if MainClass is imported in TestClass. I'm not sure if that means Java has a scripted main or not because that phrase means nothing to me still. What do you think? --Mwn3d 21:20, 6 March 2011 (UTC)

Seems close; but the central idea of what the task is about needs work before anyone can judge. I propose we work first on what the task is about; next, on whethere the idea is general enough to be in RC; then on language implementations. --Paddy3118 07:01, 7 March 2011 (UTC)
No, your Java example seems wrong to me. The current task description says to "to execute a main() function only when a program is run directly". So call MainClass.main() only when running MainClass? Your example is wrong because it also calls MainClass.main() when running TestClass? --Kernigh 02:10, 9 March 2011 (UTC)
Mwn3d, see the current Java example, "ScriptedMain". The comments above about "library as an executable" are on point. The desired behavior is that the ScriptedMain class runs a main method, Test imports ScriptedMain, and Java does not call ScriptedMain.main() when Test is run. --Mcandre

What is an "Executable library"

(This section needs expansion and discussion to see if we have enough to create a task that is capable of being completed by enough languages.) --Paddy3118 07:45, 7 March 2011 (UTC)

When given a task in a programming 'contest' such as to create a simple function and to find values of that function at certain points; then you would be giving your example in the form of an executable library if:

For an interpreted language:

  • When the interpreter is called on the source file, the result is the generation of all the values needed for the 'contest'. Although a command-line argument specifying that the library is being directly executed is permitted, an executable library must be able to contain all the code to produce the values for the competition.
  • When another source file includes the library source file as a library/module resource, the simple function can then be called, but the code in the library file for producing results specific to the competition, should not be automatically called at all.

For a compiled language:
The equivalent would be an executable shared object file (Unix) or executable DLL (Windows).

  • When the .so or DLL is called/run/clicked on, the result is the generation of all the values needed for the 'contest'.
  • Another executable must be able to access the same .so/DLL file as a resource from which the simple function can then be called, but the code in the .so/DLL file for producing results specific to the competition, should not be automatically called at all.

Examples

An example would be the Python entry for Hailstone sequence.

<lang python>def hailstone(n):
   seq = [n]
   while n>1:
       n = 3*n + 1 if n & 1 else n//2
       seq.append(n)
   return seq

if __name__ == '__main__':

   h = hailstone(27)
   assert len(h)==112 and h[:4]==[27, 82, 41, 124] and h[-4:]==[8, 4, 2, 1]
   print("Maximum length %i was found for hailstone(%i) for numbers <100,000" %
         max((len(hailstone(i)), i) for i in range(1,100000)))</lang>

In the case of the Python language the interpreter maintains a module level variable called __name__. If a file hailstone.py is imported (as import hailstone), then the __name__ variable is set to the import name of 'hailstone' and the if __name__ == '__main__' expression would then be false, and only the hailstone function is available to the importer.

If the same file hailstone.py is run, (as maybe python hailstone.py; or maybe double-clicking the hailstone.py file), then the __name__ variable is set to the special name of '__main__' and the if __name__ == '__main__' expression would then be true causing its block of code to be executed.

--Paddy3118 07:45, 7 March 2011 (UTC)