On Wed, 2007-10-03 at 01:15 +0200, kirillkh wrote: > Hi, I cc'd answer to Felix mailing list, since the discussion is useful there. Nice to have interesting problems to solve!
> Sending in private, as this is complete off-topic. I was wondering, > whether you can translate my fold_file combinator into Felix without > sacrificing performance or style. Ok, this works with current svn version, the file is called lc.flx and line counts itself. /////////////////////////////////////////// fun fold_file[a,b] (read_func: 1->opt[a]) (elem_func: a->b->b) (seed: b) :b = { fun aux (prev_val:b) :b => match read_func () with | Some ?input => aux (elem_func input prev_val) | None => prev_val endmatch ; return aux seed; } include "std/textio"; open Text_file; fun line_count (filename:string) : int = { f := fopen_input filename; fun counter (x:string) (count:int)=> count + 1; fun readline () => match readln f with | ""=>None[string] | ?x => Some x endmatch ; return fold_file the readline the counter 0; } println$ line_count "lc.flx"; /////////////////////////////////////////// and completely eliminates all closures. The generated C++ is: ////////////////////////////////////////////// void FLX_REGPARM _init_(FLX_APAR_DECL_ONLY){ _a2983t_6478 f; int _urv5841; int prev_val; _poly_2563t_6484 aux_mv_1148; _a2153t_6479 readline_mv_1158; f = std::fopen(((_a2153t_6479)("lc.flx")).data(),"rt"); prev_val = 0; _5907:; readline_mv_1158 = flx::rtl::ioutil::readln(f); if(!((_a2153t_6479)("") == readline_mv_1158 ) ) goto _5908; aux_mv_1148 = _uctor_(0,0); goto _5909; _5908:; aux_mv_1148 = _uctor_(1, new(*PTF gc, _a2153t_6479_ptr_map)_a2153t_6479(readline_mv_1158)); _5909:; if(!(aux_mv_1148.variant==1) ) goto _5910; prev_val = prev_val + 1 ; goto _5907; _5910:; if(!(aux_mv_1148.variant==0) ) goto _5911; _urv5841 = prev_val; goto _5912; _5911:; FLX_MATCH_FAILURE("./lc.flx",4,1,16,1); _5912:; { _a2153t_6479 _tmp6545 = flx::rtl::strutil::str<int>(_urv5841); *(&std::cout)<<_tmp6545; } *(&std::cout)<<std::endl; } ////////////////////////////////////////////// which is completely flattened by inlining into a single procedural loop. Two things to note: unfortunately, option types currently are variants which require heap allocation for arguments. (The gc must be called manually to clean up). This line: aux_mv_1148 = _uctor_(1, new(*PTF gc, _a2153t_6479_ptr_map)_a2153t_6479(readline_mv_1158)); constructs a struct _uctor_ { int variant, void *data; } where data is a pointer to a heap allocated object which is the variant argument. The second thing to note, is that I had to CHEAT to make the compiler generate optimal code. Technically, reading a file has a side-effect, and 'fun' functions are not allowed to have side-effects. A fast, non-cheating version could be done, but it would be using procedural code instead of functional code. Ocaml still does HOF's way better than Felix, its gc is a lot more efficient (Felix uses malloc and a naive mark-sweep). -- John Skaller <skaller at users dot sf dot net> Felix, successor to C++: http://felix.sf.net ------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/ _______________________________________________ Felix-language mailing list Felix-language@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/felix-language