看板 C_and_CPP 關於我們 聯絡資訊
最近看了 sicp 5.2 的 recusive + callback 的 scheme 寫法, 弄懂之後寫了個 c++ 的版本。 有興趣的朋友參考看看。 想順便問問看, std::function 可以省下來嗎? 我直接傳遞 std::function 那個 lambda function, compile 不會過。 t.cpp 1 // ref:http://goo.gl/k5MgDG ( http://kheresy.wordpress.com/2010/05/27/c0x%a1Glambda-expression/ ) 2 #include <vector> 3 #include <algorithm> 4 #include <iostream> 5 #include <string> 6 #include <typeinfo> 7 #include<functional> 8 9 using namespace std; 10 84 template<typename Func> 85 void extract(const string &str, Func receive) 86 { 87 if (str.length() == 0) 88 { 89 string e1, e2; 90 receive(e1, e2); 91 } 92 else 93 { 94 // ref:http://goo.gl/hgh1EI ( http://www.cnblogs.com/ttss/p/4100917.html ) 95 // std::function<int(int ,int)>func=add; 96 // <int(int,int)>是例化模板,表示返回值int,函2,(int,int), 97 // 即int(*pfunc)(int ,int )型的函 98 std::function<void(const string&, const string&)> f1 = [&](const string &n, const string &s) 99 { 100 char next_ch = str[0]; 101 string tmp_str; 102 103 tmp_str.push_back(next_ch); 104 105 #ifdef MORE_INFO 106 cout << "n: " << n << endl; 107 cout << "s: " << s << endl; 108 cout << "next_ch: " << next_ch << endl; 109 #endif 110 111 if ('0' <= next_ch && next_ch <= '9') 112 { 113 string new_str = n + tmp_str; 114 #ifdef MORE_INFO 115 cout << "new_str: " << new_str << endl; 116 cout << "===========" << endl; 117 #endif 118 receive(new_str, s); 119 } 120 else 121 { 122 string new_str = s + tmp_str; 123 #ifdef MORE_INFO 124 cout << "new_str: " << new_str << endl; 125 cout << "===========" << endl; 126 #endif 127 receive(n, new_str); 128 } 129 }; 130 131 extract(str.substr(1), f1); 132 } 133 } 134 135 void assemble(string &str) 136 { 137 extract(str, 138 [] (const string &n, const string &s) 139 { 140 cout << n << endl; 141 cout << s << endl; 142 } 143 ); 144 } 145 146 int main(int argc, char *argv[]) 147 { 154 string str="x51ca2yz"; 155 cout << str << endl; 157 assemble(str); 158 return 0; 159 } 一個 lambda function 的 type 應該怎麼描述? 為什麼需要把 type 寫出來, c++ 可不 是 scheme , 都不用宣告的, 所以不知道怎麼寫 lambda function 的type, 要怎麼傳 lambda function 給 function 當參數呢? 我想到邪惡萬用的 auto。 31 auto func = [] () { cout << "Hello world" << endl; } 可以, 不過帶有 capture-list 就不行了。 81 auto func = [&] () { cout << "Hello world" << endl; } 而且, 在 function 的 prototype 也不能寫 auto 來傳入 lambda function。 void f1(auto F); fa(func); 這樣是不行的。 所以我想到是不是可以用 function pointer 的方式傳進去, L31 的那種型式可以, ex: void f1(void (*F)()); fa(func); 這樣就可以了, 但我想傳入 L81 那種型式的 lambda function 該怎麼辦呢? 為什麼有 capture-list 不能以 function pointer 傳入呢? 因為他需要把外面那層的變數存起來 , 這不是 c++ function 應該有的樣子, 那 c++ 有什麼機制可以把東西存起來, 而且也 有像 funciton 的行為呢? 你一定馬上想到 function object, 這就是 recursive_call_back.cpp 為什麼要用上 function object 的原因。 有著 capture-list 的 lambda function 有個很酷的名稱 - lexical closure, 中國翻 譯成「閉包」, 台灣我不知道翻譯成什麼? 這東西感覺起來是不是和 function object 很像, lexical closure 搞不懂, 用 function object 來聯想也許就容易懂了。 但是我不想傳 function object, 那個我已經做過了, 那這個東西的 type 要怎麼寫呢? c++11 標準程式庫知道這很讓我們傷腦筋, 提供了 std::function 來完成這樣的事情。 所以我出動了 std::function 來將 BB 轉成 function object, 就可以當作 lambda function 的 type 來傳遞。 最後修改函式的宣告, 使用 template 來宣告一個 template function, 這樣就可以接受 std::function 轉過的 function。 不過這樣有什麼好處嗎? 辛苦理解了這些新東西, 但他們能帶來更好的效益嗎? 花時間學 習划算嗎? 看看 scheme 和 c++ 的版本, c++ 寫來辛苦不少。c++11 加入了不少東西, 還有 c++14, 這些都是負擔很大的學習, 我的建議是: 取你想用的來學習, 不必有想把 c++ 全摸透的想法, 對於 template 我就很頭疼, 幾乎看不懂比較複雜的 template 程式 碼, 我願意學習難度高的 c++ 是因為她的彈性和效率, 可不是拿來折磨自己用的, 一旦 沒有了效率優勢, 我可能得找候補人選。 對於 std::function 的行為, 我實在好奇, 這是怎麼完成的呢? c++ 越來越神奇了。 我雖然搞懂了, 但是要我以這種思維來寫程式, 呃 ... 我功力還不夠。自從學了 c++11 後, 連自己都看不懂自己在寫什麼了。 scheme 和 recursive_call_back.cpp 的版本可以參考: http://descent-incoming.blogspot.tw/2015/01/recursive-callback-function.html ( http://goo.gl/gClt7L ) // 本文使用 Blog2BBS 自動將Blog文章轉成縮址的BBS純文字 http://goo.gl/TZ4E17 // blog 版本, 呃 ... 這次沒有 blog 版本 XD -- ※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 36.236.197.237 ※ 文章網址: https://www.ptt.cc/bbs/C_and_CPP/M.1421666026.A.3EA.html ※ 編輯: descent (36.236.197.237), 01/19/2015 19:17:21
kwpn: 編譯過不了的問題,應該先簡化程式碼來查問題出在哪. 01/19 19:59
PkmX: 其實簡化來看這個extract就只是某種fold的變體... 01/20 00:14
PkmX: 要寫這麼functional的程式還是來寫歡樂的haskell吧XD" 01/20 00:18
PkmX: 直接轉換的版本:http://ideone.com/8sFb9M 01/20 00:18
PkmX: assemble'是用foldl' + lens的一行版 01/20 00:19
suhorng: (!) PkmX 出現了XD 01/20 01:33
suhorng: 普通 cont.-passing style 竟然有這種 lens 寫法XD 01/20 01:34
PkmX: 喔對沒錯這個是CPS 昨天一直突然想不起來這個叫啥XDrz... 01/20 16:01