Chapter 10. Generic Programming

10.1 General

Generic programming enables algorithms and data types to operate upon values whose types are specified when the generic entity is used rather than when it is declared.

A single generic declaration therefore describes a family of related declarations.

Generic programming promotes type safety, code reuse, and compile-time verification without sacrificing performance.

Generic facilities are integrated throughout the Buoy language and are not limited to a particular category of declaration.


10.2 Generic Declarations

A declaration is generic when it introduces one or more type parameters.

Type parameters represent placeholder types whose concrete values are supplied or inferred when the declaration is used.

The language permits generic:

  • Functions
  • Subs
  • Classes
  • Structures
  • Interfaces
  • Delegates

Additional declaration kinds may support generic parameters where explicitly specified.


10.3 Type Parameters

Each type parameter introduces a symbolic name representing an unknown type.

Within the generic declaration, the type parameter may appear wherever a type specification is permitted.

Each distinct type parameter represents an independent type.

Type parameter names obey the normal rules governing identifier visibility and scope.


10.4 Constructed Types

A constructed declaration is produced by substituting concrete type arguments for every type parameter.

Each unique set of type arguments identifies a distinct specialization.

The compiler shall ensure that every substituted type satisfies the requirements imposed by the generic declaration.


10.5 Generic Functions and Subs

Generic routines behave exactly like ordinary routines except that one or more types remain unspecified until invocation.

Generic routines participate fully in overload resolution.

Type arguments may be supplied explicitly or inferred by the compiler.


10.6 Type Inference

Where sufficient information is available, the compiler shall infer generic type arguments automatically.

Type inference considers:

  • routine parameters
  • argument types
  • assignment context
  • expected result type
  • overload resolution

The inferred types shall produce the same semantics as if they had been written explicitly.

Failure to infer a unique type is a compile-time error.


10.7 Explicit Type Arguments

A programmer may explicitly specify generic type arguments.

Explicit type arguments override inference.

Every supplied type argument shall satisfy the requirements of the corresponding type parameter.


10.8 Generic Members

Members declared within a generic type may reference the enclosing type parameters.

A member may also declare additional generic parameters independent of those declared by the enclosing type.

The scopes of enclosing and local type parameters are distinct.


10.9 Nested Generic Declarations

A generic declaration may contain additional generic declarations.

Inner declarations may reference both their own type parameters and those declared by enclosing declarations, subject to the normal visibility rules.


10.10 Type Safety

Generic programming preserves the static type guarantees of the language.

Every specialization is type checked according to the same language rules as a non-generic declaration.

No operation permitted within a generic declaration may violate the type safety of a valid specialization.


10.11 Code Generation

The language specification defines only the observable behaviour of generic declarations.

A conforming implementation may generate specialized code, shared code, or any other equivalent representation provided the externally observable behaviour remains unchanged.


10.12 Summary

Generic programming allows algorithms and data structures to be expressed independently of the concrete types upon which they operate.

Generic declarations are fully integrated with the Buoy type system, overload resolution, and compile-time type inference.