various questions

bearophile bearophileHUGS at lycos.com
Wed Jul 28 17:18:05 PDT 2010


Jason Spencer:
> I had thought of the switch, and it would be too large.  Can you give me an idea of what
> the mixin solution would look like?  Suppose I have three strings, type, rows, and cols
> that get set at runtime, where type = ["int" | "float" | "short"], rows and cols =
> ["100" | "200" | "250"].  What I want is to take these 3 variables and come up with:
> foo!(int[100][100])(...)
> foo!(int[100][200])(...)
> ...
> foo!(short[250][250])(...)
> 
> for the right cases, without switching on type, rows, or cols.

The brutal way:


import std.stdio: writeln;

void foo(T, int N, int M)() {
    writeln(typeid(T), " ", N, " ", M);
}

enum Type { int_type, float_type, short_type }
enum Size { small = 100, medium = 200, large = 250 }


void main() {
    Type type = Type.int_type;
    Size n = Size.medium;
    Size m = Size.small;


    final switch (type) {
        case Type.int_type:
            final switch (n) {
                case Size.small:
                    final switch (m) {
                        case Size.small:  foo!(int, Size.small, Size.small)(); break;
                        case Size.medium: foo!(int, Size.small, Size.medium)(); break;
                        case Size.large:  foo!(int, Size.small, Size.large)(); break;
                    }
                    break;
                case Size.medium:
                    final switch (m) {
                        case Size.small:  foo!(int, Size.medium, Size.small)(); break;
                        case Size.medium: foo!(int, Size.medium, Size.medium)(); break;
                        case Size.large:  foo!(int, Size.medium, Size.large)(); break;
                    }
                    break;
                case Size.large:
                    final switch (m) {
                        case Size.small:  foo!(int, Size.large, Size.small)(); break;
                        case Size.medium: foo!(int, Size.large, Size.medium)(); break;
                        case Size.large:  foo!(int, Size.large, Size.large)(); break;
                    }
                    break;
            }
            break;

        case Type.float_type:
            final switch (n) {
                case Size.small:
                    final switch (m) {
                        case Size.small:  foo!(float, Size.small, Size.small)(); break;
                        case Size.medium: foo!(float, Size.small, Size.medium)(); break;
                        case Size.large:  foo!(float, Size.small, Size.large)(); break;
                    }
                    break;
                case Size.medium:
                    final switch (m) {
                        case Size.small:  foo!(float, Size.medium, Size.small)(); break;
                        case Size.medium: foo!(float, Size.medium, Size.medium)(); break;
                        case Size.large:  foo!(float, Size.medium, Size.large)(); break;
                    }
                    break;
                case Size.large:
                    final switch (m) {
                        case Size.small:  foo!(float, Size.large, Size.small)(); break;
                        case Size.medium: foo!(float, Size.large, Size.medium)(); break;
                        case Size.large:  foo!(float, Size.large, Size.large)(); break;
                    }
                    break;
            }
            break;

        case Type.short_type:
            final switch (n) {
                case Size.small:
                    final switch (m) {
                        case Size.small:  foo!(short, Size.small, Size.small)(); break;
                        case Size.medium: foo!(short, Size.small, Size.medium)(); break;
                        case Size.large:  foo!(short, Size.small, Size.large)(); break;
                    }
                    break;
                case Size.medium:
                    final switch (m) {
                        case Size.small:  foo!(short, Size.medium, Size.small)(); break;
                        case Size.medium: foo!(short, Size.medium, Size.medium)(); break;
                        case Size.large:  foo!(short, Size.medium, Size.large)(); break;
                    }
                    break;
                case Size.large:
                    final switch (m) {
                        case Size.small:  foo!(short, Size.large, Size.small)(); break;
                        case Size.medium: foo!(short, Size.large, Size.medium)(); break;
                        case Size.large:  foo!(short, Size.large, Size.large)(); break;
                    }
                    break;
            }
            break;
    }
}



A more compressed way:

import std.metastrings: Format;
import std.stdio: writeln;

void foo(T, int N, int M)() {
    writeln(typeid(T), " ", N, " ", M);
}

enum Type { int_type, float_type, short_type }
enum Size { small = 100, medium = 200, large = 250 }

void main() {
    Type type = Type.short_type;
    Size n = Size.medium;
    Size m = Size.small;

    enum string inner = "
                        case Size.small:  foo!(%s, Size.%s, Size.small)(); break;
                        case Size.medium: foo!(%s, Size.%s, Size.medium)(); break;
                        case Size.large:  foo!(%s, Size.%s, Size.large)(); break;
    ";


    enum string medial = "
                    final switch (m) {
                        mixin(Format!(inner, ty, si, ty, si, ty, si));
                    }
                    break;
    ";

    enum string outer = `
            final switch (n) {
                case Size.small:
                    enum string si = "small";
                    mixin(medial);
                case Size.medium:
                    enum string si = "medium";
                    mixin(medial);
                case Size.large:
                    enum string si = "large";
                    mixin(medial);
            }
            break;
    `;

    final switch (type) {
        case Type.int_type:
            enum string ty = "int";
            mixin(outer);

        case Type.float_type:
            enum string ty = "float";
            mixin(outer);

        case Type.short_type:
            enum string ty = "short";
            mixin(outer);
    }
}


It's a mess still :-)

Bye,
bearophile


More information about the Digitalmars-d-learn mailing list