User:Enamex/DIP: Extension Interfaces

From D Wiki
Revision as of 15:30, 5 September 2015 by Enamex (talk | contribs)
Jump to: navigation, search
Title: DIP Template
DIP: xx
Version: 0.1
Status: Draft
Created: 2015-09-04
Last Modified: 2015-09-5
Author: Enamex(:real-name)
Links:

Abstract

The existing constraints system depends on manually-written 'tests' instead of compiler-assisted comparisons of signatures of the template with a prototype, for example (a la `sig` in ML).

A system is here proposed to allow the declaration of 'extension interfaces' or 'lazy interfaces' that are ad-hoc attachable to existing types (structs and classes) and thus usable as native parts of a type within the package that declares the extension interfaces.

Rationale

This would greatly increase the versatility of template constraints by allowing ad-hoc extension components (interfaces) to be declared for existing types.

With the availability of this feature, idiomatic design in D would naturally tend towards 'bundles' of functions and associated constants that are checked for by a template constraint to be available for the tested type, thus allowing constraints testing for compliance with with InputRange interface, for example, usable with third-party types that do not implement the interface, if an extension interface providing compliance with InputRange is provided for the type within the same package that the type is tested for InputRange in.

Description

Allow the declaration of extension interfaces that accept function prototypes (with optional default implementations) and associated constants (both `static immutable` and manifest constants allowed) and the implementation of such interfaces for a `struct` or `class` after its definition.

Extension interfaces defined under the user's most super package would be implementable for types provided in third-party packages/libraries. Types defined under the user's most super package would be able to implement extension interfaces provided in third-party package/libraries.

It is impossible for a package to implement a third-party extension interface for a third-party type.

In any sub-module of the most super package of a project, any local type or extension interface that has been coupled with a local or foreign extension interface or type would behave as if the type natively possesses all functions and associated constants defined in the implemented extension interfaces. All functions in the type-implemented extension interfaces would be callable through method syntax `object.method()` and visible throughout the package no matter where the implementation block lies (it must still be under the same most super package, however).

Usage

// module superb.a;
struct Tile {
    void scan() {}
}

// module superb.call.util;
import superb.a;

// anonymous extension interface, attached to struct superb.a.Tile
interface (Tile) {
    bool detectChell() { return true; }
}

// named extension interface 'prototype'; later implemented by types and tested against
interface () HydraulicMobileEnvironment : path.SomeOtherInterfaceInherited { 
    static immutable int startingHealth;
    bool smash_opposite_tiles() { return true; }
}

// module superb.core;
import superb.a: Tile;
import superb.call.util: HydraulicMobileEnvironment;

// implement extension interface 'HydraulicMobileEnvironment' for type Tile
interface (Tile) : HydraulicMobileEnvironment {
    // provided required implementation, uses default of 'smash_opposite_tiles'
    static immutable int startingHealth = 95;
}

// module superb.mainfunc;
import superb.a;
import superb.core;

void main() {
    Tile t;
    t.smash_opposite_tiles(); // works; 'superb.core.HydraulicMobileEnvironment' implementation for 'superb.a.Tile';
                              // error if 'superb.core.HydraulicMobileEnvironment' is not imported;
                              // You import the interface declaration,
                              // not the implementation (which is automatically available unless declared private)
    t.scan(); // native definition
    t.detectChell(); // function in anonymous extension interface; doesn't require importing anything for it
}

Recommendations

When writing a DIP, try not to express your opinion. DIPs should provide facts and be as objective as possible. Even when that's pretty hard, you can make the DIP look more objective by not using, for example, "I prefer XXX because YYY". If YYY is an objective advantage, write that in a more objective way, like "XXX can be a better option because YYY". Try to leave non-technical personal preferences aside; "XXX can be a better option because the syntax is nicer" is not good enough even when you don't say "I prefer".

Try not to include half-baked ideas. If you are not sure about something, leave it outside the DIP and write it on the NG announcement instead for further discussion. The idea can be added to the DIP in the future when it is in a better shape.

NG Announcement

When posting the DIP announcement to the NG, please copy the abstract, so people can easily know what is it about and follow the link if they are interested.


Copyright

This document has been placed in the Public Domain.