[stringtemplate-interest] On Pragmatism Violating Purity For The Win
Joseph Grace
ockham at gmail.com
Mon Oct 19 11:58:40 PDT 2009
*First, a clarification. I finally found the canonical name for my
"Principle of Generous Acceptance". It is the Robustness
Principle<http://en.wikipedia.org/wiki/Robustness_Principle> (also
"Postel's Principle"). (Apologies for not finding it on my previous
search!)
However, I still prefer my phrasing of it "Be strict in what you generate,
but generous in what you accept."
Zenaan Harkness* wrote at *Sun Oct 18 18:22:26 PDT 2009:*
> If we added native.if, are there other operators you see
> being useful in the native.* library?
I am not looking to add operators other than "if.*" to the core language.
The ST philosophy is strict separation of concerns. Even the existing
"if" is a violation of strict separation in that ST inspects an aspect
of the model albeit in a very tidy way. The recognition of a second
"if" is another step toward such pragmatism. I believe the
"Robustness Principle" (strict in what you generate, generous in what
you accept) explains why these "if.*" are so important even though
(strictly speaking) they violate the purity of the language. Add
"if.*" but only in a very controlled fashion, e.g., "if.null". I do
not suggest ST be littered with operators and violations of model/view
separation.
> Modifying ST into 'platform specific' variants is a significant
> change if it were undertaken.
That's not my intent or intended suggestion. The only supported
compatibility variant as envisioned would be the one instruction,
"native.if". The rest of the "native.*" namespace would be for user
customizations (unsupported, Use At Your Own Risk).
> A native.* library would be good to think/ plan for in advance
> though, rather than one feature at a time, don't you think?
I'm thinking of "native.*" more as opening the door to user
extensions, not as a new part of the language. Mostly for ease of
use, compatibility, and only a little bit of "Awaiting Further
Developments" if you will, to see what happens from user extensions.
-=-
The basic existence "if" is a practical necessity, and has been shown
largely "necessary and sufficient" for ST just not totally practical.
The question becomes how to handle multiple "if"s in ST. I believe
the answer is to recognize that "necessary and sufficient" is not
necessarily sufficient! "Practical" is also important, and I think
that's because of the "Robustness Principle", i.e., "generous in what
you accept" as in making ST easy to use (without losing ST's strength
and spirit of purity).
Hence adding multiple "if"s is practical, but how should it be
handled? There's the rub.
I can see multiple options depending on how seriously one takes ease
of use, "Robustness Principle", and attitude toward ease of adoption
of ST (and how to go about it). Just looking at ST language merits
(and not, e.g., a marketing campaign!), I see the options as follows:
1. Should ST add a single monolithic operator, "ifnull". Is that
practical? What if there are other "if" operators that are desirable
(as already mentioned on this list)?
2. Should ST then add a clean syntax for multiple "if.*" language
independent operators? Is that practical? What if a common use case
is to dovetail ST onto an existing system, in a native language, and
the native language "if" is not found in ST? What if ease of use is
compromised without native language friendly "if"?
3. Should ST then add a "native.if" which handles language native
"if" but in a tidy, automatically flaggable (command line flag ->
warning/errors), but built-in fashion? Does this increase
language/legacy friendliness enough, or does "Robustness Principle"
generosity suggest that users may have unforeseeable user-specific and
domain specific needs beyond "native.if"?
4. Should ST then make "native.*" a generic hook for user-specific
augmentation of the language to suit their specific needs?
"native.if" would then be the exemplar (code template for "native.*"
extensions) for users to build additional hooks. The hooks may be few
and far between, or become shared. However, at least users would have
power to augment ST specifically for their needs (impure or not). Now
users can customize ST in a controlled fashion ("native.*" operators)
using their language of choice for their application(s). Would
"native.*" extensions be automatically portable across all ST users?
Of course not, since "native.*" extensions would be
language/application specific. Would "native.*" extensions be
shareable at all? Yes, "native.*" extensions could be shared among ST
users who share a common language/application (e.g., Ruby on Rails for
Ruby ST --- if it existed!-). Is that desirable? I think so.
So those are the options as I see them. The big difference is
philosophy about where ST is headed, and how to get there? Big steps
or baby steps? I don't know, but I don't like monolithic design, and
do like options.
To recap:
1. "ifnull" (one new keyword)
2. "if.null", "if.empty", et al. (syntax extensions for a few
additional common ST use cases, tidy "if.*" extensibility)
3. above + "native.if" (above + language compatible "native.if" for
native language compatibility use case)
4. above + "native.*" (above + user extensible syntax hook for
open-ended user and application specific use cases)
IMO, these are all reasonable approaches.
I view #1 as a band-aid, old school (a la Bourne shell keywords) with
little future extensibility other than adding more monolithic
keywords. #1 adds a "fix" with low-risk to purity, and low potential.
I see #2 as more promising. It acknowledges there's a bit more to the
issue ("Robustness Principle"'s Generous Acceptance and ease-of-use)
than a single "ifnull" and explicitly leaves room for tidy "if.*" ST
extensibility. #2 adds a more sophisticated fix with low-risk, and
some future potential (through the "if.*" syntax).
I like #3's extensibility since it takes the extensibility syntax to a
natural progression and adds a hint of native language compatibility,
"native.if". #3 has #2's sophisticated fixes, and adds a
compatibility feature for native languages. Philosophically, this
could be considered risky (portability violation). OTOH, I believe
the nod to native language compatibility is a big step forward in
appreciating the importance of "Generous Acceptance" [Robustness
Principle] and ease of use. In other words, even though purity
prevails in ST, pragmatism has its place. The "native.if" would be
that built-in for ST.
I like #4 the best, but it's the riskiest (biggest leap) since it
would open the door to user extensibility. Is there any value in user
extensibility, or it just a Pandora's Box? I think it's a logical
extension and may have hidden value (unforeseen advantages). As I
outlined in a previous post, providing full extensibility hooks is
sometimes essential for political/mental acceptance of "foreign"
technology, e.g., the NIH (Not Invented Here) Syndrome. As long as
"necessity is the mother of invention", extensibility could lead to
some very innovative uses for ST. To fully embrace "Generous
Acceptance" [Robustness Principle], "native.*" and user extensibilty
seems the next logical step when adding "if.*" and "native.if" to ST.
-=-
So that's how I see the "ifnull", "if.*", "native.if", and "native.*"
conversation. It's been very thought-provoking. I feel some
resistance by the experts (and maybe rightly so), but at least the
options are under consideration.
I'm mostly interested in Ruby and am toying with taking Ter's Toy-ST
and converting that to Ruby. I've been wondering how to get ST on
Ruby for some time. I'm hoping Toy-ST is the path of least
resistance.
I think it's important to give a nod to pragmatism, even when ST's
core strength is purity. Perhaps it's even -more- important to nod to
pragmatism since ST has such strong purity genetics. I think
pragmatism has already gotten a boost in the discussion of
abbreviating "StringTemplate" to "Template" (not to mention "ST").
IMO, ST has the genetics to be the king of the hill in templating, and
Ter continues to improve on it with v4. The rub seems to be less
about genetics and power, than about packaging and ease of adoption.
I believe the biggest opportunity for ST to grow is to convert users
with greater ease of use, ease of adoption. I believe ST's purity is
a two-edged sword. Strict adherence to separation of concerns
(model/view) keeps the ST language pure and valuable, but can make ST
harder to adopt (and appear riskier to prospective users, tech leads,
managers). I believe a few nods toward pragmatism with ("if.*") and
user extensibility ("native.*") could alleviate some of those
concerns.
Could these changes lead to wider ST adoption? Possibly, but perhaps
that's just my wishful thinking. We all want ST to be successful.
The question is how, not just from a purity of language standpoint,
but also from an ease-of-use and safety of adoption standpoint. I
think "Generous Acceptability" [Robustness Principle] could lead the
way, and that's where I suggest extrapolating beyond the simple
"ifnull".
Cheers,
= Joe =
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://www.antlr.org/pipermail/stringtemplate-interest/attachments/20091019/8def1127/attachment.html
More information about the stringtemplate-interest
mailing list