Generic programming: Difference between revisions

Content deleted Content added
m unpiped links using script
Line 13:
| pages=9–10}}</ref><ref>{{cite conference |last1=Milner |first1=R. |last2=Morris |first2=L. |last3=Newey |first3=M. |year=1975 |title=A Logic for Computable Functions with Reflexive and Polymorphic Types |book-title=Proceedings of the Conference on Proving and Improving Programs}}</ref> permits writing common [[function (computer science)|functions]] or [[type (computer science)|type]]s that differ only in the set of types on which they operate when used, thus reducing [[duplicate code]].
 
Generic programming was introduced to the mainstream with [[Ada (programming language)|Ada]] in 1977. With [[Template (C++)|templates]] in [[C++]], generic programming became part of the repertoire of professional library design. The techniques were further improved and ''parameterized types'' were introduced in the influential 1994 book ''[[Design Patterns (book)|Design Patterns]]''.<ref name="GoF">
{{cite book |last1=Gamma
|first1=Erich
Line 69:
 
==Programming language support for genericity==
Genericity facilities have existed in high-level languages since at least the 1970s in languages such as [[ML (programming language)|ML]], [[CLU (programming language)|CLU]] and [[Ada (programming language)|Ada]], and were subsequently adopted by many [[Object-based language|object-based]] and [[Object-oriented programming|object-oriented]] languages, including [[BETA (programming language)|BETA]], [[C++]], [[D (programming language)|D]], [[Eiffel (programming language)|Eiffel]], [[Java (programming language)|Java]], and [[Digital Equipment Corporation|DEC]]'s now defunct [[Trellis-Owl]].
 
Genericity is implemented and supported differently in various programming languages; the term "generic" has also been used differently in various programming contexts. For example, in [[Forth (programming language)|Forth]] the [[compiler]] can execute code while compiling and one can create new ''compiler keywords'' and new implementations for those words on the fly. It has few ''words'' that expose the compiler behaviour and therefore naturally offers ''genericity'' capacities that, however, are not referred to as such in most Forth texts. Similarly, dynamically typed languages, especially interpreted ones, usually offer ''genericity'' by default as both passing values to functions and value assignment are type-indifferent and such behavior is often used for abstraction or code terseness, however this is not typically labeled ''genericity'' as it's a direct consequence of the dynamic typing system employed by the language.{{citation needed|date=August 2015}} The term has been used in [[functional programming]], specifically in [[Haskell]]-like languages, which use a [[structural type system]] where types are always parametric and the actual code on those types is generic. These uses still serve a similar purpose of code-saving and rendering an abstraction.
Line 227:
This works whether the arguments <code>x</code> and <code>y</code> are integers, strings, or any other type for which the expression <code>x &lt; y</code> is sensible, or more specifically, for any type for which <code>operator&lt;</code> is defined. Common inheritance is not needed for the set of types that can be used, and so it is very similar to [[Duck typing#Templates or generic types|duck typing]]. A program defining a custom data type can use [[operator overloading]] to define the meaning of <code>&lt;</code> for that type, thus allowing its use with the <code>max()</code> function template. While this may seem a minor benefit in this isolated example, in the context of a comprehensive library like the STL it allows the programmer to get extensive functionality for a new data type, just by defining a few operators for it. Merely defining <code>&lt;</code> allows a type to be used with the standard <code>sort()</code>, <code>stable_sort()</code>, and <code>binary_search()</code> algorithms or to be put inside data structures such as <code>set</code>s, [[heap (programming)|heap]]s, and [[associative array]]s.
 
C++ templates are completely [[type safety|type safe]] at compile time. As a demonstration, the standard type <code>complex</code> does not define the <code>&lt;</code> operator, because there is no strict order on [[complex number]]s. Therefore, <code>max(x, y)</code> will fail with a compile error, if ''x'' and ''y'' are <code>complex</code> values. Likewise, other templates that rely on <code>&lt;</code> cannot be applied to <code>complex</code> data unless a comparison (in the form of a functor or function) is provided. E.g.: A <code>complex</code> cannot be used as key for a <code>map</code> unless a comparison is provided. Unfortunately, compilers historically generate somewhat esoteric, long, and unhelpful error messages for this sort of error. Ensuring that a certain object adheres to a [[protocol (computer science)|method protocol]] can alleviate this issue. Languages which use <code>compare</code> instead of <code>&lt;</code> can also use <code>complex</code> values as keys.
 
Another kind of template, a ''class template,'' extends the same concept to classes. A class template specialization is a class. Class templates are often used to make generic containers. For example, the STL has a [[linked list]] container. To make a linked list of integers, one writes <code>list&lt;int&gt;</code>. A list of strings is denoted <code>list&lt;string&gt;</code>. A <code>list</code> has a set of standard functions associated with it, that work for any compatible parameterizing types.
Line 249:
However, templates are generally considered an improvement over macros for these purposes. Templates are type-safe. Templates avoid some of the common errors found in code that makes heavy use of function-like macros, such as evaluating parameters with side effects twice. Perhaps most importantly, templates were designed to be applicable to much larger problems than macros.
 
There are four primary drawbacks to the use of templates: supported features, compiler support, poor error messages (usually with pre C++20 [[Substitution failure is not an error|SFINAE]]), and [[code bloat]]:
# Templates in C++ lack many features, which makes implementing them and using them in a straightforward way often impossible. Instead programmers have to rely on complicated tricks which leads to bloated, hard to understand and hard to maintain code. Current developments in the C++ standards exacerbate this problem by making heavy use of these tricks and building a lot of new features for templates on them or with them in mind.
# Many compilers historically had poor support for templates, thus the use of templates could have made code somewhat less portable. Support may also be poor when a C++ compiler is being used with a [[Linker (computing)|linker]] that is not C++-aware, or when attempting to use templates across [[Library (computer science)#Shared libraries|shared library]] boundaries.
Line 262:
The [[D (programming language)|D]] language supports templates based in design on C++. Most C++ template idioms work in D without alteration, but D adds some functionality:
* Template parameters in D are not restricted to just types and primitive values (as it was in C++ before C++20), but also allow arbitrary compile-time values (such as strings and struct literals), and aliases to arbitrary identifiers, including other templates or template instantiations.
* Template constraints and the <code>static if</code> statement provide an alternative to respectively C++'s [[Concepts (C++)|C++ concepts]] and <code>if constexpr</code>.
* The <code>is(...)</code> expression allows speculative instantiation to verify an object's traits at compile time.
* The <code>auto</code> keyword and the <code>[[typeof]]</code> expression allow [[type inference]] for variable declarations and function return values, which in turn allows "Voldemort types" (types that do not have a global name).<ref>{{cite web |last=Bright |first=Walter |title=Voldemort Types in D |url =https://www.drdobbs.com/cpp/voldemort-types-in-d/232901591 |website=Dr. Dobbs |access-date=3 June 2015}}</ref>
Line 369:
{{Main|Generics in Java}}
 
Support for the ''generics'', or "containers-of-type-T" was added to the [[Java (programming language)|Java programming language]] in 2004 as part of J2SE 5.0. In Java, generics are only checked at compile time for type correctness. The generic type information is then removed via a process called [[type erasure]], to maintain compatibility with old [[Java virtual machine|JVM]] implementations, making it unavailable at runtime.{{sfn|Bloch|2018|loc=§Item 28: Prefer lists to arrays|p=126}} For example, a <code>List&lt;String&gt;</code> is converted to the raw type <code>List</code>. The compiler inserts [[Type conversion|type casts]] to convert the elements to the <code>String</code> type when they are retrieved from the list, reducing performance compared to other implementations such as C++ templates.
 
====Genericity in .NET [C#, VB.NET]====