Version française
Home     About     Download     Resources     Contact us    
Browse thread
Avoiding shared data
[ Home ] [ Index: by date | by threads ]
[ Search: ]

[ Message by date: previous | next ] [ Message in thread: previous | next ] [ Thread: previous | next ]
Date: -- (:)
From: Wolfgang Lux <wlux@u...>
Subject: Re: Ant: Re: [Caml-list] Avoiding shared data
Pal-Kristian Engstad wrote:

> The author argues that "Writing loops with tail-recursive function 
> calls is
> the equivalent of writing them with goto’s." and gives an example that 
> I've
> rewritten from Scheme-ish into OCaml-ish:
>
> let myfunc l =
>   let rec loop rest result =
>     match rest with
>       | [] -> List.rev result
>       | x::xs ->
> 	  if xpred x then
> 	    let y = verbose_code_using_x x in
> 	      if ypred y then
> 		let z = verbose_code_using_y y in
> 		  loop xs (z_expression :: result)
> 	      else
> 		loop xs result
> 	  else
> 	    loop xs result
>   in
>     loop l []
> ;;
>
> Obviously, one would like to refactor this into HOF, but in this 
> situation it
> is hard to see how one should do it.

Oh come on! IMHO, most loops can easily be transformed by using map, 
filter,
fold_left, and fold_right. The example given is no exception. The loop
essentially applies some complex code to every element of the list and
includes the result in the output list only if a condition is satisfied
that is computed along with result. This is always the structure of a 
fold.
(If the condition were independent from the result one could combine a 
filter
and a map.) Thus, a straight forward rewrite of the loop is:

   let myfunc l =
     let f x result =
           if xpred then
             let y = verbose_code_using_x x in
               if ypred y then
                 let z = verbose_code_using_y y in
                   z_expression :: result
               else
                 result
           else
             result
     in
       fold_right f l []

Furthermore, I would turn the two if expressions into local functions

   let myfunc l =
     let g y result =
           if ypred y then
             let z = verbose_code_using_y y in z_expression :: result
           else
             result
     in let f x result =
          if xpred x then
            let y = verbose_code_using_x x in g y result
          else
            result
     in fold_right f l []

Regards
Wolfgang