If you see it differently you are implicitly assuming a non-formalist perspective on what "validation" means. Tell us about it.
"A square is a rectangle" means "A square is a TYPE of rectangle" (at least, that is what I am parsing it as).
"Parsing is Validation" means Parsing is isomorphic to Validation.
How do I know? Because that is how I want you to parse it.
In that case your former statement that 'The word "is" implies an isomorphism' seems to be wrong.
Are you talking about a bijective mapping or are you saying it's a synonym for identical?
Because the former doesn't make any sense here and the latter is not true.
Red is a color does not imply that all colors are red.
"Red is a color" can be formalized as "Red is a type of color" or "Red is member of set Colors".
You can't formalize "Color is red" because it doesn't mean anything.
When I say "Parsing is validation" I am using the verb "is" to mean an isomorphism.
Good luck with that.
Two things are the same type of thing if they share all of their extensional properties.
That is what it means for two things to be identical/equal.
For example let's say that I have written an HTTP API that accepts application/x-www-form-urlencoded data to one of its endpoints. Let's say `POST /users`, and this is where the client-side application posts data to.
Now I can implement this in many ways. I can for example define
pub struct Person {
name: String,
phone_number: String,
}
But how I populate this struct can determine whether I am actually parsing or not, even if most of the code aside from that is the same.And of course I could go further and define types for the name and the phone number but in this case lets say that I have decided that strings are the proper representation in this case.
If the fields of my structs were directly accessible
pub struct Person {
pub name: String,
pub phone_number: String,
}
And in my HTTP API endpoint for `POST /users` I do the following: // ...
let name = post_data.name;
let phone_number = post_data.phone_number;
let norwegian_phone_number_format = Regex::new(r"^(\+47|0047)?\d{8}$").unwrap();
// ...
And I didn't bother to write out the rest of the code here for this example but you get the gist.The point is that here I am doing some rudimentary validation on the phone number, requiring it to be in Norwegian format. But I am enforcing this in the implementation of the handler for the HTTP API endpoint, rather than in the data type itself.
Whereas if I was instead doing
pub struct Person {
name: String,
phone_number: String,
}
impl Person {
pub fn try_new (name: String, phone_number: String) -> std::result::Result<Self, PersonDataError> {
// ...
let norwegian_phone_number_format = Regex::new(r"^(\+47|0047)?\d{8}$").unwrap();
// ...
}
}
Now I've moved the validation into an associated function of the type itself, and I've made the fields of the struct unaccessible from the outside.And in this manner, even though my validation is still rudimentary, and a type purist might find the type insufficiently constrained, I have indeed in my own book gone from just validation to actual parsing. Because I have made it so that the construction of the type enforces the constraints on the data.