User:Enamex/DIP: User Defined Active Patterns

From D Wiki
Jump to: navigation, search
Title: DIP Template
DIP: xx
Version: 0.1
Status: Draft
Created: 2015-09-04
Last Modified: 2015-09-10
Author: Enamex(:real-name)
Links:

Abstract

(quick jot down; not final abstract); Proposal to add a match keyword and an auto opMatch(string pattern: "myPattern")(typeof(this) matobj) class/struct method and free function that takes as the only argument the object being de-structured and returns a Tuple containing the patterns assignable hooks. The compiler then rewrites invocations to the specific active pattern function into a series of declarations of the variables in user code inited with the returned parts of the chosen opMatch.

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

void main() {
    Option!int x = ???;
    #match(x) {
        Some(v): { writeln(v); }
        default: {}
    }
}

struct Option(T) {
    struct Some {
        T value_;
    }
    
    struct None {}

    enum Tag { Some, None }
    Tag Tag_;

    union UD {
        Some Some_;
        None None_;
    }
    UD ud;
    
    Tuple!(bool, Some*) opMatch(string op: "Some") {
        if( Tag_ == Tag.mixin(op) ) {
             return std.typecons.tuple(true, &ud.mixin(op~"_").value_);
        }
        else return std.typecons.tuple(false, null);
    }

    Tuple!(bool, None*) opMatch(string op: "None") {
        if( Tag_ == Tag.mixin(op) ) {
             return std.typecons.tuple(true, &ud.mixin(op~"_")));
        }
        else return std.typecons.tuple(false, null);
    }
}

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.