lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


I like named arguments much more so than positional ones. In fact, I
hate positional arguments and refuse to use them. Therefore, all of my
functions look like this:

local myfunc = function(args)
  local name = args.name or nil
  local age = args.age or error("You have to pass me an age, dimwit.")

--...
end

This is relatively okay, but I tend to think of arguments that I pass
in as "special" and in need of being explicitly "syntax-ed." Having a
single argument called "args" requires me to take up the "this was
what I was thinking" slack in comments or when I assign default
values, which I may not actually need to do, but now kind-of-need-to
because there is no other code-way to say that I expect an argument to
be there.

I've thought some about how one might introduce some syntax sugar and
I now more fully-appreciate that finding a good way to accomplish this
goal has some potential ugliness.

At a minimum, it would be super-fancy if I could type something like this:

local myfunc = function{name, --optional or the name of the person
    age, --should be your age, in years, as a whole number
}

local args = ...
  --etc.
end

This has some coolness. I still need to do my default assignments and
error checking, but that's normal. I can at least see the arguments
that I expect and have a place to comment them. The reality is that I
imagine that lua could pretty much interpret this code as:

local myfunc = function(...)
local args = ...
  --...
end

.. and you know what? That's okay with me. It makes things clearer
_for future me_, even as it does nothing within the language.

So we could end my proposal there with a nice, simple, probably
(hopefully) low impact suggestion, which would help me to make things
clearer and not break anything for anyone else.

That said... one could imagine:

local myfunc = function{name = nil, --optional or the name of the person
  age = error("You have to pass me an age, dimwit.") --should be your
age, in years, as a whole number
}
  --...
end

This is cool for simple "this or that" assignments, which advances
things without tarting the language up, too much.

One can see how we could descend into hell with this approach by
asking how I might do error checking or other complicated maneuvers?

local myfunc = function{name = type(??) == "string" --etc...


That is, since the table isn't real yet, so much of what you do isn't
available until later. One approach to this would lead to all manner
of possible confusion (which I just got done arguing against!):

local myfunc = function(args = {name = type(args.name) == "string" and
args.name or args.name ~= nil and error("Has to be nothing or a
string") or nil, --should be a string
  age = args.age or error("You have to pass me an age, dimwit.")
--should be your age, in years, as a whole number
})
  --...
end


Realizing, of course, that "args" does not yet exist and so would run
afoul of Lua's scoping rules. We'd have to pretend that the scope
within a function's arguments parens was "other", which never ends
well.

Or, perhaps, it's as though you may take the assignment of defaults
within function arguments all of the way through by saying that these
rules always apply, even when table arguments are not used, such that:

function(local name = type(name) == "string" and name or name ~= nil
and error("Must be string or nothing") or nil, local age = age or
error("Need an age."))
--etc...
end

This is like saying that when you assign defaults within function
args, it's like you're short handing the subsequent:

local name = type(name) --etc.


I think I hate that solution, but I'm not sure. For now, how about try 3:


local myfunc = function{name = type((...).name) == "string" and
(...).name ) or (...).name  == nil and (...).name or error("Has to be
nothing or a string"), --should be a string
  age =(...).age or error("You have to pass me an age, dimwit.")
--should be your age, in years, as a whole number
}
  args = ...
end

Where '...' was permissible as the reference for the default value in
cases where a single table was the only accessible argument within the
function. If you wanted to get hyper-ugly, you could allow
"(...)[1].name" and still allow varargs. This translates into:

local myfunc = function(...)
 args= ...
args.name = type(args.name) == "string" and args.name or args.name ~=
nil and error("Has to be nothing or a string") or nil
args.age = args.age or error("You have to pass me an age, dimwit.")
--should be your age, in years, as a whole number

end

That seems to not break much...

I'm aware that this has probably been hashed outm ad naseum.  I
searched the archives for conversations related to this idea and while
I know that they are there, the closest that I could find were
comments related to "my_func{name="someone", age=32}", which I
understand and depend upon.

I'm just looking for a way to express what I expect within a table
argument and to do so in the same spirit as the sugar that we get with
a function call that has a single table as the argument. Of course, I
only propose this if it contributes to Lua's simplicity.

Best Regards,

Andrew Starks