Version française
Home     About     Download     Resources     Contact us    

This site is updated infrequently. For up-to-date information, please visit the new OCaml website at

Browse thread
Newbie list question
[ Home ] [ Index: by date | by threads ]
[ Search: ]

[ Message by date: previous | next ] [ Message in thread: previous | next ] [ Thread: previous | next ]
Date: 2009-05-13 (18:06)
From: Cedric Auger <Cedric.Auger@l...>
Subject: Re: [Caml-list] Newbie list question
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
> #
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
 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 <- 
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 
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.

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:
> Archives:
> Beginner's list:
> Bug reports:

Cédric AUGER

Univ Paris-Sud, Laboratoire LRI, UMR 8623, F-91405, Orsay