|
View:
New views
5 Messages
—
Rating Filter:
Alert me
|
|
|
"ocaml_beginners"::[] [Cross-Post] Lazy vs. wrapping a function in (fun () -> x)Recently I was writing some Ocaml code to do some Unix file system
management and I was mistakenly using let statements without knowing that they would be evaluated eagerly. EG. let x dir:string = let cd = (* Unix system call that cd's into dir *) and mkdir = (* Unix system call that makes dir *) in mkdir; cd; ;; I wanted to make the directory first then cd into it, but because the let statements evaluate right away so it tried to cd into a nonexistent directory and failed. I can make it do what I want using the Lazy module: let x dir:string = let cd = lazy (* Unix system call that cd's into dir *) and mkdir = lazy (* Unix system call that makes dir *) in force mkdir; force cd ;; But I can also wrap cp and mkdir into anonymous functions and achieve the same effect: let x dir:string = let cd = (fun () -> (* Unix system call that cd's into dir *)) and mkdir = (fun () -> (* Unix system call that makes dir *)) in mkdir (); cd (); ;; Is there a difference between the approaches in terms of efficiency, style etc? I find both to be equally readable. -deech |
|
|
Re: "ocaml_beginners"::[] [Cross-Post] Lazy vs. wrapping a function in (fun () -> x)I wrap things into functions, since lazy things can only be forced once, but functions can be
executed over and over again. ~~ Robert. deech_99 wrote: > Recently I was writing some Ocaml code to do some Unix file system > management and I was mistakenly using let statements without knowing > that they would be evaluated eagerly. EG. > > let x dir:string = > let cd = (* Unix system call that cd's into dir *) > and mkdir = (* Unix system call that makes dir *) > in > mkdir; > cd; > ;; > > I wanted to make the directory first then cd into it, but because the > let statements evaluate right away so it tried to cd into a > nonexistent directory and failed. I can make it do what I want using > the Lazy module: > > let x dir:string = > let cd = lazy (* Unix system call that cd's into dir *) > and mkdir = lazy (* Unix system call that makes dir *) > in > force mkdir; > force cd > ;; > > But I can also wrap cp and mkdir into anonymous functions and achieve > the same effect: > let x dir:string = > let cd = (fun () -> (* Unix system call that cd's into dir *)) > and mkdir = (fun () -> (* Unix system call that makes dir *)) > in > mkdir (); > cd (); > ;; > > Is there a difference between the approaches in terms of efficiency, > style etc? I find both to be equally readable. > > -deech > > |
|
|
Re: "ocaml_beginners"::[] [Cross-Post] Lazy vs. wrapping a function in (fun () -> x)deech_99 wrote:
> let cd = (fun () -> (* Unix system call that cd's into dir *)) You can also write this as: let cd () = (* Unix system call that cd's into dir *) |
|
|
Re: "ocaml_beginners"::[] [Cross-Post] Lazy vs. wrapping a function in (fun () -> x)You should take care about "and" because the different operands can be
evaluated in any order. In your example, let cd = (* Unix system call that cd's into dir *) and mkdir = (* Unix system call that makes dir *) you are not guaranteed that cd will be evaluated before mkdir. In fact it is guaranteed that there is no order. Therefore you could get the same results with let mkdir = (* Unix system call that makes dir *) and cd = (* Unix system call that cd's into dir *) The best way to avoid this problem is to use "let ... in" or ';' : let cd = (* Unix system call that cd's into dir *) in let mkdir = (* Unix system call that makes dir *) in () As far as I'm concerned, I would write this at the top of the code : let cd = Unix.chdir (* which is equivalent to your "fun () -> ..." *) let mkdir = function s -> Unix.mkdir 0o777 s (* I know it's bad but that's just and example :p *) and use these shiny new cd and mkdir. By the way, why are you forcing the type of your dir variable ? (with dir:string ) You really don't need to. ;) --- Adrien Nader 2008/7/2 Robert Fischer <robert.fischer@...>: > I wrap things into functions, since lazy things can only be forced once, but functions can be > executed over and over again. > > ~~ Robert. > > deech_99 wrote: >> Recently I was writing some Ocaml code to do some Unix file system >> management and I was mistakenly using let statements without knowing >> that they would be evaluated eagerly. EG. >> >> let x dir:string = >> let cd = (* Unix system call that cd's into dir *) >> and mkdir = (* Unix system call that makes dir *) >> in >> mkdir; >> cd; >> ;; >> >> I wanted to make the directory first then cd into it, but because the >> let statements evaluate right away so it tried to cd into a >> nonexistent directory and failed. I can make it do what I want using >> the Lazy module: >> >> let x dir:string = >> let cd = lazy (* Unix system call that cd's into dir *) >> and mkdir = lazy (* Unix system call that makes dir *) >> in >> force mkdir; >> force cd >> ;; >> >> But I can also wrap cp and mkdir into anonymous functions and achieve >> the same effect: >> let x dir:string = >> let cd = (fun () -> (* Unix system call that cd's into dir *)) >> and mkdir = (fun () -> (* Unix system call that makes dir *)) >> in >> mkdir (); >> cd (); >> ;; >> >> Is there a difference between the approaches in terms of efficiency, >> style etc? I find both to be equally readable. >> >> -deech >> >> > > ------------------------------------ > > Archives up to December 31, 2007 are also downloadable at http://www.connettivo.net/cntprojects/ocaml_beginners/ > The archives of the very official ocaml list (the seniors' one) can be found at http://caml.inria.fr > Attachments are banned and you're asked to be polite, avoid flames etc.Yahoo! Groups Links > > > > |
|
|
Re: "ocaml_beginners"::[] [Cross-Post] Lazy vs. wrapping a function in (fun () -> x)On Wednesday 02 July 2008 22:08:25 deech_99 wrote:
> Recently I was writing some Ocaml code to do some Unix file system > management and I was mistakenly using let statements without knowing > that they would be evaluated eagerly. EG. > > let x dir:string = > let cd = (* Unix system call that cd's into dir *) > and mkdir = (* Unix system call that makes dir *) > in > mkdir; > cd; > ;; This code is certainly broken and poor style anyway. Firstly, you have assigned the unit (void) return values of your expressions to two variables and then explicitly ignored them. Secondly, by using "and" instead of two separate let bindings you have left the order of evaluation undefined so the cd and mkdir could occur in either order. Finally, you have annotated a type as if it were the type of "dir" when, in fact, it is the return type of the function "x". I would have used: let x (dir: string) = (* mkdir *) ...Unix system call that makes dir... (* cd *) ...Unix system call that cd's into dir... > I wanted to make the directory first then cd into it, but because the > let statements evaluate right away so it tried to cd into a > nonexistent directory and failed. I can make it do what I want using > the Lazy module: > > let x dir:string = > let cd = lazy (* Unix system call that cd's into dir *) > and mkdir = lazy (* Unix system call that makes dir *) > in > force mkdir; > force cd > ;; > > But I can also wrap cp and mkdir into anonymous functions and achieve > the same effect: > let x dir:string = > let cd = (fun () -> (* Unix system call that cd's into dir *)) > and mkdir = (fun () -> (* Unix system call that makes dir *)) > in > mkdir (); > cd (); > ;; > > Is there a difference between the approaches in terms of efficiency, > style etc? I find both to be equally readable. Using functions is more efficient because the result is not memoized. Also, you can write it more concisely: let x dir = let mkdir() = (* Unix system call that makes dir *) in let cd() = (* Unix system call that cd's into dir *) in mkdir(); cd(); You should using "and" unless it is necessary. Your type annotation is almost certainly superfluous. -- Dr Jon D Harrop, Flying Frog Consultancy Ltd. http://www.ffconsultancy.com/products/?e |
| Free Forum Powered by Nabble | Forum Help |