A request arrives with an empty value. Does it mean leave the old value alone, clear it, or reject the request? The answer may feel obvious to the person writing the client and equally obvious, in a different direction, to the person writing the server. That disagreement is the beginning of an expensive kind of simplicity. I would rather spend a little precision at the boundary than ask every caller to rediscover the same unwritten rule.
Giorgi Kobaidze’s essay comparing natural languages and programming-language tradeoffs uses an analogy to discuss explicitness and context. I read it as an analogy, not a scientific classification of human languages. It prompted a smaller engineering question: where should a machine interface permit interpretation, and where should it demand an exact choice? A hypothetical contact-edit endpoint makes that question concrete.
Give absence its own meaning
Imagine a contact record with a required identifier and an optional nickname. We are designing a custom edit operation, not relying on an unspecified patch standard. In this contract, an omitted nickname leaves the current nickname unchanged. A nickname explicitly set to null clears it. An empty string is rejected because this product does not treat a blank nickname as useful stored data. These are proposed rules for the example. Other products can choose differently, but their clients still need one documented answer.
The distinction produces three readable requests. An object containing only the identifier edits no nickname. An object with nickname set to null requests a clear. An object with nickname set to an empty string produces a validation error that explains the accepted options. The server should not silently turn the third request into the second unless that conversion is the published contract. Silent generosity can be costly when a client accidentally serialises a missing field as an empty string.
Identifiers need another deliberate choice. Suppose an external contact identifier has the form customer:12. Treating the suffix as the entire identifier discards the namespace that tells the caller what kind of record it names. I would require the stated string form at this boundary and reject the wrong type with a useful message. This does not mean all identifiers should be strings or that numerical types are dangerous. It means the representation should preserve the identity rule this particular interface has promised to its callers.
Separate convenience from the stored contract
A user interface may offer a convenient clear button instead of asking a person to type null. That is a translation the client owns: the visible action maps to the documented request. The server does not have to infer intention from a blank field. This separation also helps when there are several clients. A mobile form, an import tool and an administrative interface can present different controls while using the same explicit operation. Convenience at the surface does not require ambiguity in the request.
I would write a compact acceptance matrix before implementing the endpoint. It would cover omitted nickname, explicit null, empty string, valid text and a value of the wrong type. For each row, it would state both the response and the resulting stored value. Checking only the response can miss a server that returns success without applying the intended change. Checking only the stored value can miss an interface that reports an error after making a mutation. The pair is the observable contract.
The matrix should also include a failed request followed by a read. If a required validation fails, the earlier record should remain intact under this proposed operation. A caller should not discover that half of an edit was applied before another field was rejected. Whether the implementation uses a transaction or another mechanism is an engineering choice; the behavioural requirement needs to be settled first. These examples are a contract design, not an executed test suite or a claim about an existing service.
Decide how changes will be explained
Once clients rely on these meanings, changing them is a compatibility decision. If empty strings were previously accepted, rejecting them may break a caller even when the new rule feels cleaner. I would identify those consumers and choose a documented transition rather than relabelling the change as validation cleanup. An API’s history is part of its behaviour. The same input changing meaning can be more disruptive than a new field, because the old request continues to look perfectly valid to its sender.
Ambiguity is sometimes useful in conversation because people can ask what was meant. An unattended client usually cannot. That is why my budget for interpretation would be small at a write boundary and more generous in the interface that helps a person prepare the request. The next time an endpoint accepts several forms of nothing, I would ask which ones represent distinct actions. Naming them now may save the person debugging a disappearing nickname from having to reconstruct our intentions later.

