caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
* Newbie list question
@ 2009-05-13 17:24 Joel Christner
  2009-05-13 18:06 ` [Caml-list] " Cedric Auger
  2009-05-15 13:49 ` Florian Hars
  0 siblings, 2 replies; 4+ messages in thread
From: Joel Christner @ 2009-05-13 17:24 UTC (permalink / raw)
  To: caml-list, Joel Christner

[-- Attachment #1: Type: text/plain, Size: 1657 bytes --]

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;;

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
#

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.

Thanks for any and all help
Joel

[-- Attachment #2: Type: text/html, Size: 1930 bytes --]

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [Caml-list] Newbie list question
  2009-05-13 17:24 Newbie list question Joel Christner
@ 2009-05-13 18:06 ` Cedric Auger
  2009-05-13 20:24   ` John Li
  2009-05-15 13:49 ` Florian Hars
  1 sibling, 1 reply; 4+ messages in thread
From: Cedric Auger @ 2009-05-13 18:06 UTC (permalink / raw)
  To: Joel Christner; +Cc: caml-list

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


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [Caml-list] Newbie list question
  2009-05-13 18:06 ` [Caml-list] " Cedric Auger
@ 2009-05-13 20:24   ` John Li
  0 siblings, 0 replies; 4+ messages in thread
From: John Li @ 2009-05-13 20:24 UTC (permalink / raw)
  To: Cedric Auger; +Cc: Joel Christner, caml-list

On Wed, May 13, 2009 at 08:06:34PM +0200, Cedric Auger wrote:
> Joel Christner a écrit :
>>
>> 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"

Yes, but of course.

# !varlist <- a :: !varlist

won't work. There's more sugar for that:

# varlist := a :: !varlist

is equivalent to the 3 lines you originally had.


-John


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [Caml-list] Newbie list question
  2009-05-13 17:24 Newbie list question Joel Christner
  2009-05-13 18:06 ` [Caml-list] " Cedric Auger
@ 2009-05-15 13:49 ` Florian Hars
  1 sibling, 0 replies; 4+ messages in thread
From: Florian Hars @ 2009-05-15 13:49 UTC (permalink / raw)
  To: Joel Christner; +Cc: caml-list

Joel Christner schrieb:
> What I'm wanting to do is create a ref list that contains a series of
> strings

Judging from your code, you really do not want to do this (I just sped up
a program of mine by at least two orders of magnitude fixing an error like
that). What you probably want to do is

module S = Set.Make(String);;

let s = ref S.empty;;

let add_variable_ref s v = 
  s := S.add v !s;;

add_variable_ref s "foo";;
add_variable_ref s "bar";;
S.elements !s;;

Even better if you can structure your code to get rid of the ref:

# let add_variable s v = S.add v s;;
val add_variable : S.t -> S.elt -> S.t = <fun>
# let vars = List.fold_left add_variable S.empty ["Foo"; "Bar"; "Baz"; "Foo"; "Qux"; "Baz"];;
val vars : S.t = <abstr>
# S.elements vars;;
- : S.elt list = ["Bar"; "Baz"; "Foo"; "Qux"]

Of course, this works as well, but uses more stack space as right folds are
not tail recursive:

# let vars' = List.fold_right S.add ["Foo"; "Bar"; "Baz"; "Foo"; "Qux"; "Baz"] S.empty;;
val vars' : S.t = <abstr>
# S.elements vars';;
- : S.elt list = ["Bar"; "Baz"; "Foo"; "Qux"]

-- Florian.


^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2009-05-15 13:49 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-05-13 17:24 Newbie list question Joel Christner
2009-05-13 18:06 ` [Caml-list] " Cedric Auger
2009-05-13 20:24   ` John Li
2009-05-15 13:49 ` Florian Hars

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).