|
On 15/01/15 11:55, Roberto Ierusalimschy wrote:
Now, how do you imagine these functions: 1. a consumer that is not guaranteed to have data available, like a nonblocking socket. Today it is data, err = read() If data is nil that means that read() could not actually read anything, so can not provide a value. Depending on how read() works, an error message could be useful or not. In the simplest case no error message is needed: no data means no data, do whatever you can. 2. A function that returns a boolean: __eq = function (a, b) return a == b end There is nothing special in returning a false.Actually there is. If 'read' can return 'false', you cannot use 'assert(read(...))' to check that no errors occurred. But that is not relevant here. What is relevant is that, if 'read' can read *anything*, of course it should be able to read 'nil', too. (Otherwise, how could it return the result of a query like "what was the result of the last call to 'read'" where that last call failed?)
Ok, here comes the stuff mailing-list-regrets are made of: I think you're wrong. :)
read() is not not supposed to read *anything*, only *values*. When it returns nil, it isn't retuning anything of what you wanted to get from the call: it failed. In that sense, the example you put is a sort of meta-programming concept, where you talk about the state of the program, not of the result of the call as seen in the application space. That this concept is not being expressible in the business logic looks natural to me: when I write a, say, web proxy, I handle concepts like streams, strings, lines and fields, not "calls that failed".
I /believe/ this only happens when you overload nil with meaning from your business logic. I see nil as a truly and only language-level concept. It occupies all the space outside the concepts and meaning and semantics you define in your program, and is the single only one doing that.The key point is: you cannot use a value to represent the absence of a value, at least not as a generic methodoly. So, if you need to return any value + error, you need more than one value (like 'pcall' does) or some other mechanism besides returns (like 'error'). That is a fact of life, and we are not going to solve it by throwing more values/non-values/semi-values/error-values into the language.
The interesting thing with pcall() is that it mixes two different universes of business-logic. One is the library: pcall receives a entity that is a "function", executes it, and can either succeed doing it or not. The other level is the function itself, which has it's own semanthics for parameters and returns. The trouble is not with nil, but having two independent actors providing semantics to two bits of code in the same call.
... My point is that, in the simpler and more common case when the function cannot return nil nor false and returns a message, false-msg might be better than nil-msg.
Both cases -nil and false- rest on the premise that in your business logic there is no meaning attached to have a function "return a nil | false". I see this a natural condition for nil, and clearly false with false :)
Jorge