D
Don Y
Hi Malcolm,
That was the point I was trying to bring out. Do you call the
"parameter" passed to it a "programming error"? That would imply
the caller had the responsibility of checking it for correctness
(eliminating the need for the parser's functionality).
I think "expect" is overly cynical. I would say "you PREPARE FOR
<any input> to be 'malformed'" -- since you can't control the
outside world.
Returning to my original example (scanning a string of chars to
extract the numeric value expected to be represented therein),
that function (pure function using your terminology) can report
the nature of any "incompatible input" to any degree of detail
that it considers appropriate. Not just "hey, I couldn't find
a valid 'number' in this mess..."
Those reports make sense in the context of a function that
is responsible for extracting the numeric value represented by a
string of characters. REGARDLESS OF WHAT THAT NUMBER IS BEING
USED FOR. And, regardless of the actual value!
E.g., if that routine also had the responsibility of testing that
the value was within a particular set of bounds, it could add
"Value specified exceeds the maximum allowed.", etc. to its
lexicon of errors.
None of these reports need to know whether the "value" is being
used as a representation of AGE, azimuth/elevation, speed,
stock market index, etc. You are dealing with a *value* -- just
like when you complain that the first letter of a sentence is
not capitalized (you don't even look at the CONTENT of the
sentence to understand the nature of that "report").
But, you obviously don't want that "pure function" to become
a "procedure" by virtue of informing the user directly of
this error (this would also badly contort the design of
your code).
Nor do you need to return the text of the message to the caller!
(how do you decide whether you should return the en_US version
of the message or the es version?)
Instead, return an identifier that allows the caller to fetch
a version of the error that *it* considers appropriate.
It, in turn, can embellish -- or replace -- that message with
something appropriate to its understanding of the application.
E.g., perhaps the caller is responsible for obtaining the
coordinates of a point in 2D space. It *uses* the called routine
to parse the string (that is provided to *it* by ITS caller!)
for the X coordinate, then the Y coordinate. An error reported
during the first parse might cause it to report an error to
*it's* caller like: "Bad value for X coordinate." AUGMENTED
by the report returned by the function that had actually
detected the lower level error "Non-numeric character encountered
in value."
Or not (depends on the range of errors that you document
get_point() as reporting). You could, instead, ignore the
detail presented to you by any of your "underlings" and
just report: "Bad point".
A parser is a pure function (assuming IO is not handled by the
function). It takes one sequence of bits - the script - and it returns
a another sequence of bits - the result. So all it's doing is
shuffling bits about in memory. If a pure function calls a procedure,
it's no longer a pure function.
Understood.
However most parsers will do IO. That leads to a question. If a pure
function takes a function pointer as a parameter, and that parameter
is to a procedure, is it still a pure function? The answer is no, but
here the classification is beginning to lose its usefulness.
Parsers are an obvious case of invalid input not being reasonably
caught by caller. You could require that caller pass only correct
scripts to the parser, but that means caller has to do almost as much
work as the parser itself to verify that the script is correct. So you
That was the point I was trying to bring out. Do you call the
"parameter" passed to it a "programming error"? That would imply
the caller had the responsibility of checking it for correctness
(eliminating the need for the parser's functionality).
have to treat malformed scripts as part of the normal flow control of
the parser. The caler's then got the problem. If the script was typed
into the source byt he programer, it's an internal error. If the
script was provided by outside, it should usually be treated as normal
flow control - you expect complex user-provided scripts to be
malformed.
I think "expect" is overly cynical. I would say "you PREPARE FOR
<any input> to be 'malformed'" -- since you can't control the
outside world.
Returning to my original example (scanning a string of chars to
extract the numeric value expected to be represented therein),
that function (pure function using your terminology) can report
the nature of any "incompatible input" to any degree of detail
that it considers appropriate. Not just "hey, I couldn't find
a valid 'number' in this mess..."
Those reports make sense in the context of a function that
is responsible for extracting the numeric value represented by a
string of characters. REGARDLESS OF WHAT THAT NUMBER IS BEING
USED FOR. And, regardless of the actual value!
E.g., if that routine also had the responsibility of testing that
the value was within a particular set of bounds, it could add
"Value specified exceeds the maximum allowed.", etc. to its
lexicon of errors.
None of these reports need to know whether the "value" is being
used as a representation of AGE, azimuth/elevation, speed,
stock market index, etc. You are dealing with a *value* -- just
like when you complain that the first letter of a sentence is
not capitalized (you don't even look at the CONTENT of the
sentence to understand the nature of that "report").
But, you obviously don't want that "pure function" to become
a "procedure" by virtue of informing the user directly of
this error (this would also badly contort the design of
your code).
Nor do you need to return the text of the message to the caller!
(how do you decide whether you should return the en_US version
of the message or the es version?)
Instead, return an identifier that allows the caller to fetch
a version of the error that *it* considers appropriate.
It, in turn, can embellish -- or replace -- that message with
something appropriate to its understanding of the application.
E.g., perhaps the caller is responsible for obtaining the
coordinates of a point in 2D space. It *uses* the called routine
to parse the string (that is provided to *it* by ITS caller!)
for the X coordinate, then the Y coordinate. An error reported
during the first parse might cause it to report an error to
*it's* caller like: "Bad value for X coordinate." AUGMENTED
by the report returned by the function that had actually
detected the lower level error "Non-numeric character encountered
in value."
Or not (depends on the range of errors that you document
get_point() as reporting). You could, instead, ignore the
detail presented to you by any of your "underlings" and
just report: "Bad point".