在没有if-else / switch-case语句的情况下控制程序流程

时间:2013-02-19 21:17:56

标签: function programming-languages function-pointers program-flow

假设我有1000个函数定义如下

void func dummy1(int a);
void func dummy2(int a, int aa);
void func dummy3(int a, int aa, int aaa);
.
.
.
void func dummy1000(int a, int aa, int aaa, ...);

我想编写一个函数,它接受一个整数,n(n <1000)并调用第n个虚函数(如果是10,dummy10),只有n个参数(参数可以是任何整数,假设为0)需要。我知道这可以通过写一个包含1000个案例的switch case语句来实现。

在我看来,如果没有在运行时重新编译就无法实现这一点,因此像java,c,c ++这样的语言永远不会让这样的事情发生。

希望有一种方法可以做到这一点。如果是这样,我很好奇。

注意:这不是我将要使用的东西,我问的只是因为我的好奇心。

5 个答案:

答案 0 :(得分:2)

在现代函数式语言中,您可以创建一个以列表作为参数的函数列表。这可以说可以解决你的问题,但它也可以说是作弊,因为它不是你的问题似乎暗示的静态类型实现。但是,当使用“手动”参数处理时,它几乎就是Python,Ruby或Perl等动态语言...

无论如何,以下是在Haskell中:它为n函数(来自其第一个参数fs)提供了第二个参数n个副本的列表({{1} }),并返回结果。当然,您需要以某种方式将函数列表放在一起,但与switch语句不同,此列表将作为第一类参数重用。

x

当然,如果selectApplyFunction :: [ [Int] -> a ] -> Int -> Int -> a selectApplyFunction fs x n = (fs !! (n-1)) (replicate n x) dummy1 [a] = 5 * a dummy2 [a, b] = (a + 3) * b dummy3 [a, b, c] = (a*b*c) / (a*b + b*c + c*a) ... myFunctionList = [ dummy1, dummy2, dummy3, ... ] -- (myfunction n) provides n copies of the number 42 to the n'th function myFunction = selectApplyFunction myFunctionList 42 -- call the 666'th function with 666 copies of 42 result = myFunction 666 大于函数数,或者函数无法处理列表,则会出现异常。请注意,它是糟糕的Haskell风格 - 主要是因为它滥用列表的方式(滥用)解决你的问题......

答案 1 :(得分:0)

不,你不对。大多数现代语言支持某种形式的反射,它允许您通过名称调用函数并将params传递给它。

答案 2 :(得分:0)

您可以在大多数现代语言中创建函数数组。 在伪代码中,

var dummy = new Array();
dummy[1] = function(int a);
dummy[2] = function(int a, int aa);
...

var result = dummy[whateveryoucall](1,2,3,...,whateveryoucall);

答案 3 :(得分:0)

在函数式语言中你可以这样做,在强类型语言中,比如Haskell,函数必须具有相同的类型,但是:

funs = [reverse, tail, init]   -- 3 functions of type [a]->[a]

run fn arg = (funs !! fn) $ args  -- applies function at index fn to args

答案 4 :(得分:0)

在面向对象语言中,您可以同时使用function objects和反射来实现您想要的效果。通过将适当的POJO(调用C stucts)传递给函数对象来解决可变参数数量的问题。

interface Functor<A,B> {
    public B compute(A input);
}

class SumInput {
    private int x, y;
    // getters and setters
}

class Sum implements Functor<SumInput, Integer> {

    @Override
    public Integer compute(SumInput input) {
       return input.getX() + input.getY();
    }

}

现在想象一下,你有很多这些“仿函数”。您将它们收集在一个配置文件中(可能是一个XML文件,其中包含有关每个仿函数的元数据,使用方案,说明等...)并将列表返回给用户。
用户选择其中一个。通过使用反射,您可以看到所需的输入和预期输出。用户填写输入,并使用反射实例化仿函数类(newInstance()),调用compute()函数并获取输出。
添加新仿函数时,只需更改配置文件中的仿函数列表即可。