Modulinos
It is useful to be able to execute a main() function only when a program is run directly. This is a central feature in programming scripts; the feature is called scripted main.
Examples from GitHub.
Sometimes getting the ScriptName is required in order to determine when to run main().
- This is still a draft task, and the current task description has caused mega confusion. See Talk:Scripted Main for numerous attempts to understand the task and to rewrite the task description.
- The task Executable library is written to replace this task. This task's future is in doubt as its aims are not clear enough.
C
C programs cannot normally do scripted main, because main() is implicitly included by another program, test.c, even though scriptedmain.h omits any main() prototype. A compiler directive fixes this.
<lang sh>$ gcc -o scriptedmain scriptedmain.c scriptedmain.h $ ./scriptedmain Main: The meaning of life is 42 $ gcc -o test test.c scriptedmain.c scriptedmain.h $ ./test Test: The meaning of life is 42</lang>
scriptedmain.h
<lang c>int meaning_of_life();</lang>
scriptedmain.c
<lang c>#include <stdio.h>
int meaning_of_life() { return 42; }
int __attribute__((weak)) main(int argc, char **argv) { printf("Main: The meaning of life is %d\n", meaning_of_life());
return 0; }</lang>
test.c
<lang c>#include "scriptedmain.h"
- include <stdio.h>
extern int meaning_of_life();
int main(int argc, char **argv) { printf("Test: The meaning of life is %d\n", meaning_of_life()); return 0; }</lang>
C++
C++ programs cannot normally do scripted main, because main() is implicitly included by another program, test.c, even though scriptedmain.h omits any main() prototype. A compiler directive fixes this.
scriptedmain.h
<lang cpp>int meaning_of_life();</lang>
scriptedmain.cpp
<lang cpp>#include <iostream>
using namespace std;
int meaning_of_life() { return 42; }
int __attribute__((weak)) main(int argc, char **argv) { cout << "Main: The meaning of life is " << meaning_of_life() << endl;
return 0; }</lang>
test.cpp
<lang cpp>#include "scriptedmain.h"
- include <iostream>
using namespace std;
extern int meaning_of_life();
int main(int argc, char **argv) { cout << "Test: The meaning of life is " << meaning_of_life() << endl;
return 0; }</lang>
Chicken Scheme
Chicken Scheme has the {{{ -ss }}} flag for the interpreter, but compiled Chicken Scheme programs do not have scripted main unless the behavior is added manually to the code.
scriptedmain.scm
<lang scheme>#!/bin/sh
- |
exec csi -ss $0 ${1+"$@"} exit |#
(use posix) (require-extension srfi-1) ; lists
(define (meaning-of-life) 42)
(define (main args) (display (format "Main: The meaning of life is ~a\n" (meaning-of-life))) (exit))
(define (program) (if (string=? (car (argv)) "csi") (let ((s-index (list-index (lambda (x) (string-contains x "-s")) (argv)))) (if (number? s-index) (cons 'interpreted (list-ref (argv) (+ 1 s-index))) (cons 'unknown ""))) (cons 'compiled (car (argv)))))
(if (equal? (car (program)) 'compiled) (main (cdr (argv))))</lang>
test.scm
<lang scheme>#!/bin/sh
- |
exec csi -ss $0 ${1+"$@"} exit |# (define (main args) (load "scriptedmain.scm") (display (format "Test: The meaning of life is ~a\n" (meaning-of-life))) (exit))</lang>
Clojure
Clojure has a function -main which will run in only four cases.
- clj is passed the flag -m <class>. <lang sh>$ clj -m scriptedmain
Main: The meaning of life is 42 $ clj -m test Test: The meaning of life is 42</lang>
- A shebang forces -m <class>. <lang sh>$ ./scriptedmain.clj
Main: The meaning of life is 42 $ ./test.clj Test: The meaning of life is 42</lang>
- The compiled class is run. <lang sh>$ java -cp ~/Library/Clojure/lib/clojure.jar:. scriptedmain
Main: The meaning of life is 42 $ java -cp ~/Library/Clojure/lib/clojure.jar:. test Test: The meaning of life is 42</lang>
- -main is explicitly called. <lang sh>
$ clj user=> (load-file "scriptedmain.clj") user=> (scriptedmain/-main) Main: The meaning of life is 42 nil</lang>
scriptedmain.clj
<lang lisp>":";exec clj -m `basename $0 .clj` $0 ${1+"$@"} ":";exit
(ns scriptedmain (:gen-class))
(defn meaning-of-life [] 42)
(defn -main [& args] (println "Main: The meaning of life is" (meaning-of-life)))</lang>
test.clj
<lang lisp>":";exec clj -m `basename $0 .clj` $0 ${1+"$@"} ":";exit
(ns test (:gen-class))
(load "scriptedmain")
(defn -main [& args] (println "Test: The meaning of life is" (scriptedmain/meaning-of-life)))</lang>
Common Lisp
Common Lisp has few standards for POSIX operation. Shebangs and command line arguments are hacks.
In CLISP, this code only works for ./scriptedmain.lisp.
~/.clisprc.lisp
<lang lisp>;;; Play nice with shebangs (set-dispatch-macro-character #\# #\!
(lambda (stream character n) (declare (ignore character n)) (read-line stream nil nil t) nil))</lang>
scriptedmain.lisp
<lang lisp>#!/bin/sh
- |
exec clisp -q -q $0 $0 ${1+"$@"} exit |#
- Usage
- ./scriptedmain.lisp
(defun meaning-of-life () 42)
(defun main (args)
(format t "Main: The meaning of life is ~a~%" (meaning-of-life)) (quit))
- With help from Francois-Rene Rideau
- http://tinyurl.com/cli-args
(let ((args
#+clisp ext:*args* #+sbcl sb-ext:*posix-argv* #+clozure (ccl::command-line-arguments) #+gcl si:*command-args* #+ecl (loop for i from 0 below (si:argc) collect (si:argv i)) #+cmu extensions:*command-line-strings* #+allegro (sys:command-line-arguments) #+lispworks sys:*line-arguments-list* ))
(if (member (pathname-name *load-truename*) args :test #'(lambda (x y) (search x y :test #'equalp))) (main args)))</lang>
test.lisp
<lang lisp>#!/bin/sh
- |
exec clisp -q -q $0 $0 ${1+"$@"} exit |#
(load "scriptedmain.lisp") (format t "Test: The meaning of life is ~a~%" (meaning-of-life))</lang>
D
D manages to implement scriptedmain through the use of version directives, which require special options to rdmd and dmd.
scriptedmain.d:
<lang d>#!/usr/bin/env rdmd -version=scriptedmain
module scriptedmain;
import std.stdio;
int meaningOfLife() { return 42; }
version (scriptedmain) { void main(string[] args) { writeln("Main: The meaning of life is ", meaningOfLife()); } }</lang>
test.d:
<lang d>#!/usr/bin/env rdmd -version=test
import scriptedmain; import std.stdio;
version (test) { void main(string[] args) { writeln("Test: The meaning of life is ", meaningOfLife()); } }</lang>
Example:
<lang sh>$ ./scriptedmain.d Main: The meaning of life is 42 $ ./test.d Test: The meaning of life is 42 $ dmd scriptedmain.d -version=scriptedmain $ ./scriptedmain Main: The meaning of life is 42 $ dmd test.d scriptedmain.d -version=test $ ./test Test: The meaning of life is 42</lang>
Emacs Lisp
Emacs has scripted main, though older versions require an obscure shebang syntax.
scriptedmain.el
<lang lisp>:;exec emacs -batch -l $0 -f main $*
- Shebang from John Swaby
- http://www.emacswiki.org/emacs/EmacsScripts
(defun meaning-of-life () 42)
(defun main ()
(message "Main: The meaning of life is %d" (meaning-of-life)))</lang>
test.el
<lang lisp>:;exec emacs -batch -l $0 -f main $*
- Shebang from John Swaby
- http://www.emacswiki.org/emacs/EmacsScripts
(defun main ()
(setq load-path (cons default-directory load-path)) (load "scriptedmain.el" nil t) (message "Test: The meaning of life is %d" (meaning-of-life)))</lang>
Erlang
Erlang has scripted main by default. scriptedmain.erl must be compiled before test.erl can access its functions.
scriptedmain.erl
<lang erlang>-module(scriptedmain). -export([meaning_of_life/0]). -import(lists, [map/2]).
meaning_of_life() -> 42.
main(_) -> io:format("Main: The meaning of life is ~w~n", [meaning_of_life()]).</lang>
test.erl
<lang erlang>% Compile scriptedmain.erl first.
-module(test). -import(scriptedmain, [meaning_of_life/0]).
main(_) -> io:format("Test: The meaning of life is ~w~n", [meaning_of_life()]).</lang>
Factor
Note: The INCLUDE/INCLUDING macros must be added to the ~/.factor-rc configuration file.
Example:
<lang sh>$ ./scriptedmain.factor Main: The meaning of life is 42 $ ./test.factor Test: The meaning of life is 42</lang>
~/.factor-rc:
<lang factor>! INCLUDING macro that imports source code files in the current directory
USING: kernel vocabs.loader parser sequences lexer vocabs.parser ; IN: syntax
- include-vocab ( vocab -- ) dup ".factor" append parse-file append use-vocab ;
SYNTAX: INCLUDING: ";" [ include-vocab ] each-token ;</lang>
scriptedmain.factor:
<lang factor>#! /usr/bin/env factor
USING: io math.parser ; IN: scriptedmain
- meaning-of-life ( -- n ) 42 ;
- main ( -- ) meaning-of-life "Main: The meaning of life is " write number>string print ;
MAIN: main</lang>
test.factor:
<lang factor>#! /usr/bin/env factor
INCLUDING: scriptedmain ; USING: io math.parser ; IN: test
- main ( -- ) meaning-of-life "Test: The meaning of life is " write number>string print ;
MAIN: main</lang>
Forth
Given this awful running reference:
<lang forth>42 constant Douglas-Adams
- go ( -- )
." The meaning of life is " Douglas-Adams . cr ;</lang>
The bulk of Forth systems provide a way to generate an executable that enters GO (ar any word) on start.
<lang forth>' go 'MAIN ! program douglas-adams</lang>
Which creates a file named 'douglas-adams' that you can then run. If this is all in the same file, you can load the file, test parts of it, and then exit (or shell out) to run the executable.
A unix script requires that '#!' be a comment and that the system have some #!-compatible arguments.
<lang forth>#! /usr/bin/env gforth
42 constant Douglas-Adams .( The meaning of life is ) Douglas-Adams . cr bye</lang>
Adding #! as a comment, as gforth does, is trivial. For a means by which this script could distinguish between 'scripted execution' and otherwise, a symlink like 'forthscript' could easily be used, and the zeroth OS argument tested for, but there's no convention.
<lang forth>#! /usr/bin/env forthscript
42 constant Douglas-Adams
s" forthscript" 0 arg compare 0= [IF]
.( The meaning of life is ) Douglas-Adams . cr bye
[THEN]
cr .( Why aren't you running this as a script? It only provides a constant.)</lang>
Free Pascal
Makefile:
<lang make>all: scriptedmain
scriptedmain: scriptedmain.pas fpc -dscriptedmain scriptedmain.pas
test: test.pas scriptedmain fpc test.pas
clean: -rm test -rm scriptedmain -rm *.o -rm *.ppu</lang>
scriptedmain.pas:
<lang pascal>{$IFDEF scriptedmain} program ScriptedMain; {$ELSE} unit ScriptedMain; interface function MeaningOfLife () : integer; implementation {$ENDIF} function MeaningOfLife () : integer; begin MeaningOfLife := 42 end; {$IFDEF scriptedmain} begin write('Main: The meaning of life is: '); writeln(MeaningOfLife()) {$ENDIF} end.</lang>
test.pas:
<lang pascal>program Test; uses ScriptedMain; begin write('Test: The meaning of life is: '); writeln(MeaningOfLife()) end.</lang>
Example:
<lang sh>$ make $ ./scriptedmain Main: The meaning of life is: 42 $ make test $ ./test Test: The meaning of life is: 42</lang>
Go
Makefile:
<lang make>include $(GOROOT)/src/Make.inc TARG=scriptname GOFILES=scriptname.go include $(GOROOT)/src/Make.cmd</lang>
scriptname.go:
<lang go>package main
import ("os"; "fmt")
func main() { program := os.Args[0] fmt.Println("Program:", program) }</lang>
Haskell
Haskell has scripted main, but getting scripted main to work with compiled scripts is tricky.
<lang sh>$ runhaskell scriptedmain.hs Main: The meaning of life is 42 $ runhaskell test.hs Test: The meaning of life is 42 $ ghc -fforce-recomp -o scriptedmain -main-is ScriptedMain scriptedmain.hs $ ./scriptedmain Main: The meaning of life is 42 $ ghc -fforce-recomp -o test -main-is Test test.hs scriptedmain.hs $ ./test Test: The meaning of life is 42</lang>
scriptedmain.hs
<lang haskell>#!/usr/bin/env runhaskell
-- Compile: -- -- ghc -fforce-recomp -o scriptedmain -main-is ScriptedMain scriptedmain.hs
module ScriptedMain where
meaningOfLife :: Int meaningOfLife = 42
main :: IO () main = putStrLn $ "Main: The meaning of life is " ++ show meaningOfLife</lang>
test.hs
<lang haskell>#!/usr/bin/env runhaskell
-- Compile: -- -- ghc -fforce-recomp -o test -main-is Test test.hs scriptedmain.hs
module Test where
import ScriptedMain hiding (main)
main :: IO () main = putStrLn $ "Test: The meaning of life is " ++ show meaningOfLife</lang>
Io
ScriptedMain.io:
<lang io>#!/usr/bin/env io
ScriptedMain := Object clone ScriptedMain meaningOfLife := 42
main := method( "Main: The meaning of life is #{ScriptedMain meaningOfLife}" interpolate println )
if (System args size > 0 and System args at(0) containsSeq("ScriptedMain"), main)</lang>
test.io:
<lang io>#!/usr/bin/env io
main := method( "Test: The meaning of life is #{ScriptedMain meaningOfLife}" interpolate println )
if (System args size > 0 and System args at(0) containsSeq("test"), main)</lang>
<lang sh>$ ./ScriptedMain.io Main: The meaning of life is 42 $ ./test.io Test: The meaning of life is 42</lang>
J
scriptedmain.j:
<lang j>#!/usr/bin/env jconsole
load 'regex'
meaningOfLife =: 42
main =: monad : 0 echo 'Main: The meaning of life is ', > 'd' (8!:0) meaningOfLife exit )
program =: monad : 0 if. (#;.1 ARGV) > 1 do. > 1 { ARGV else. 'Interpreted' end. )
shouldrun =: monad : 0 if. '.*scriptedmain.*' rxeq program 0 do. main 0 end. )
shouldrun 0</lang>
test.j:
<lang j>#!/usr/bin/env jconsole
load 'scriptedmain.j'
echo 'Test: The meaning of life is ', > 'd' (8!:0) meaningOfLife
exit </lang>
Example:
<lang sh>$ ./scriptedmain.j Main: The meaning of life is 42 $ ./test.j Test: The meaning of life is 42</lang>
Java
Java has scripted main by default.
ScriptedMain.java
<lang java>public class ScriptedMain { public static int meaningOfLife() { return 42; }
public static void main(String[] args) { System.out.println("Main: The meaning of life is " + meaningOfLife()); } }</lang>
Test.java
<lang java>public class Test { public static void main(String[] args) { System.out.println("Test: The meaning of life is " + ScriptedMain.meaningOfLife()); } }</lang>
LLVM
LLVM can have scripted main a la C, using the weak attribute.
<lang sh>$ make llvm-as scriptedmain.ll llc scriptedmain.bc gcc -o scriptedmain scriptedmain.s ./scriptedmain Main: The meaning of life is 42 llvm-as test.ll llc test.bc gcc -o test test.s scriptedmain.s ./test Test: The meaning of life is 42</lang>
Makefile
<lang make>EXECUTABLE_SM=scriptedmain EXECUTABLE_TEST=test
all: test.ll scriptedmain.s llvm-as test.ll llc test.bc gcc -o $(EXECUTABLE_TEST) test.s scriptedmain.s ./$(EXECUTABLE_TEST)
scriptedmain.s: scriptedmain.ll llvm-as scriptedmain.ll llc scriptedmain.bc gcc -o $(EXECUTABLE_SM) scriptedmain.s ./$(EXECUTABLE_SM)
clean: -rm $(EXECUTABLE_TEST) -rm $(EXECUTABLE_SM) -rm test.s -rm test.bc -rm scriptedmain.s -rm scriptedmain.bc</lang>
scriptedmain.ll
<lang llvm>@msg_main = internal constant [33 x i8] c"Main: The meaning of life is %d\0A\00"
declare i32 @printf(i8* noalias nocapture, ...)
define i32 @meaning_of_life() { ret i32 42 }
define weak i32 @main(i32 %argc, i8** %argv) { %meaning = call i32 @meaning_of_life()
call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([33 x i8]* @msg_main, i32 0, i32 0), i32 %meaning)
ret i32 0 }</lang>
test.ll
<lang llvm>@msg_test = internal constant [33 x i8] c"Test: The meaning of life is %d\0A\00"
declare i32 @printf(i8* noalias nocapture, ...)
declare i32 @meaning_of_life()
define i32 @main(i32 %argc, i8** %argv) { %meaning = call i32 @meaning_of_life()
call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([33 x i8]* @msg_test, i32 0, i32 0), i32 %meaning)
ret i32 0 }</lang>
Lua
Lua has scripted main by default because files are largely indistinguishable from functions semantically (they compile to Lua functions.) Ellipses is Lua's var-arg syntax for functions, and, therefore, for files as well.
scriptedmain.lua
<lang lua>#!/usr/bin/env lua
function meaningoflife() return 42 end
function main(arg) print("Main: The meaning of life is " .. meaningoflife()) end
if type(package.loaded[(...)]) ~= "userdata" then main(arg) else module(..., package.seeall) end</lang>
test.lua
<lang lua>#!/usr/bin/env lua sm = require("scriptedmain") print("Test: The meaning of life is " .. sm.meaningoflife())</lang>
Mathematica
scriptedmain.ma <lang mathematica>#!/usr/bin/env MathKernel -script
MeaningOfLife[] = 42
ScriptName[] = Piecewise[ { {"Interpreted", Position[$CommandLine, "-script", 1] == {}} }, $CommandLine[[Position[$CommandLine, "-script", 1]1,1 + 1]] ]
Program = ScriptName[];
If[StringMatchQ[Program, ".*scriptedmain.*"], Print["Main: The meaning of life is " <> ToString[MeaningOfLife[]]] ]</lang>
test.ma: <lang mathematica>#!/usr/bin/env MathKernel -script
Get["scriptedmain.ma"]
Print["Test: The meaning of life is " <> ToString[MeaningOfLife[]]]</lang>
Example: <lang sh>$ ./scriptedmain.ma Main: The meaning of life is 42 $ ./test.ma Test: The meaning of life is 42</lang>
In Mac and Windows, the output will be surrounded by spurious quotes.
newLISP
newLISP lacks scripted main, but the feature is easily added.
scriptedmain.lsp
<lang lisp>#!/usr/bin/env newlisp
(context 'SM)
(define (SM:meaning-of-life) 42)
(define (main) (println (format "Main: The meaning of life is %d" (meaning-of-life))) (exit))
(if (find "scriptedmain" (main-args 1)) (main))
(context MAIN)</lang>
test.lsp
<lang lisp>#!/usr/bin/env newlisp
(load "scriptedmain.lsp") (println (format "Test: The meaning of life is %d" (SM:meaning-of-life))) (exit)</lang>
Node.js
Node.js has scripted main.
scriptedmain.js
<lang javascript>#!/usr/bin/env node
function meaningOfLife() { return 42; }
exports.meaningOfLife = meaningOfLife;
function main() { console.log("Main: The meaning of life is " + meaningOfLife()); }
if (!module.parent) { main(); }</lang>
test.js
<lang javascript>#!/usr/bin/env node
var sm = require("./scriptedmain");
console.log("Test: The meaning of life is " + sm.meaningOfLife());</lang>
Objective-C
scriptedmain.h:
<lang objc>#import <objc/Object.h>
@interface ScriptedMain: Object {}
+ (int)meaningOfLife;
@end</lang>
scriptedmain.m:
<lang objc>#import "scriptedmain.h"
- import <Foundation/Foundation.h>
@implementation ScriptedMain
+ (int)meaningOfLife { return 42; }
@end
int __attribute__((weak)) main(int argc, char **argv) { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
printf("Main: The meaning of life is %d\n", [ScriptedMain meaningOfLife]);
[pool drain];
return 0; }</lang>
test.m:
<lang objc>#import "scriptedmain.h"
- import <Foundation/Foundation.h>
int main(int argc, char **argv) { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
printf("Test: The meaning of life is %d\n", [ScriptedMain meaningOfLife]);
[pool drain];
return 0; }</lang>
<lang sh>$ gcc -o scriptedmain -lobjc -framework foundation scriptedmain.m $ gcc -o test -lobjc -framework foundation test.m scriptedmain.m $ ./scriptedmain Main: The meaning of life is 42 $ ./test Test: The meaning of life is 42</lang>
OCaml
scriptedmain.ml
<lang ocaml>(*
Compile:
ocamlc -o scriptedmain -linkall str.cma scriptedmain.ml
Run:
./scriptedmain
- )
let meaning_of_life : int = 42
let main () = print_endline ("Main: The meaning of life is " ^ string_of_int meaning_of_life)
let _ = let program = Sys.argv.(0) and re = Str.regexp "scriptedmain" in try let _ = Str.search_forward re program 0 in main () with Not_found -> ()</lang>
test.ml
<lang ocaml>(*
Compile:
ocamlc -o test -linkall str.cma scriptedmain.ml test.ml
Run:
./test
- )
let main () = print_endline ("Test: The meaning of life is " ^ string_of_int Scriptedmain.meaning_of_life)
let _ = let program = Sys.argv.(0) and re = Str.regexp "test" in try let _ = Str.search_forward re program 0 in main () with Not_found -> ()</lang>
Octave/MATLAB
Octave and MATLAB have scripted main by default, because only the first function listed in a program are importable by other programs.
meaningoflife.m
<lang matlab>#!/usr/bin/env octave -qf
function y = meaningoflife() y = 42; endfunction
function main() printf("Main: The meaning of life is %d", meaningoflife()); endfunction
main();</lang>
test.m
<lang matlab>#!/usr/bin/env octave -qf
printf("Test: The meaning of life is %d", meaningoflife());</lang>
Perl
Perl has scripted main. The code inside unless(caller) { ... } only runs when Life.pm is the main program.
<lang perl>#!/usr/bin/env perl
- Life.pm
package Life;
use strict; use warnings;
sub meaning_of_life { return 42; }
unless(caller) { print "Main: The meaning of life is " . meaning_of_life() . "\n"; }</lang>
<lang perl>#!/usr/bin/env perl
- death.pl
use strict; use warnings;
use Life;
print "Life means " . Life::meaning_of_life . ".\n"; print "Death means invisible scary skeletons.\n";</lang>
Perl 6
Perl 6 automatically calls MAIN on direct invocation, but this may be a multi dispatch, so a library may have multiple "scripted mains". <lang perl6>class LUE {
has $.answer = 42;
}
multi MAIN ('test') {
say "ok" if LUE.new.answer == 42;
}
multi MAIN ('methods') {
say ~LUE.^methods;
}</lang>
PHP
PHP does not have scripted main, but the feature is easily added with a regular expression.
scriptedmain.php
<lang php><?php function meaning_of_life() { return 42; }
function main($args) { echo "Main: The meaning of life is " . meaning_of_life() . "\n"; }
if (preg_match("/scriptedmain/", $_SERVER["SCRIPT_NAME"])) { main($argv); } ?></lang>
test.php
<lang php><?php require_once("scriptedmain.php"); echo "Test: The meaning of life is " . meaning_of_life() . "\n"; ?></lang>
PicoLisp
PicoLisp normally does it the other way round: It calls main from the command line with the '-' syntax if desired. Create an executable file (chmod +x) "life.l": <lang PicoLisp>#!/usr/bin/picolisp /usr/lib/picolisp/lib.l
(de meaningOfLife ()
42 )
(de lifemain ()
(prinl "Main: The meaning of life is " (meaningOfLife)) (bye) )</lang>
and an executable file (chmod +x) "test.l": <lang PicoLisp>#!/usr/bin/picolisp /usr/lib/picolisp/lib.l
(load "life.l")
(prinl "Test: The meaning of life is " (meaningOfLife)) (bye)</lang> Test:
$ ./life.l -lifemain Main: The meaning of life is 42 $ ./test.l Test: The meaning of life is 42
Python
Python has scripted main.
<lang python>#!/usr/bin/env python
- life.py
def meaning_of_life():
return 42
if __name__ == "__main__":
print "Main: The meaning of life is %s" % meaning_of_life()</lang>
<lang python>#!/usr/bin/env python
- death.py
from life import meaning_of_life
print "Life means %s." % meaning_of_life() print "Death means invisible scary skeletons."</lang>
Smalltalk
Note that the ScriptedMain package must be installed in order for test.st to access code from scriptedmain.st.
Example
<lang shell>$ gst-package -t ~/.st package.xml &>/dev/null
$ ./scriptedmain.st Main: The meaning of life is 42
$ ./test.st Test: The meaning of life is 42</lang>
package.xml
<lang xml><packages> <package> <name>ScriptedMain</name> <filein>scriptedmain.st</filein> <file>scriptedmain.st</file> </package> </packages></lang>
scriptedmain.st
<lang smalltalk>"exec" "gst" "-f" "$0" "$0" "$@" "exit"
Object subclass: ScriptedMain [ ScriptedMain class >> meaningOfLife [ ^42 ] ]
| main |
main := [ Transcript show: 'Main: The meaning of life is ', ((ScriptedMain meaningOfLife) printString); cr. ].
(((Smalltalk getArgc) > 0) and: [ ((Smalltalk getArgv: 1) endsWith: 'scriptedmain.st') ]) ifTrue: [ main value. ].</lang>
test.st
<lang smalltalk>"exec" "gst" "-f" "$0" "$0" "$@" "exit"
" PackageLoader fileInPackage: 'ScriptedMain'.
Transcript show: 'Test: The meaning of life is ', ((ScriptedMain meaningOfLife) printString); cr.</lang>
R
R does not have scripted main, but the feature is easily added with regular expressions.
scriptedmain.R
<lang R>#!/usr/bin/Rscript
meaningOfLife <- function() { 42 }
main <- function(program, args) { cat("Main: The meaning of life is", meaningOfLife(), "\n") }
getProgram <- function(args) { sub("--file=", "", args[grep("--file=", args)]) }
args <- commandArgs(trailingOnly = FALSE) program <- getProgram(args)
if (length(program) > 0 && length(grep("scriptedmain", program)) > 0) { main(program, args) q("no") }</lang>
test.R
<lang R>#!/usr/bin/Rscript
source("scriptedmain.R")
cat("Test: The meaning of life is", meaningOfLife(), "\n")
q("no")</lang>
Ruby
Ruby has scripted main.
<lang ruby># life.rb
def meaning_of_life
42
end
if __FILE__ == $0
puts "Main: The meaning of life is #{meaning_of_life}"
end</lang>
<lang ruby># death.rb
require 'life'
puts "Life means #{meaning_of_life}." puts "Death means invisible scary skeletons."</lang>
SAC
Makefile: <lang make>all: scriptedmain
scriptedmain: ScriptedMain.sac sac2c -o scriptedmain ScriptedMain.sac -Dscriptedmain
test: test.sac ScriptedMain.sac sac2c ScriptedMain.sac sac2c -o test test.sac
clean: -rm test -rm test.c -rm libScriptedMainTree.so -rm libScriptedMainMod.so -rm libScriptedMainMod.a -rm scriptedmain -rm scriptedmain.c</lang>
ScriptedMain.sac: <lang c>#ifndef scriptedmain module ScriptedMain;
- endif
use StdIO: all; use Array: all; export all;
int meaning_of_life() { return(42); }
- ifdef scriptedmain
int main() { printf("Main: The meaning of life is %d\n", meaning_of_life()); return(0); }
- endif</lang>
test.sac: <lang c>use StdIO: all; use Array: all; use ScriptedMain: all;
int main() { printf("Test: The meaning of life is %d\n", meaning_of_life()); return(0); }</lang>
Example: <lang sh>$ make $ make test $ ./scriptedmain Main: The meaning of life is 42 $ ./test Test: The meaning of life is 42</lang>
Tcl
<lang tcl>proc main {args} {
puts "Directory: [pwd]" puts "Program: $::argv0" puts "Number of args: [llength $args]" foreach arg $args {puts "Arg: $arg"}
}
if {$::argv0 eq [info script]} {
main {*}$::argv
}</lang>
UNIX Shell
Bash has scripted main.
scriptedmain.sh
<lang sh>#!/usr/bin/env sh
meaning_of_life() { return 42 }
main() { meaning_of_life echo "Main: The meaning of life is $?" }
if "$BASH_SOURCE" == "$0" then
main
fi</lang>
test.sh
<lang sh>#!/usr/bin/env sh source scriptedmain.sh meaning_of_life echo "Test: The meaning of life is $?"</lang>
ZX Spectrum Basic
On the ZX Spectrum, there is no main function as such, however a saved program can be made to start running from a particular line number by providing the line number as a parameter to save command. If the program is being merged as a module, then it does not run automatically. The following example will save the program in memory so that it starts running from line 500:
<lang zxbasic>SAVE "MYPROG" LINE 500: REM For a program with main code starting at line 500</lang>