← Code Compare

Command-line Args

The shared task: read the program's command-line arguments and print each one, numbered. The big split is how the args reach your code - in Erlang and LFE an escript hands them straight to main(Args) as a list of strings; Elixir exposes them through System.argv/0; Gleam (which has no global state) loads them via the argv package's argv.load().arguments; and Lua reads the global arg table, where arg[0] is the script name and the positive indices hold the actual arguments. Notice too that the BEAM languages hand you plain Erlang strings/charlists or binaries, while Lua's arg is a 1-indexed table you walk with ipairs.

Show: ErlangElixirGleamLFELuerl
Erlang
#!/usr/bin/env escript

%% An escript's entry point is main/1; Args is a list of strings
%% (charlists), one per command-line argument.
main(Args) ->
    io:format("~p arguments:~n", [length(Args)]),
    %% Number them by zipping with a 1.. index, then print each.
    lists:foreach(
        fun({I, Arg}) -> io:format("  ~p: ~s~n", [I, Arg]) end,
        lists:zip(lists:seq(1, length(Args)), Args)
    ).
%% $ escript args.erl one two three
%% => 3 arguments:
%% =>   1: one
%% =>   2: two
%% =>   3: three

An escript receives the command-line arguments as the single list passed to main/1; here lists:seq/lists:zip number them and lists:foreach prints each charlist with ~s.

Elixir
# System.argv/0 returns the arguments as a list of binaries (strings).
args = System.argv()

IO.puts("#{length(args)} arguments:")

args
|> Enum.with_index(1)
|> Enum.each(fn {arg, i} -> IO.puts("  #{i}: #{arg}") end)
# $ elixir args.exs one two three
# => 3 arguments:
# =>   1: one
# =>   2: two
# =>   3: three

Elixir reads the arguments with System.argv/0 (a list of UTF-8 binaries); the pipeline pairs each with a 1-based index via Enum.with_index/2 and prints it with Enum.each/2.

Gleam
import argv
import gleam/int
import gleam/io
import gleam/list

pub fn main() -> Nil {
  // argv.load() reads the arguments on either target; .arguments
  // is a List(String) excluding the program name.
  let args = argv.load().arguments

  io.println(int.to_string(list.length(args)) <> " arguments:")

  // index_map gives (value, index); add 1 for human numbering.
  list.index_map(args, fn(arg, i) {
    io.println("  " <> int.to_string(i + 1) <> ": " <> arg)
  })
  Nil
}
// $ gleam run -- one two three
// => 3 arguments:
// =>   1: one
// =>   2: two
// =>   3: three

Gleam has no ambient globals, so the argv package's argv.load().arguments returns a typed List(String); list.index_map walks it with a 0-based index that we shift to 1 for display, converting numbers with int.to_string.

LFE
#!/usr/bin/env lfescript

;; An lfescript's entry point is (main args), where args is the
;; same list of charlist strings Erlang's escript would hand you.
(defun main (args)
  (io:format "~p arguments:~n" (list (length args)))
  (lists:foreach
    (lambda (pair)
      (case pair
        (`#(,i ,arg) (io:format "  ~p: ~s~n" (list i arg)))))
    (lists:zip (lists:seq 1 (length args)) args)))
;; $ lfescript args.lfe one two three
;; => 3 arguments:
;; =>   1: one
;; =>   2: two
;; =>   3: three

An lfescript mirrors Erlang's escript: (main args) gets the argument list, and the same lists:zip/lists:foreach BEAM functions number and print each one, with the tuple destructured by a #(i arg) pattern.

Luerl
-- Lua exposes arguments in the global 'arg' table: arg[0] is the
-- script name, and arg[1], arg[2], ... are the actual arguments.
print(#arg .. " arguments:")

-- ipairs walks the positive integer keys (1..#arg) in order,
-- skipping arg[0] and any negative interpreter flags.
for i, value in ipairs(arg) do
  print("  " .. i .. ": " .. value)
end
-- $ lua args.lua one two three
-- => 3 arguments:
-- =>   1: one
-- =>   2: two
-- =>   3: three

Standard Lua puts the arguments in the global arg table where arg[0] is the script path and arg[1..] are the user arguments; #arg counts them and ipairs iterates the 1-based positive indices, leaving arg[0] out.