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 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(1); } } 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 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 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.
std::env::args()less convenient thanString[] args? You are only going "out of your way" in Rust because you wrote a separatecmainfunction and called it from the realmainfunction. Your simple program would be a lot simpler if you just wrotefor arg of std::env::args()in themainfunction. Likewise I'm not sure howstd::process::exit(...)is significantly less convenient thanreturn. These are things you will write at most once per project; it's more inconvenient to type#include <stdio.h>in C, when modern languages don't hide console output behind ... $\endgroup$std::env::args()andstd::process::exit(...)are more convenient than declaring the args as a parameter ofmainand returning from it, because you can call them from anywhere in a program. $\endgroup$std::env::args()is longer thanargv, but not longer once you add the parameter declarationString[] argv. As for parsing the args and passing them around, absolutely, but your argument parser needs to access the arguments, and it's more convenient for it to fetch them fromstd::env::args()itself than for you to have to pass them along yourself. Particularly, you are probably using a library likeargto do the parsing, and that library's API is simpler if it doesn't require you to be a middleman. $\endgroup$