* How to handle try .... finally properly? @ 2008-12-10 11:15 Conglun Yao 2008-12-10 22:58 ` [Caml-list] " blue storm 2008-12-11 0:09 ` Jacques GARRIGUE 0 siblings, 2 replies; 4+ messages in thread From: Conglun Yao @ 2008-12-10 11:15 UTC (permalink / raw) To: caml-list Sorry, no replies in ocaml-beginner, post it again in caml-list. Dear all, I'm thinking about how to handle try .... finally in ocaml, and found one of camlp4 implementations from http://bluestorm.info/camlp4/dev/try/pa_tryfinally.ml.html Example code adopted from Gabriel Scherer's pa_tryfinally Example Input : let transform f x = GlMat.push(); try f x finally GlMat.pop() Output : let transform f x = (GlMat.push (); let after () = GlMat.pop () and result = try `Result (f x) with | exn -> `Exn exn in (after (); match result with | `Result v -> v | `Exn e -> raise e)) At the first glance, it answered my question. However, it solved the problem partially, only working on functions with one argument. If we feed the * transform * a function with more than one argument, (it is possible because of curring) transform (fun x y -> .... some logic staff .... ) x y will invoke the * after () * before the ((fun x y -> .....) x) y is really executed. Ideally, * transform * function is specified as allowing a function f with only one parameter. But it seems impossible in OCaml, as f : 'a -> 'b doesn't means f can and only accept one argument. ( 'b could be 'c -> 'd ) If we could constraint 'b as a non-function type, it can solve the problem. Or someone knows a better solution to work around the problem. Thanks. Conglun ^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [Caml-list] How to handle try .... finally properly? 2008-12-10 11:15 How to handle try .... finally properly? Conglun Yao @ 2008-12-10 22:58 ` blue storm 2008-12-11 0:09 ` Jacques GARRIGUE 1 sibling, 0 replies; 4+ messages in thread From: blue storm @ 2008-12-10 22:58 UTC (permalink / raw) To: Conglun Yao; +Cc: caml-list > I'm thinking about how to handle try .... finally in ocaml, and found > one of camlp4 implementations from > http://bluestorm.info/camlp4/dev/try/pa_tryfinally.ml.html As you probably noticed, the website is down right now. I'll see that the files are reachable again as soon as possible (in the meantime, if you want specific files, mail me and i'll send them). I should also warn you that the files under the "dev/" prefix are "in development", and not supposed to be stable or free of bugs. > Example code adopted from Gabriel Scherer's pa_tryfinally The example code actually comes from a mailing-list discussion : http://caml.inria.fr/pub/ml-archives/caml-list/2007/01/31db0fd9b7e158f5679991560cb8f876.en.html > At the first glance, it answered my question. However, it solved the > problem partially, only working on functions with one argument. > > If we feed the * transform * a function with more than one argument, > (it is possible because of curring) > > transform (fun x y -> .... some logic staff .... ) x y > > will invoke the * after () * before the ((fun x y -> .....) x) y is > really executed. In that particular case, using "transform f x" to send a function and not a value would be plain wrong : the whole point of transform is "do the dirty things" inside the push/pop of the OpenGL matrix. If you push/pop when building your function, and then apply it later without restoring the matrix at the application time, you'll get uncorrect behavior, and this is not a try/finally-specific issue. > Ideally, * transform * function is specified as allowing a function f > with only one parameter. But it seems impossible in OCaml, > as f : 'a -> 'b doesn't means f can and only accept one argument. ( 'b > could be 'c -> 'd ) If we could constraint 'b as a non-function type, > it can solve the problem. This particular transform function is imperative in nature : the idea is to do side effects at the right moment. You could probably enforce the transformed function to return an unit type without that much loss of generality : let transform (f : 'a -> unit) x = ... That way, you can only transform ('a -> unit) functions, wich is a bit limited (though you could use side-effects to send back values through a reference for example) but should fit the intended use of the function well. In general, there is no solution to your problem. And I'm not even sure there is a problem, as you could wish to protect the partial evaluation of a function from raising exceptions : in some case, the behaviour you find problematic will actually be the expected and right thing to do. If you want your function to be polymorphic, you have to accept it could send anything back. If you want specialized "transform" functions for curryfied two-arguments functions or more, you could write ad-hoc functions for the 3, 4 or 5 parameters case. It sounds ugly but is a practical solution, in the spirit of what the Haskellers have done with their "zip, zip3, zip4, zip5" list functions ( http://www.haskell.org/ghc/docs/latest/html/libraries/base/Data-List.html#17 ). ^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [Caml-list] How to handle try .... finally properly? 2008-12-10 11:15 How to handle try .... finally properly? Conglun Yao 2008-12-10 22:58 ` [Caml-list] " blue storm @ 2008-12-11 0:09 ` Jacques GARRIGUE 2008-12-11 0:52 ` Conglun Yao 1 sibling, 1 reply; 4+ messages in thread From: Jacques GARRIGUE @ 2008-12-11 0:09 UTC (permalink / raw) To: yaoconglun; +Cc: caml-list From: "Conglun Yao" <yaoconglun@gmail.com> > Example Input : > > let transform f x = > GlMat.push(); > try f x > finally GlMat.pop() > > At the first glance, it answered my question. However, it solved the > problem partially, only working on functions with one argument. > > If we feed the * transform * a function with more than one argument, > (it is possible because of curring) > > transform (fun x y -> .... some logic staff .... ) x y > > will invoke the * after () * before the ((fun x y -> .....) x) y is > really executed. A usual workaround in such situations is to first partially apply your function to the (n-1) first arguments, as this should cause no side-effects. Since I suppose you are really talking about transform f x y you should rather write transform (f x) y Note that this will not work properly if partial applications of f cause side-effects (i.e. f is actually "fun x -> ...; fun y -> ..."). This is pretty rare, but I believe this is the case for printf for instance. Jacques Garrigue ^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [Caml-list] How to handle try .... finally properly? 2008-12-11 0:09 ` Jacques GARRIGUE @ 2008-12-11 0:52 ` Conglun Yao 0 siblings, 0 replies; 4+ messages in thread From: Conglun Yao @ 2008-12-11 0:52 UTC (permalink / raw) To: Jacques GARRIGUE; +Cc: caml-list > A usual workaround in such situations is to first partially apply your > function to the (n-1) first arguments, as this should cause no > side-effects. Since I suppose you are really talking about > > transform f x y > > you should rather write > > transform (f x) y > It indeed helps, forces to invoke function f (with two parameters) inside transform. We know how to use transform properly, passing a function with only one parameter or passing curried f with n-1 parameters. But what if we were providing a library, users still might use it incorrectly, thus it will cause a runtime error rather than compile time error. I know it's difficult and (even) impossible to do this kind of compile time checking, zip1, zip2, zip3, .... zip7, mentioned by blue storm, might be a better solution. Ask users to follow the convention, use zip1 if f has one parameter use zip2 if f has two parameters .... use zip7 if f has seven parameters OR transform only accepts function with one parameter, multiple parameters must be passed as a touple type like (a, b, c) > Note that this will not work properly if partial applications of f cause > side-effects (i.e. f is actually "fun x -> ...; fun y -> ..."). > This is pretty rare, but I believe this is the case for printf for > instance. > > Jacques Garrigue > ^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2008-12-11 0:52 UTC | newest] Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2008-12-10 11:15 How to handle try .... finally properly? Conglun Yao 2008-12-10 22:58 ` [Caml-list] " blue storm 2008-12-11 0:09 ` Jacques GARRIGUE 2008-12-11 0:52 ` Conglun Yao
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox