C/C++ has an entrypoint int main(int argc, char **argv);, which provides the program with the arguments passed to it and a way to signal back the result:
#include <stdio.h> int main(int argc, char **argv) { // Or it could be int main(void); if the arguments are not needed for (int i = 0; i < argc; i++) printf("%s\n", argv[i]); return 69;1; } More "modern" languages such as Java and C# still provide the arguments, but hide away the result behind an explicit call to exit with a specific exit code:
public class Main { public static void main(String[] args) { // C# main is usually void Main(string[] args), but any combination of // int|void Main(string[] | void) is allowed. for (String arg : args) System.out.println(arg); System.exit(691); } } Rust and Go go even further and hide the argv, which makes me go out of my way to get the arguments and return the result:
fn cmain(argv: Vec<String>) -> i32 { for arg of &argv { println!("{}", arg); } return 69;1; } fn main() { // Rust main is usually fn main() -> (); // It can be fn main() -> Result<(), E: std::fmt::Debug>; // but that still doesn't allow user-specified exit codes // and more about supporting Rust's func()? syntax std::process::exit(cmain(std::env::args().collect())); } Some languages such as Python and Javascript do not have the concept of a main function, thus they need explicit calls to get arguments and return results. I find myself writing a main function anyway when using those languages:
function main(argv: string[]): number { for (const arg of argv) console.log(arg); return 69;1; } process.exit(main(process.argv.slice(2))); Why do modern languages stop exposing the arguments and exit code through the main function? It's clear they do support the concept of arguments and exit codes, so I guess it's the design decision reasonings that I'm curious about and cannot find.