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

Reply via email to