3

次のように定義された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++ などの言語ではそのようなことは決して起こりません。

うまくいけば、これを行う方法があります。もしそうなら、私は興味があります。

注: これは私が使用するものではありません。好奇心から質問しました。

4

5 に答える 5

2

最近の関数型言語では、引数としてリストをとる関数のリストを作成できます。これは間違いなくあなたの問題を解決しますが、それはあなたの質問が暗示しているように見える静的に型付けされた実装ではないので、間違いなく不正行為でもあります。ただし、「手動」引数処理を使用する場合、Python、Ruby、Perlなどの動的言語が行うこととほぼ同じです...

とにかく、以下はHaskellにあります:それはn(最初の引数から)th関数に2番目の引数()のコピーのfsリストを提供し、結果を返します。もちろん、何らかの方法で関数のリストをまとめる必要がありますが、switchステートメントとは異なり、このリストはファーストクラスの引数として再利用できます。nx

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

もちろん、がn関数の数よりも大きい場合、または関数が指定されたリストを処理できない場合は、例外が発生します。また、Haskellのスタイルが貧弱であることに注意してください-主に、リストを悪用して(乱暴に)問題を解決する方法が原因です...

于 2013-02-20T22:05:21.047 に答える
0

いいえ、あなたは間違っています。最近のほとんどの言語は、名前で関数を呼び出してパラメーターを渡すことができる何らかの形式のReflectionをサポートしています。

于 2013-02-19T21:20:35.840 に答える
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);
于 2013-02-19T21:22:02.447 に答える
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
于 2013-02-20T10:53:26.290 に答える
0

オブジェクト指向言語では、関数オブジェクトとリフレクションを一緒に使用して、目的を正確に達成できます。可変数の引数の問題は、関数オブジェクトに適切な POJO (C スタックを思い出してください) を渡すことによって解決されます。

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()て出力を取得します。
新しいファンクターを追加するときは、構成ファイル内のファンクターのリストを変更するだけです。

于 2013-02-20T11:06:07.247 に答える