質問

が"適切に"を実施し高次機能C.

僕はほんのような携帯性、文法の正確性やあり方にメリットおよび欠陥ます。

編集:その理由を知りたい作成方法の高次機能のことを書いたシステムに変換すPyObjectリスト(おかける場合はpythonスクリプト)のリストのC構造体を含むを同じデータが集いに依存します。hます。このような中、私計画している機能を繰り返して調べてをpythonicリストや通話機能の各項目のリストに結果をリストして戻ります。

なので基本的にはマイプラン:

typedef gpointer (converter_func_type)(PyObject *)

gpointer converter_function(PyObject *obj)
{
    // do som stuff and return a struct cast into a gpointer (which is a void *)
}

GList *pylist_to_clist(PyObject *obj, converter_func_type f)
{
   GList *some_glist;
   for each item in obj
   {
       some_glist = g_list_append(some_glist, f(item));
   }
   return some_glist;
}

void some_function_that_executes_a_python_script(void)
{
   PyObject *result = python stuff that returns a list;
   GList *clist = pylist_to_clist(result, converter_function);
}

やclearifyの質問:いったいどのようなことに、より安全で正しいC.よりお問い合わせくだけの高次機能スタイルもその延時ほど、よろしくお願い致しますなあ。

役に立ちましたか?

解決

プレーンなCでこれを行うにしている熱心なあなたがいる場合は、渡された関数にファンクタ(高階関数)の呼び出し元からコンテキスト・ポインタに渡すオプションを含めるように覚えておく必要があります。これは、することができますあなたは物事が簡単に十分に動作させることができることクロージャを十分にシミュレートします。何そのポインタが指して...よく、あなた次第ですが、それは数子のAPI(または、そのようなTclのC APIでのGLibの世界でvoid*またはgpointerとして、それのための多くの別名の1)でClientDataする必要があることます。

[EDIT]:使用するために/あなたの例を適応ます:

typedef gpointer (converter_func_type)(gpointer,PyObject *)

gpointer converter_function(gpointer context_ptr,PyObject *obj)
{
    int *number_of_calls_ptr = context_ptr;
    *number_of_calls_ptr++;
    // do som stuff and return a struct cast into a gpointer (which is a void *)
}

GList *pylist_to_clist(PyObject *obj, converter_func_type f, gpointer context_ptr)
{
   GList *some_glist;
   for each item in obj
   {
       some_glist = g_list_append(some_glist, f(context_ptr,item));
   }
   return some_glist;
}

void some_function_that_executes_a_python_script(void)
{
   int number_of_calls = 0;
   PyObject *result = python stuff that returns a list;
   GList *clist = pylist_to_clist(result, converter_function, &number_of_calls);
   // Now number_of_calls has how often converter_function was called...
}

これはそれを行う方法の簡単な例であるが、それはあなたの道を示す必要があります。

他のヒント

技術的には、高次の機能だけの機能または戻ります。いqsortは既に高ます。

まうような、ラムダ機能言語である高次機能が本当に役に立ちたいと考えていた方は少し硬いときに自然に現在の標準C.いでなされたものの翻訳であります。アップルのブロックの延長は最高。でのみ動作GCC(LLVMのCコンパイラ)も本当に便利です。と思うくする。こちらは数に関連するリソース:

Cで高階関数を実装すると大きな問題は、それはあなたが、彼らはへのアクセス権を持つローカル変数を含むデータ構造で拡張関数ポインタですクロージャを、必要な非自明な何かを行うことです。閉鎖全体の考え方は、ローカル変数をキャプチャし、関数ポインタと一緒にそれらを渡すことですので、それはコンパイラのサポートなしで行うことは困難です。変数がそれらを解放する際に把握するのは難しいそれを作る、その範囲の外に存在することができるため、さらにはコンパイラのサポートと、それは、ガベージコレクションなしで行うことは困難です。

ストレートCで、これは本当に唯一の痛みと(彼らは苦痛である理由の一部である)事のこのタイプのためのものではないの両方である関数ポインタ、を介して行われます。 (非アップルによるまたは閉鎖、)ブロックは、しかし、このために素晴らしいです。彼らは、GCC-4.xまたは何か、およびICCの何かにコンパイルし、関係なく、あなたが探しているものthatsの。残念ながら、私はオンライン何か良いチュートリアルを見つけるように見えることはできませんが、十分ではそれがこのようなものを作品と言ってます:

void iterate(char *str, int count, (^block)(str *)){
  for(int i = 0; i < count; i++){
    block(list[i]);
  }
}

