Talk:Modulinos
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)
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)
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)
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)