4 ms·
They're recognizing for the first case that if you have to resort to it you're trying to cover for some sort of deficiency in the language. Which is good. I th
by crdoconnor 9y ago
They're recognizing for the first case that if you have to resort to it you're trying to cover for some sort of deficiency in the language. Which is good.
I think the kind of thing they're doing would be possible without code generation in a good dynamically typed language or a language with a feature like F#'s type providers, but maybe swift doesn't allow it.
The second use case (generating test mocks) is a pretty bad reason to use code generation IMHO. Instead they should be generating non-turing complete code representing the mock (JSON or something).
- Robin_Message 9y agoThe mock is called by Swift code in test cases (that's the point of a mock) so how would generating some JSON help?
- crdoconnor 9y agoActually I'm now starting to think that the idea I had in mind (generate the mocks on the fly using JSON data) might not be possible.
- lomnakkus 9y agoIndeed, and I think people are missing a lot of nuance here. Code generation to avoid parametricity is (AFAICT) unequivocally a bad thing. Parametricity in code is almost always a good thing because it constrains what any implementation can do -- and thus gives you guarantees (subject to compiler correctness). Code generation to avoid boilerplate in a sane way? IMO it's actually a pretty low-tech and simple way to avoid huge amounts of repetetive work, especially if you're targeting multiple platforms in different languages. Obviously, there's LISP-like macros and maybe pseudo-dependent types in Haskell (Servant) which may buck the trend[1], but I, for one, actually appreciate the simplicity of a bit of actually generated "on disk" code when it's appropriate. IME code generation really shines when you're approaching the business domain, i.e. closer to the "edges" of your program/service. This is where "generic" solutions tend to not work as well just by virtue of every business case being slightly different. For logic that works on top of core data structures like vector-of-X or vector-of-Y? Hell no! You're writing lots of code that 'talks to' vector-of-$ all the time and you'd be crazy to want to have to duplicate all of that. [1] Servant actually seems to be a sort of "define the types" and generate code for all the platforms, so that may actually be an example of my "sane" way. Whatever. LISP-like macros obviously kind of avoid the point entirely because they're never "materialized" as source. Just wanted to bring them up because they tend to be brought up in these discussions, regardless.