Skip to main content
added 2 characters in body
Source Link
janos
  • 112.8k
  • 15
  • 154
  • 396

Yes, the repetition is not great. But I think the bigger problem is that fun, hun, gun all need intimate knowledge of the predicate, how to respond when predicate X is true. Even worse, they need to know the relationships between the predicates (if pred1 is true, no need to call the others).

How about building a map of predicates to list of functions:

typedef std::list<void(*)(int)> lt_fun;
typedef std::map<bool(*)(int), lt_fun> mt_pred_fun;

void fun(mt_pred_fun functions, int x) {
    for (mt_pred_fun::iterator it = functions.begin(); it != functions.end(); ++it) {
        if (it->first(x)) {
            lt_fun fx = it->second;
            for (lt_fun::iterator it = fx.begin(); it != fx.end(); ++it) {
                (*it)(x);
            }
            return;
        }
    }
}

int main() {
    mt_pred_fun functions;

    functions[pred1] = lt_fun();
    functions[pred1].push_back(fun1);
    functions[pred1].push_back(fun2);
    functions[pred1].push_back(fun3);

    functions[pred2] = lt_fun();
    functions[pred2].push_back(fun2);
    functions[pred2].push_back(fun3);

    functions[pred3] = lt_fun();
    functions[pred3].push_back(fun3);

    std::cout << 60 << std::endl;
    fun(functions, 60);
    std::cout << 45 << std::endl;
    fun(functions, 45);
    std::cout << 65 << std::endl;
    fun(functions, 65);
}

Granted, there is still the duplication of adding the same functions to the lists of multiple predicates. But at least now they are all defined in one place, and fun doesn't need to know anything about the predicates, or the order in which to evaluate them, andor which functions to run.

Yes, the repetition is not great. But I think the bigger problem is that fun, hun, gun all need intimate knowledge of the predicate, how to respond when predicate X is true. Even worse, they need to know the relationships between the predicates (if pred1 is true, no need to call the others).

How about building a map of predicates to list of functions:

typedef std::list<void(*)(int)> lt_fun;
typedef std::map<bool(*)(int), lt_fun> mt_pred_fun;

void fun(mt_pred_fun functions, int x) {
    for (mt_pred_fun::iterator it = functions.begin(); it != functions.end(); ++it) {
        if (it->first(x)) {
            lt_fun fx = it->second;
            for (lt_fun::iterator it = fx.begin(); it != fx.end(); ++it) {
                (*it)(x);
            }
            return;
        }
    }
}

int main() {
    mt_pred_fun functions;

    functions[pred1] = lt_fun();
    functions[pred1].push_back(fun1);
    functions[pred1].push_back(fun2);
    functions[pred1].push_back(fun3);

    functions[pred2] = lt_fun();
    functions[pred2].push_back(fun2);
    functions[pred2].push_back(fun3);

    functions[pred3] = lt_fun();
    functions[pred3].push_back(fun3);

    std::cout << 60 << std::endl;
    fun(functions, 60);
    std::cout << 45 << std::endl;
    fun(functions, 45);
    std::cout << 65 << std::endl;
    fun(functions, 65);
}

Granted, there is still the duplication of adding the same functions to the lists of multiple predicates. But at least now they are all defined in one place, and fun doesn't need to know anything about the predicates, the order in which to evaluate them, and which functions to run.

Yes, the repetition is not great. But I think the bigger problem is that fun, hun, gun all need intimate knowledge of the predicate, how to respond when predicate X is true. Even worse, they need to know the relationships between the predicates (if pred1 is true, no need to call the others).

How about building a map of predicates to list of functions:

typedef std::list<void(*)(int)> lt_fun;
typedef std::map<bool(*)(int), lt_fun> mt_pred_fun;

void fun(mt_pred_fun functions, int x) {
    for (mt_pred_fun::iterator it = functions.begin(); it != functions.end(); ++it) {
        if (it->first(x)) {
            lt_fun fx = it->second;
            for (lt_fun::iterator it = fx.begin(); it != fx.end(); ++it) {
                (*it)(x);
            }
            return;
        }
    }
}

int main() {
    mt_pred_fun functions;

    functions[pred1] = lt_fun();
    functions[pred1].push_back(fun1);
    functions[pred1].push_back(fun2);
    functions[pred1].push_back(fun3);

    functions[pred2] = lt_fun();
    functions[pred2].push_back(fun2);
    functions[pred2].push_back(fun3);

    functions[pred3] = lt_fun();
    functions[pred3].push_back(fun3);

    std::cout << 60 << std::endl;
    fun(functions, 60);
    std::cout << 45 << std::endl;
    fun(functions, 45);
    std::cout << 65 << std::endl;
    fun(functions, 65);
}

Granted, there is still the duplication of adding the same functions to the lists of multiple predicates. But at least now they are all defined in one place, and fun doesn't need to know anything about the predicates, or the order in which to evaluate them, or which functions to run.

Source Link
janos
  • 112.8k
  • 15
  • 154
  • 396

Yes, the repetition is not great. But I think the bigger problem is that fun, hun, gun all need intimate knowledge of the predicate, how to respond when predicate X is true. Even worse, they need to know the relationships between the predicates (if pred1 is true, no need to call the others).

How about building a map of predicates to list of functions:

typedef std::list<void(*)(int)> lt_fun;
typedef std::map<bool(*)(int), lt_fun> mt_pred_fun;

void fun(mt_pred_fun functions, int x) {
    for (mt_pred_fun::iterator it = functions.begin(); it != functions.end(); ++it) {
        if (it->first(x)) {
            lt_fun fx = it->second;
            for (lt_fun::iterator it = fx.begin(); it != fx.end(); ++it) {
                (*it)(x);
            }
            return;
        }
    }
}

int main() {
    mt_pred_fun functions;

    functions[pred1] = lt_fun();
    functions[pred1].push_back(fun1);
    functions[pred1].push_back(fun2);
    functions[pred1].push_back(fun3);

    functions[pred2] = lt_fun();
    functions[pred2].push_back(fun2);
    functions[pred2].push_back(fun3);

    functions[pred3] = lt_fun();
    functions[pred3].push_back(fun3);

    std::cout << 60 << std::endl;
    fun(functions, 60);
    std::cout << 45 << std::endl;
    fun(functions, 45);
    std::cout << 65 << std::endl;
    fun(functions, 65);
}

Granted, there is still the duplication of adding the same functions to the lists of multiple predicates. But at least now they are all defined in one place, and fun doesn't need to know anything about the predicates, the order in which to evaluate them, and which functions to run.