From mboxrd@z Thu Jan 1 00:00:00 1970 Received: (from majordomo@localhost) by pauillac.inria.fr (8.7.6/8.7.3) id VAA26150; Mon, 17 Nov 2003 21:44:47 +0100 (MET) X-Authentication-Warning: pauillac.inria.fr: majordomo set sender to owner-caml-list@pauillac.inria.fr using -f Received: from concorde.inria.fr (concorde.inria.fr [192.93.2.39]) by pauillac.inria.fr (8.7.6/8.7.3) with ESMTP id VAA26073 for ; Mon, 17 Nov 2003 21:44:45 +0100 (MET) Received: from herd.plethora.net (herd.plethora.net [205.166.146.1]) by concorde.inria.fr (8.11.1/8.11.1) with ESMTP id hAHKii120822 for ; Mon, 17 Nov 2003 21:44:44 +0100 (MET) Received: from bhurt.plethora.net (bhurt.plethora.net [205.166.146.49]) by herd.plethora.net (8.11.6/8.10.1) with ESMTP id hAHKiYC28943; Mon, 17 Nov 2003 14:44:35 -0600 (CST) Date: Mon, 17 Nov 2003 15:43:59 -0600 (CST) From: Brian Hurt X-X-Sender: bhurt@localhost.localdomain To: "chris.danx" cc: caml-list@inria.fr Subject: Re: [Caml-list] Closure & Ref In-Reply-To: <3FB92396.4060908@ntlworld.com> Message-ID: MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII X-Loop: caml-list@inria.fr X-Spam: no; 0.00; caml-list:01 toying:01 generic:01 generics:01 hash:01 chris:01 ints:01 ints:01 ocaml:01 closure:01 int:01 int:01 rec:01 nov:01 simpler:01 Sender: owner-caml-list@pauillac.inria.fr Precedence: bulk On Mon, 17 Nov 2003, chris.danx wrote: > Hi, > > I was toying with ocaml just now and have successfully written a > function that takes and int that produces a function that takes an int > to add to the original. > > let prodAdd x = > let value = ref x in > fun y -> !value + y;; Since you're not setting the reference, why have one? Instead, try: let prodAdd x = fun y -> x + y But we can do it simpler than that: let prodAdd x y = x + y And use partial function application. (prodAdd 4) returns a function which adds 4 to whatever int parameter passed to it. > > Now I want to do a function that takes a ref to a list and returns a > function that adds items to the list and produce a function that returns > another that returns the list. How do I do that? > > let prod_list_acc a = > fun x -> a := x :: !a; true;; > > let return_acc a = > fun () -> !a;; > > but that gives a "unit -> int list" =. How do you get a copy of the > list values? Now you're setting the reference. But prod_list_acc and return_acc need to share the reference. Now, I for one, hate globals. This is the result of programming for years in C. What I would do is write a function which returns a tuple of two functions, and accumlator function and a current list function, like: let make_listacc () = let r: int list ref = ref [] in let acc x = r := x :: !r and lst () = !r in acc, lst ;; This allows you to have multiple different lists being constructed independently. Note, the above code is actually more generic than it looks- I had to add an explicit type statement to make it "come out correct". Without the explicit type information: let make_listacc () = let r = ref [] in let acc x = r := x :: !r and lst () = !r in acc, lst ;; The function is both clearer than the original, and creates lists of any type, not just ints. If you hear me bitching about C++ and Java making generics "special and extraordinary", this is a classic example of what I'm kvetching about. You'd use make_listacc like: let my_acc, my_list = make_listacc() in my_acc 3; my_acc 4; my_acc 5; my_list () ;; The above code returns [5;4;3] (note, the list is built backward!). The most common way to access members of a list is to use what is called "list comprehensions". Don't let the names fool you- these are just functions that walk the list and do something on every element of the list. Look at List.iter and List.fold_left. So let's say I want to take a list of ints and sum them. I could simply do: List.fold_left (fun x y -> x + y) 0 lst Note that + is just a function, so I could just as easily have done: List.fold_left (+) 0 lst to do the same thing. The second most common way to access members of a list is to write a short recursive function. Say I wanted to know if the list contained a given number. I might write: let rec has_num x = function | [] -> false | h :: t -> if (h == x) then true else has_num x t ;; If you want to access specific members of a list (other than the head), I wouldn't recommend using a list, but instead some other datastructure (an array or hash table being the obvious choices). -- "Usenet is like a herd of performing elephants with diarrhea -- massive, difficult to redirect, awe-inspiring, entertaining, and a source of mind-boggling amounts of excrement when you least expect it." - Gene Spafford Brian ------------------- To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/ Beginner's list: http://groups.yahoo.com/group/ocaml_beginners