Adding info to manual (#22252)

* Adjustments

* Moving example

* typo

* adding code example back and fix terms

* Condensing
This commit is contained in:
Ryan McConnell
2023-07-19 09:04:14 -04:00
committed by GitHub
parent 7d9fe106ec
commit 0d3bde95f5

View File

@@ -2642,9 +2642,15 @@ of the argument.
6. Conversion match: `a` is convertible to `f`, possibly via a user
defined `converter`.
These matching categories have a priority: An exact match is better than a
literal match and that is better than a generic match etc. In the following,
`count(p, m)` counts the number of matches of the matching category `m`
There are two major methods of selecting the best matching candidate, namely
counting and disambiguation. Counting takes precedence to disambiguation. In counting,
each parameter is given a category and the number of parameters in each category is counted.
The categories are listed above and are in order of precedence. For example, if
a candidate with one exact match is compared to a candidate with multiple generic matches
and zero exact matches, the candidate with an exact match will win.
In the following, `count(p, m)` counts the number of matches of the matching category `m`
for the routine `p`.
A routine `p` matches better than a routine `q` if the following
@@ -2662,6 +2668,11 @@ algorithm returns true:
return "ambiguous"
```
When counting is ambiguous, disambiguation begins. Parameters are iterated
by position and these parameter pairs are compared for their type relation. The general goal
of this comparison is to determine which parameter is more specific. The types considered are
not of the inputs from the callsite, but of the competing candidates' parameters.
Some examples:
@@ -5470,6 +5481,49 @@ The following example shows how a generic binary tree can be modeled:
The `T` is called a `generic type parameter`:idx: or
a `type variable`:idx:.
Generic Procs
---------------
Let's consider the anatomy of a generic `proc` to agree on defined terminology.
```nim
p[T: t](arg1: f): y
```
- `p`: Callee symbol
- `[...]`: Generic parameters
- `T: t`: Generic constraint
- `T`: Type variable
- `[T: t](arg1: f): y`: Formal signature
- `arg1: f`: Formal parameter
- `f`: Formal parameter type
- `y`: Formal return type
The use of the word "formal" here is to denote the symbols as they are defined by the programmer,
not as they may be at compile time contextually. Since generics may be instantiated and
types bound, we have more than one entity to think about when generics are involved.
The usage of a generic will resolve the formally defined expression into an instance of that
expression bound to only concrete types. This process is called "instantiation".
Brackets at the site of a generic's formal definition specify the "constraints" as in:
```nim
type Foo[T] = object
proc p[H;T: Foo[H]](param: T): H
```
A constraint definition may have more than one symbol defined by seperating each definition by
a `;`. Notice how `T` is composed of `H` and the return type of `p` is defined as `H`. When this
generic proc is instantiated `H` will be bound to a concrete type, thus making `T` concrete and
the return type of `p` will be bound to the same concrete type used to define `H`.
Brackets at the site of usage can be used to supply concrete types to instantiate the generic in the same
order that the symbols are defined in the constraint. Alternatively, type bindings may be inferred by the compiler
in some situations, allowing for cleaner code.
Is operator
-----------