public static IList<Ephraimite> FindEphraimitesToKill(IList<Ephraimite> ephraimites)
{
IList<Ephraimite> ephraimitesToKill = new List<Ephraimite>();
foreach (Ephraimite ephraimite in ephraimites)
{
if (ephraimite.Speak("shibboleth") == "sibboleth")
{
ephraimitesToKill.Add(ephraimite);
}
}
return ephraimitesToKill;
}
Now, the same in (imperative-style) OCaml: let findEphraimitesToKill ephraimites =
let ephraimitesToKill = ref [] in
List.iter (fun (ephraimite) -> begin
if speak(ephraimite, "shibboleth") = "sibboleth" then
ephraimitesToKill := !ephraimitesToKill @ [ephraimite]
end) ephraimites ;
ephraimitesToKill;;
See how much less we had to specify the type of what we're handling here? And things would have gotten easier if we used functional-style OCaml, but that's not entirely a fair comparison.So hypothetically it should be possible to write a C# compiler that would, if type annotations were omitted in some places, be confident enough to assign a sensible default, which is why we call the current version verbose. Although I suppose it's slightly more complicated than that. (Interfaces, if we want to have them, need to be explicitly declared as there are potentially many interfaces that could be used for a given object, and the rigidity imposed by redundant type declarations could help with the health of large and long-lived codebases.)