Overloading and genericity
Updated: 2024-02-22
Created: 2022-02-22
References:
- Overloading and genericity: one leads to another.
- Both means more flexible code, especially for libraries.
- Both can be static or dynamic.
- Types and procedures implement algebras, overloading and
genericity allow implementing something like "categories".
- Terminology: procedure declaration, definition, call.
- Procedure declaration: interface name,
signature
,
parameters
.
- Procedure definition: implementation
name,
signature
,
parameters
, body
.
- Procedure call: invocation
name,
signature
,
arguments
.
- const k: int = 3; var i: int = 9;
- The
type
of k is int
its value is 3.
- The
type
of i
is reference
, its value is "some reference"
that denotes 3, int is the constraint on the
type of values "some reference" can denote.
- Type constraints can be applied to all sorts of values, not
just references, but there can be also non-type constraints,
for example value constraints (for example ranges, or
even single values, some of which may be semantically
irrelevant).
- Overloading is a property of procedure interface names: one
procedure interface name has multiple signatures, each
signature leads to a different definition.
- One type of difference: in the types or type constraints of
parameters. Usually for types implementing similar underlying
algebras (within the same "category").
- Another type of difference: in the values or value
constraints of parameters. Usually for implementing different
algorithms of the same function.
- Overload resolutions is done by matching the call signature
to the definition signature. Usually called
"dispatching".
- Static when signatures are matched at compile time, dynamic
when signatures are matched at run time (in case of type
constraint that's often called "dynamic typing" but that's
incorrect).
- Over a single distinguished argument of the signature, over
multiple (all) arguments.
- variable.procedure(arg1,arg2) is just equivalent to
procedure(variable,arg1,arg2) so in many languages
dynamic dispatching is possible only on the first argument,
which is distinguished with the variable. syntax
before the procedure name.
- Actually varT1.field1 and varT2.field1 are
also implicit
getter
or setter
calls, that is
overloaded field1 with signatures:
- field1(varT1: T1)
- field1(varT2: T2)
- field1(varT1: ref T1,rvalue: T1)
- field1(varT2: ref T2,rvalue: T2)
- Genericity is a property of any stretch of code:
a stretch of code is generic over the intersection of the
signatures of all procedure calls in that code stretch.
- Most often the stretch of code is the implementation of a
procedure, in which case that procedure definition can be
called "generic" if the signature of the definition is
equally generic.
- That applies whether the genericity is static (e.g.
templates) or dynamic (virtual and
equivalent).
- That applies whether the procedures are implicit in
getters/setters, are
methods
, or
friends
.
- The purpose of overloading is genericity, the main purpose
of genericity is defining procedures that implement functions
for all types belonging to the same category.
- Another function of genericity is to defining procedures
that implement function for different subsets of values in the
same algebra.
- Genericity mainly applies to libraries as
most programs are not generic, or their genericity is
much narrower than the of the libraries they use.
- One important aspect of this narrowness is that in many
cases what is dynamic genericity in a library become static
genericity in a program, as some types and value are known
statically in calls. Sometimes explicit instantiation
of still-generic procedures is useful for optimization.
- Indeed one difference between library and program is that
programs are far more specialized than libraries in both type
and value genericity, because they have
closed
rather than open
type sets.