Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

Re: for loop question



On Nov 3, 10:37pm, Ray Andrews wrote:
} Subject: Re: for loop question
}
} On 11/03/2014 06:43 PM, Bart Schaefer wrote:
} > The 0 is appended because [ -n "$TLC[i]" ] does not produce any output,
} But in
} 
}        if [ -n "$TLC[i]" ]
} 
} ... the test must surely produce an answer of some sort.

The *nix command paradigm is organized around two concepts:  (1) passing
data through file streams, of which stdin and stdout are the basis for
connecting commands as pipelines; and (2) the input argument array and
integer exit status mapped straight onto C's main() function, with zero
for success and any nonzero value for failure.  The idea is that there
are many ways to fail (among which you might want to distinguish) but
only one way to succeed, and zero is a conviently unique value.

Shells are designed for linking together other programs (some of which
are built in to the shell) using these two paradigms.  Conditions like
"if" and "while" test the exit status; pipelines and substitutions use
the data streams.  If the exit status and the data stream were mixed
together, you could never pass pure data through a pipeline, and you
could never test for program failure without sticking your fingers in
its data stream.

$? [and $status in csh and zsh] exists for the purpose of transforming
an exit status back into an argument list; "echo" [and "print"] is for
transforming argument lists into stream data; "test" transforms an
argument list into an exit status; "read" [and $(...) which originally
was `...`] converts a stream to an argument list.  Plug these four
things together in the right ways and you can build any program linkage
you need.  This is the basic elegance of the shell.

Math operations and all the various parameter manipulations were bolted
onto the top of this model for efficiency, adding complexity for speed
at the cost of elegance.  Originally one had to call programs like
"expr" and "basename" to do all that work, and read back the results
from the their stdout streams.  (More ways to transform argument lists
into stream data.)  But that required forking processes and setting up
data pipes and was slow and expensive, so ...

} Yes or no. If that answer is not acceptable as 'arithmetic', then what
} is it?

It's an exit status, which is a thing separate from the data model.  If
you want it as data (argument list or stream), you have to convert it.
If "test" produced both an exit status and an output stream, you'd have
to be constantly throwing away one or the other, so it only produces
the exit status because that's what you want most often, and you use $?
if you need that in another form.

Shell math works on argument lists (which happen to be interpreted as
variable names and numbers), not on exit status values.  (( )) is just
syntactic sugar for converting numbers to exit status, and $(( )) is
sugar for converting from numbers back to arguments.

I won't quote the rest of your questions, because I think the above has
answered them.

If you REALLY want to understand why shells are the way they are, you
need to study the history of C and UNIX.



Messages sorted by: Reverse Date, Date, Thread, Author