How to write a macro that takes a variable number of arguments

This is quite easy with xparse and \NewDocumentCommand, having two optional arguments, however, you need to check for their existence.

Please note that oo could be replaced by gg to allow for optional {}{} arguments, but that's not recommended, but see below in this answer as an alternative.

\documentclass{article}

\usepackage{xparse}

\NewDocumentCommand{\com}{oo}{%
  \lambda%
  %Check if the first arg is given
  \IfValueT{#1}{%
    % Now check if has a 2nd argument as well. 
    \IfValueTF{#2}{% Yes, the 2nd one is present, use {f}(x) style
      \{#1\}(#2)%
    }{% No, use [f] style
      [#1]% 
    }%
  }%
}

\begin{document}

$\com$

$\com[f]$

$\com[f][x]$

\end{document}

enter image description here

Update with gg type (use it with care!) and another optional argument to use that instead of \lambda

\documentclass{article}

\usepackage{xparse}

\NewDocumentCommand{\com}{oo}{%
  \lambda%
  %Check if the first arg is given
  \IfValueT{#1}{%
    % Now check if has a 2nd argument as well. 
    \IfValueTF{#2}{% Yes, the 2nd one is present, use {f}(x) style
      \{#1\}(#2)%
    }{% No, use [f] style
      [#1]% 
    }%
  }%
}

\NewDocumentCommand{\comother}{O{\lambda}gg}{%
  #1%
  %Check if the first arg is given
  \IfValueT{#2}{%
    % Now check if has a 2nd argument as well. 
    \IfValueTF{#3}{% Yes, the 2nd one is present, use {f}(x) style
      \{#2\}(#3)%
    }{% No, use [f] style
      [#2]% 
    }%
  }%
}


\begin{document}

$\com$

$\com[f]$

$\com[f][x]$


$\comother$

$\comother{f}$

$\comother{f}{x}$

% Now with \beta instead of \lambda

$\comother[\beta]$

$\comother[\beta]{h}$

$\comother[\beta]{h}{y}$
\end{document}

enter image description here


Of course, the syntax uses the standard LaTeX convention of optional arguments in square brackets, in this case for both optional arguments.

Also, the OP implied that the command should be used not in math mode, so I have accommodated that.

\documentclass{article}
\newcommand\com[1][\relax]{\ifx\relax#1$\lambda$\else\def\firstarg{#1}\comhelp\fi}
\newcommand\comhelp[1][\relax]{\ifx\relax#1$\lambda [\firstarg]$%
  \else$\lambda \{\firstarg\}(#1)$\fi}
\begin{document}
\com\quad\com[f]\quad\com[f][x]
\end{document}

enter image description here

For a version that instead oeprates in math mode, here it is:

\documentclass{article}
\newcommand\com[1][\relax]{\ifx\relax#1\lambda\else\def\firstarg{#1}\comhelp\fi}
\newcommand\comhelp[1][\relax]{\ifx\relax#1\lambda [\firstarg]%
  \else\lambda \{\firstarg\}(#1)\fi}
\begin{document}
$\com\quad\com[f]\quad\com[f][x]$
\end{document}

Here's a LuaLaTeX-based solution. It works as a preprocessor: The Lua function comscan runs at a very early stage of processing, before TeX gets to do its usual work. The Lua function find all instances of \com and replaces with a different macro, depending on whether \com is found to have 0, 1, or 2 arguments.

enter image description here

% !TeX program = lualatex
\documentclass{article}
\usepackage{luacode}
\begin{luacode}
function comscan ( s )
  s = string.gsub ( s , "\\com(%b{})(%b{})" , "\\lambda\\{%1\\}(%2)" )
  s = string.gsub ( s , "\\com(%b{})", "\\lambda[%1]" )
  s = string.gsub ( s , "\\com(%A)" , "\\lambda%1" )
  return ( s )
end
luatexbase.add_to_callback( "process_input_buffer", comscan, "comscan" )
\end{luacode}
\providecommand{\command}{aaa} % dummy command
\begin{document}
$\com{f}{x}$, $\com{g}$, $ \com $, \command
\end{document}