These are two or more features in languages which arguably overlap enough that having both/all are of questionable value or design.
- Associative arrays and objects in dynamic languages
- Arrays and tables
- Arrays and Lists
- Object methods and (pure) functions (possibly multiple dispatch)
- SQL's HAVING and WHERE clause.
- templates and macros
- operator overloading and traditional functions
- HigherOrderFunction and OOP
- Tables and WHERE clause filtering, potentially (TableQuantityVersusAppSize)
- EssExpressions and everything ;-)
- (more to come...)
- Associative arrays and objects in dynamic languages
- The two concepts are so similar in dynamic languages that one might as well build/meld one with the other.
- Arrays and tables
- later dialects of ExBase added arrays, but I felt they were not really needed because tables were easy enough to create and use. (Some dialects later added temporary and self-deleting tables to help with clean-up.)
- SQL's HAVING clause.
- It's kind of a duplicate of the concept of WHERE. In TopsQueryLanguage, one would simply use the "filter" operation to get such just as they would for the equivalent of WHERE.
- The "having" clause is used as a filter after the "grouping" has been done. I use this "select invoice,count(*) as cnt from invoice group by invoice having cnt>1" to verify that I don't have any duplicate records and it will show me which ones are. The "where" in this case would filter the rows before they were aggregated rather than after. Two kinds of filters for different purposes. Definitely not the same or "duplicate".
- In SQL strictly speaking, you are correct. But SQL is designed poorly in my opinion, resulting in a "need" to have very similar constructs.
- Object methods and (pure) functions (possibly multiple dispatch)
- Having object methods effectively means single dispatch on a selected argument. This could be done as syntactic sugar of a general dispatch. But having both notations coexist like in C++ causes unnecessary complexity.
- Except, which of these is clearer? nroot(3, 9) or 3.nroot(9) or 9.nroot(3)? How about these: out.print("hello") or print(out, "hello")? But if you choose the first one, wouldn't it be better to have an implicit version with just print("hello") implying out? What if it's hard to decide which parameter is the object (eg. /foo/.accept?("bar") vs "bar".matchTo(/foo/))? What if you can't mixin or augment classes?
- KeywordParameterPassing can help out syntax-wise. For example, print("hello", device=foo) allows us to optionally select the non-default console device.
- templates and macros
- For added complexity in C++ both are supported but in a way none can be left out. Great!
- Yes, but think how hard it is implementing one in terms of the other...
- operator overloading and traditional functions with parameters
- if operator overloading is possible then function calls should be a special case notation of this.
- Don't you mean the other way around?
I suppose this should be held distinct from the fact that orthogonal language features tend to involve CrossCuttingConcerns and utterly non-orthogonal language design and language implementation requirements (due to FeatureInteraction... which is EssentialComplexity since half the purpose of using a language with two features instead of two languages each with one feature is to have the language implementation efficiently handle FeatureInteraction).
It might also be kept distinct from SyntacticSugar, in which a syntactic shorthand is provided to convenience the authors. For example, the ability to write "Hello, World!" instead of ['H', 'e', 'l', 'l', 'o', ',', ' ', 'W', 'o', 'r', 'l', 'd', '!']. SyntacticSugar is, perhaps, a syntactic language feature... but not a semantic one. It doesn't imply the same costs on the compiler (or interpreter) as do semantic language features. OTOH, SyntacticSugar does have a cost on the parser and on the user who is learning the language or maintaining programs written in it by others.
Re: ability to write "Hello, World!" instead of ['H', 'e', 'l', 'l', 'o', ',', ' ', 'W', 'o', 'r', 'l', 'd', '!']
Ah, similar to early ForTran. Good times!
Non-IT Examples
The Model-T engine had a brilliant form of conceptual reuse. The earliest Model-T's had water-pumps to circulate water to cool the engine. But it was eventually realized that with a slight redesign, the engine's own heat could power water circulation. Thus, the water-pump was soon dropped, reducing cost and reducing the number of parts that could break. Heat is energy (at least when next to non-heat), thus it might as well be put to use when it can. This kind of thinking is one reason why the Model-T was so successful for its time. (Unfortunately, this technique is not consistent enough for modern or larger engines.)
See also: ParadigmPotpourriMeansDiminishingReturns, LanguageIdiomClutter, AbstractionsTooNear, GreatLispWar
CategoryProgrammingLanguage, CategoryLanguageDesign CategoryMultiparadigm