main() {
  char str[20];
  iterate(str, 20, ^(char c){
    printf("%c ", c);
  });

  int accum = 0;
  iterate(someList, 20, ^(char c){
    accum += c;
    iterate(str, 20, ^(char c){
      printf("%c ", c);
    });
  });
}
明らかにこのコードは無意味ですが、それそれの間にスペースを含む文字列(文字列)の各文字を印刷し、その後、一緒にACCUMへのすべての文字を追加し、それがないたびに、それは文字のリストを出力します再びます。

希望、このことができます。ところで、ブロックは、Mac OS XのSnow LeopardのAPI-Sに非常に見える、と私は彼らが珍しいことを本当にじゃないので、今後のC ++ 0xの標準であると考えています。

は実際には、任意の興味深い高階関数アプリケーションはCで手動構造体関数の引数を定義し、充填のlaborous及びエラープローンルーチンを伴う閉鎖を必要とする。

この質問への答えです。どのようにCの関数を構成するために、ここにリダイレクトされます。

あなたは、リストデータ型を実装するためのデータ構造を作成することができます。 その構造は、関数ポインタを含めることができます。

#include<stdlib.h>
#include<malloc.h>

typedef (*fun)();

typedef struct funList { fun car; struct funList *cdr;} *funList;

const funList nil = NULL;

int null(funList fs){ return nil==fs; }

fun car(funList fs)
{
   if(!null(fs)) return fs->car; 
   else 
   {
     fprintf(stderr,"error:can't car(nil) line:%d\n",__LINE__);
     exit(1);
   }
}

funList cdr(funList ls)
{ if(!null(ls)) return ls->cdr; 
  else 
  {
    fprintf(stderr,"error:can't cdr(nil) line:%d\n",__LINE__);
    exit(1);
  }
}

funList cons(fun f, funList fs)
{  funList ls;

   ls=(funList) malloc(sizeof(struct funList));
   if(NULL==ls)
   {
     fprintf(stderr,"error:can't alloc mem for cons(...) line:%d\n",__LINE__);
     exit(1);
   }

   ls->car=f;
   ls->cdr=fs;

   return ls;
}

私たちは関数のリストを適用する機能カンプを書くことができます

type_2 comp(funList fs, type_1 x)
{  
   return (null(fs)) ? x : car(fs)(comp(cdr(fs),x)); 
}

それがどのように動作するかの例。

:我々は、与えられた引数xに適用される短所の短縮表記(F、短所(G、短所(H、NIL)))として(G hのF)を使用します
comp((f g h),x)

=

f(comp((g h),x))

=

f(g(comp((h),x)))

=

f(g(h(comp(nil,x))))

=

f(g(h(x)))
あなたはSMLやHaskellのような型付き言語で多型リストタイプを使用していた場合は、

COMPのタイプがある必要があります:

comp :: ([a -> a],a) -> a

そのコンテキストで、リスト内のすべてのメンバーは、同じ型を持っているので。 Cは、この意味では、より柔軟であり得ます。たぶん何かのように

typedef void (*fun)();

または

typedef (*fun)();

あなたはこれについてどのようなCのマニュアル発言が表示されるはずです。そして、必ずすべての連続関数は互換性のある型を持っているということ。

構成する機能は副作用も自由変数なしすなわち、純粋であるべきである。

とても難しいのでは直C.とでC++を参照 functorsチュートリアル または向上の bind機能 することがあります。最後に、 C++0xに追加しネイティブの支援のためのラムダ機能, かなケアですの撮影に閉鎖すべての変数おfuncionです。

あなたは高階関数を作成したい場合は、Cを使用していない、あなたの問題へのCのソリューションがあります。彼らは、エレガントではないかもしれない、あるいは、彼らはあなたが気付いていることをよりエレガントかもしれません。

[編集]私はこれを達成する唯一の方法は、スクリプト言語を使用することが示唆されました。他の人はそれに私を呼んでいます。だから、私はこれでその提案を交換しています:[/編集]

あなたは何を達成しようとしていますか?あなたが模倣閉鎖したい場合は、支持体には、それら(あなたが図書館を通じてルビー、LUAは、Javascriptなどに結び付けることができます)その言語を使用します。あなたがコールバックを使用したい場合は、関数ポインタはOKです。関数ポインタはC(ポインタと弱い型システム)の最も危険な領域を結合するので、注意してください。関数ポインタの宣言はどちらか、読んで楽しいではありません。

あなたは、彼らが持っているので、関数ポインタを使用して、いくつかのCライブラリを見つけます。あなたはライブラリを書いている場合は、多分あなたも、それらを使用する必要があります。あなたはちょうどあなたがおそらくC.あなたにlispのか方式やルビーにいる思考を考えたり...とCの方法を学びC.でそれを書き込もうとしていない、独自のコード内でそれらを使用している場合。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top