lua-users home
lua-l archive

Re: Ternary operator patch

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


On Tue, Sep 14, 2010 at 1:17 PM, Drake Wilson <drake@begriffli.ch> wrote:
> The primary currently-valid plain-Lua form of the above that works
> correctly is:
>
>  -- (declaration if necessary) local value;
>  if a_is_valid then
>    value = do_something_with(a)
>  else
>    value = some_default
>  end
>
> with possible reformatting.  However, this can require the creation of
> extra temporaries instead of being able to embed the whole thing into
> an argument in a function call, for instance.  The target name(s) are
> also duplicated, which could lead to other errors during maintenance.
> So it works and is semantically clean but doesn't compose well.
Those are good points, which I restate as follows. To me, indicators
of code quality include
 - immutability of variables
 - minimal variable scope
 - minimal repetition
because they reduce the number of possible meanings of code, making it
easier to grasp and analyze. For example, this code:
 local x = f() or y
is much superior to its statement-like form,
 local temp = f()
 local x
 if temp then x = temp else x = y end
on each of the above three points: x is set once (in fact, in C it can
be declared "const", and in Lua it is highlighted as immutable by
LuaInspect), there is no "temp" variable whose scope extends beyond
its use, and the short expression has immediately recognizable
meaning.
When Lua lacks an expression-like syntax for something, I tend to
resort to writing it in a way that mimics it. To use the above
example, if the syntax "f() or y" were not available, I might have
instead written it as
 local _temp = f()
 local x; if _temp then
 x = _temp
 else
 x = y
 end
To take a real-world example, you'll find in LuaInspect some code that
defines a variable "argvalues_concrete" with something like this:
 local argvalues_concrete = true; do -- true iff all function args known
 if #ast >= 2 then
 local firstargvalue; if isinvoke then
 firstargvalue = ast.valueself
 else
 firstargvalue = ast[2].value
 end
 if unknown(firstargvalue) then
 argvalues_concrete = false
 else -- test remaining args
 for i=3,#ast do
 if unknown(ast[i].value) then
 argvalues_concrete = false
 break
 end
 end
 end
 end
 end
This is pretending to simulate the following expression, if it were
allowed in Lua:
 local argvalues_concrete = do
 if #ast >= 2 then
 local firstargvalue = if isinvoke then
 ast.valueself
 else
 ast[2].value
 end
 if unknown(firstargvalue) then
 false
 else
 for i=3,#ast do
 if unknown(ast[i].value) then
 break false
 end
 end
 true
 end
 else
 true
 end
 end
To explain that syntax above...Block statements are allowed inside
expressions provided the last statement in the block is replaced by an
expression that is to be returned by the block. This is similar to
Eric Man's suggestion above for `if` statements but generalized to
other statement types. I also allow `break` to have a return value.
I propose this syntax as an answer to David Kastrup's proposal:
On Tue, Sep 14, 2010 at 7:23 AM, David Kastrup <dak@gnu.org> wrote:
> I think that local variables and assignments do a good job for that in
> an imperative language. If other people disagree, then one should
> figure out how to smoother wrap the existing control structures into
> expressions rather than make functionally equivalent things that look
> utterly different.
That example I gave above might best be made into a function though,
and as written the translation is trivial.
Here's another example appearing immediately after:
 -- list of values of arguments.
 local argvalues; do
 argvalues = {n=#ast-1}
 for i=1,argvalues.n do
 argvalues[i] = ast[i+1].value
 end
 if isinvoke then argvalues[1] = ast.valueself end
 end

AltStyle によって変換されたページ (->オリジナル) /