From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.1.3 (2006-06-01) on yquem.inria.fr X-Spam-Level: X-Spam-Status: No, score=0.4 required=5.0 tests=AWL autolearn=disabled version=3.1.3 X-Original-To: caml-list@yquem.inria.fr Delivered-To: caml-list@yquem.inria.fr Received: from mail2-relais-roc.national.inria.fr (mail2-relais-roc.national.inria.fr [192.134.164.83]) by yquem.inria.fr (Postfix) with ESMTP id 71587BC37 for ; Wed, 13 May 2009 20:06:35 +0200 (CEST) X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: Aj8CAG+oCkqBrw8EmWdsb2JhbACNTolJAQEBAQEICwoHEbgdhAIF X-IronPort-AV: E=Sophos;i="4.41,189,1241388000"; d="scan'208";a="26115601" Received: from ext.lri.fr ([129.175.15.4]) by mail2-smtp-roc.national.inria.fr with ESMTP/TLS/ADH-AES256-SHA; 13 May 2009 20:06:35 +0200 Received: from localhost (localhost [127.0.0.1]) by ext.lri.fr (Postfix) with ESMTP id E9AE8A43FA; Wed, 13 May 2009 20:06:34 +0200 (CEST) X-Virus-Scanned: Debian amavisd-new at lri.fr Received: from ext.lri.fr ([127.0.0.1]) by localhost (ext.lri.fr [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id gjh4+B45CCkm; Wed, 13 May 2009 20:06:34 +0200 (CEST) Received: from [129.175.4.114] (lri4-114 [129.175.4.114]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by ext.lri.fr (Postfix) with ESMTP id BED27A43E3; Wed, 13 May 2009 20:06:34 +0200 (CEST) Message-ID: <4A0B0C2A.6010303@lri.fr> Date: Wed, 13 May 2009 20:06:34 +0200 From: Cedric Auger User-Agent: Thunderbird 2.0.0.21 (X11/20090318) MIME-Version: 1.0 To: Joel Christner Cc: caml-list@yquem.inria.fr Subject: Re: [Caml-list] Newbie list question References: <9da743ed0905131024u53a207f0s9e963be782f3f2c6@mail.gmail.com> In-Reply-To: <9da743ed0905131024u53a207f0s9e963be782f3f2c6@mail.gmail.com> Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 8bit X-Spam: no; 0.00; lri:01 notation:01 recursive:01 pointers:01 ocaml:01 pointers:01 dup:01 beginner's:01 ocaml:01 bug:01 paris-sud:01 lri:01 umr:01 orsay:01 garbage:01 Joel Christner a écrit : > Hello, > > I posted this question on a couple of newsgroups as well, please > pardon the cross-posting and the newbie question. > > What I'm wanting to do is create a ref list that contains a series of > strings, i.e. > # let varlist = ref [];; > # let a = "a";; > # let b = "b";; > # let c = "c";; > > Then throughout the course of program operation, I will be adding data > into this list, i.e.: > # varlist.contents <- a::varlist.contents;; > # varlist.contents <- b::varlist.contents;; > # varlist.contents <- c::varlist.contents;; I don't know if you know it, but there exist a notation: "!varlist" as syntactic sugar for "varlist.contents" > > Which is working fine, i.e. > # varlist.contents;; > - : string list = ["c"; "b"; "a"] > > But what I'm trying to do next I can't figure out how to get working. > What I'd like to do is have a function that first checks to see if the > item is already in the ref list. If it is, do nothing. If it isn't, > add it. Here's what I tried, which is of course failing. If anyone has > a suggestion on how to make it work would you please help me out? > > # let rec addvariable stringdata listname = > match listname.contents with > | [] -> (listname.contents <- stringdata::listname.contents); () > | [a] -> if a.contents = stringdata then () else (listname.contents <- > stringdata::listname.contents); () > | h::t -> if h.contents = stringdata then () else addvariable > stringdata t.contents > ;; > > Which returns... > This expression has type 'a ref but is here used with type 'a > # Hopefully! You want listname to be a (string list) ref, so: * !listname (listname.contents) is a string list * addvariable has type string -> (string list) ref -> unit but your recursive call is: addvariable stringdata !t where t is a string list (since h::t=!listname), so t has no field "contents", so !t has no meaning; and even if it had a meaning it should be of type string list which can't be applied to addvariable (which expects a (string list) ref) A solution should be: # let addvariable stringdata listnameref = let rec av listname = match listname with | [] -> stringdata::listname | [a] -> if a = stringdata then listname else stringdata::listname | h::t -> if h = stringdata then listname else av t in listnameref := av !listnameref ;; But I am not sure that is what you wanted, and I am not sure you really want to use ref... And one last point: (listname.contents <- stringdata::listname.contents); () is pointless, since it is same as doing "listname.contents <- stringdata::listname.contents" which is already of type unit. I may be wrong, but you seem to be more familiar to C, where pointers are everywhere as soon as you have linked lists, and other complex structures. In ocaml, pointers are well hidden and you just have to rely on the garbage collector. ref are used only when you have no other choice (mainly for a shared variable for all your module). > > Does anyone have any suggestions on how to change the above to make it > work? Basically I want the function to either 1) add the contents to > the list if no duplicates exist and return unit or 2) return unit if it > determines that the string is already there. Try: let add_no_dup strdat lst = if List.exists ((=) strdat) lst then lst else strdat::lst > > Thanks for any and all help > Joel > ------------------------------------------------------------------------ > > _______________________________________________ > Caml-list mailing list. Subscription management: > http://yquem.inria.fr/cgi-bin/mailman/listinfo/caml-list > Archives: http://caml.inria.fr > Beginner's list: http://groups.yahoo.com/group/ocaml_beginners > Bug reports: http://caml.inria.fr/bin/caml-bugs > -- Cédric AUGER Univ Paris-Sud, Laboratoire LRI, UMR 8623, F-91405, Orsay