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
[email protected]
https://lists.sourceforge.net/lists/listinfo/felix-language