caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
* [Caml-list] still puzzled on generic types
@ 2011-09-29 15:07 Walter Cazzola
  2011-09-29 15:16 ` David Allsopp
  2011-09-29 15:20 ` Pierre Chopin
  0 siblings, 2 replies; 6+ messages in thread
From: Walter Cazzola @ 2011-09-29 15:07 UTC (permalink / raw)
  To: OCaML Mailing List

Dear all,
waiting for some hints on my other issue for functors and generic I was
playing with an enumerate function (with tail recursion):

   let rec enumerate ?(l':((int * 'a) list)=[]) ?(n=0) l =
     match l with
          h::l1 -> enumerate (l'@[(n,h)]) (n+1) l1
     |  [] -> l'

this should just take a list and return a list of couple whose first
entry is the position in the list of the element; to be clearer:

   enumerate ['a'; 'b'; 'c'] -> [(0,'a'); (1,'b'); (2,'c')];

but this doesn't work as by type mismatch:

  Error: This expression has type (int * 'a) list
         but an expression was expected of type 'a list

Doesn't a matter if I've annotated the type (int * 'a) list
to the optional argument l' when I try to call the function with the new
value it says that the two things don't have the same type.

I'm quite puzzled by this behavior, any explanation/help is welcome as
usual.

Walter
-- 

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

* RE: [Caml-list] still puzzled on generic types
  2011-09-29 15:07 [Caml-list] still puzzled on generic types Walter Cazzola
@ 2011-09-29 15:16 ` David Allsopp
  2011-09-29 15:29   ` Walter Cazzola
  2011-09-29 15:20 ` Pierre Chopin
  1 sibling, 1 reply; 6+ messages in thread
From: David Allsopp @ 2011-09-29 15:16 UTC (permalink / raw)
  To: OCaml List (caml-list@inria.fr)

Walter Cazzola wrote:
> Dear all,
> waiting for some hints on my other issue for functors and generic I was
> playing with an enumerate function (with tail recursion):
> 
>    let rec enumerate ?(l':((int * 'a) list)=[]) ?(n=0) l =
>      match l with
>           h::l1 -> enumerate (l'@[(n,h)]) (n+1) l1
>      |  [] -> l'
> 
> this should just take a list and return a list of couple whose first entry
> is the position in the list of the element; to be clearer:
> 
>    enumerate ['a'; 'b'; 'c'] -> [(0,'a'); (1,'b'); (2,'c')];
> 
> but this doesn't work as by type mismatch:
> 
>   Error: This expression has type (int * 'a) list
>          but an expression was expected of type 'a list

I think it's probably something to do with optional arguments not behaving as you expect. But this is a bad use for optional arguments - you should instead use a nested function to pass the accumulator values. This works fine:

let enumerate l =
  let rec enumerate acc n = function
    h::ls -> enumerate ((n, h)::acc) (n + 1) ls
  | [] -> List.rev acc
  in
    enumerate [] 0 l

Concatenating lists is also expensive in terms of the left list so your function is about as slow as possible! Much better when aiming for tail recursion, accumulate a reversed list and then reverse it in the basis case.


David


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

* Re: [Caml-list] still puzzled on generic types
  2011-09-29 15:07 [Caml-list] still puzzled on generic types Walter Cazzola
  2011-09-29 15:16 ` David Allsopp
@ 2011-09-29 15:20 ` Pierre Chopin
  2011-09-29 15:32   ` Walter Cazzola
  1 sibling, 1 reply; 6+ messages in thread
From: Pierre Chopin @ 2011-09-29 15:20 UTC (permalink / raw)
  To: Walter Cazzola; +Cc: OCaML Mailing List

You need to explicitly name the optional arguments you are passing, 
otherwise the interpreter thinks you are trying to pass l, which should be 'a list : 

 let rec enumerate ?(l'=[]) ?(n=0) l =
   match l with
        h::l1 -> enumerate  ~l':(l'@[(n,h)]) ~n:(n+1) l1
   |  [] -> l'


-Pierre


Le 29 sept. 2011 à 11:07, Walter Cazzola a écrit :

> Dear all,
> waiting for some hints on my other issue for functors and generic I was
> playing with an enumerate function (with tail recursion):
> 
>  let rec enumerate ?(l':((int * 'a) list)=[]) ?(n=0) l =
>    match l with
>         h::l1 -> enumerate (l'@[(n,h)]) (n+1) l1
>    |  [] -> l'
> 
> this should just take a list and return a list of couple whose first
> entry is the position in the list of the element; to be clearer:
> 
>  enumerate ['a'; 'b'; 'c'] -> [(0,'a'); (1,'b'); (2,'c')];
> 
> but this doesn't work as by type mismatch:
> 
> Error: This expression has type (int * 'a) list
>        but an expression was expected of type 'a list
> 
> Doesn't a matter if I've annotated the type (int * 'a) list
> to the optional argument l' when I try to call the function with the new
> value it says that the two things don't have the same type.
> 
> I'm quite puzzled by this behavior, any explanation/help is welcome as
> usual.
> 
> Walter
> -- 
> 
> -- 
> Caml-list mailing list.  Subscription management and archives:
> https://sympa-roc.inria.fr/wws/info/caml-list
> Beginner's list: http://groups.yahoo.com/group/ocaml_beginners
> Bug reports: http://caml.inria.fr/bin/caml-bugs
> 



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

* RE: [Caml-list] still puzzled on generic types
  2011-09-29 15:16 ` David Allsopp
@ 2011-09-29 15:29   ` Walter Cazzola
  2011-09-29 19:04     ` David Allsopp
  0 siblings, 1 reply; 6+ messages in thread
From: Walter Cazzola @ 2011-09-29 15:29 UTC (permalink / raw)
  To: David Allsopp; +Cc: OCaml List (caml-list@inria.fr)

On Thu, 29 Sep 2011, David Allsopp wrote:

> I think it's probably something to do with optional arguments not
> behaving as you expect.

uhm, would be interesting to see what is wrong on my use of the optional
arguments.

> But this is a bad use for optional arguments - you should instead use
> a nested function to pass the accumulator values. This works fine:

yes my first attempt was implemented with nested functions but ,,,

> let enumerate l =
>  let rec enumerate acc n = function
>    h::ls -> enumerate ((n, h)::acc) (n + 1) ls
>  | [] -> List.rev acc
>  in
>    enumerate [] 0 l

... my nested function had a different name than the nextee function and
I was passing l to it too. Could you explain me why your code works? in
particular where does it take the list to enumerate? Silly question I
know but it seems magic to me written in such a way

> Concatenating lists is also expensive in terms of the left list so
> your function is about as slow as possible! Much better when aiming
> for tail recursion, accumulate a reversed list and then reverse it in
> the basis case.

Ok, thanks for the note, but efficiency issues are still far in my
learning curve ;-)

Walter

-- 

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

* Re: [Caml-list] still puzzled on generic types
  2011-09-29 15:20 ` Pierre Chopin
@ 2011-09-29 15:32   ` Walter Cazzola
  0 siblings, 0 replies; 6+ messages in thread
From: Walter Cazzola @ 2011-09-29 15:32 UTC (permalink / raw)
  To: Pierre Chopin; +Cc: OCaML Mailing List

On Thu, 29 Sep 2011, Pierre Chopin wrote:

> You need to explicitly name the optional arguments you are passing,
> otherwise the interpreter thinks you are trying to pass l, which should be 'a list :

> let rec enumerate ?(l'=[]) ?(n=0) l =
>   match l with
>        h::l1 -> enumerate  ~l':(l'@[(n,h)]) ~n:(n+1) l1
>   |  [] -> l'

great point, you are right (what a silly error), thanks a lot.

Walter
-- 

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

* RE: [Caml-list] still puzzled on generic types
  2011-09-29 15:29   ` Walter Cazzola
@ 2011-09-29 19:04     ` David Allsopp
  0 siblings, 0 replies; 6+ messages in thread
From: David Allsopp @ 2011-09-29 19:04 UTC (permalink / raw)
  To: OCaml List (caml-list@inria.fr)

Walter Cazzola wrote:
> On Thu, 29 Sep 2011, David Allsopp wrote:
> 
> > I think it's probably something to do with optional arguments not
> > behaving as you expect.
> 
> uhm, would be interesting to see what is wrong on my use of the optional
> arguments.

Separately answered...

> > But this is a bad use for optional arguments - you should instead use
> > a nested function to pass the accumulator values. This works fine:
> 
> yes my first attempt was implemented with nested functions but ,,,
> 
> > let enumerate l =
> >  let rec enumerate acc n = function
> >    h::ls -> enumerate ((n, h)::acc) (n + 1) ls
> >  | [] -> List.rev acc
> > in
> >    enumerate [] 0 l
> 
> ... my nested function had a different name than the nextee function and I
> was passing l to it too. Could you explain me why your code works? in
> particular where does it take the list to enumerate? Silly question I know
> but it seems magic to me written in such a way

OCaml allows a name to hide a previous use of a name in the scope chain. The closest name moving up the "let .. in .." chains will always be the one used. Very occasionally that can cause some weird bugs but as the types will often differ, it's a clearer way of writing (rather than inventing arbitrary new names or using lots of prime symbols). I defined the innermost [enumerate] using the [function] keyword. You could equivalently write:

let rec enumerate acc n l =
  match l with
    h::ls -> ...

but the function keyword gives you that for free (it's the keyword for introducing an anonymous function with match and simply gives you a match over a single anonymous parameter).

> > Concatenating lists is also expensive in terms of the left list so
> > your function is about as slow as possible! Much better when aiming
> > for tail recursion, accumulate a reversed list and then reverse it in
> > the basis case.
> 
> Ok, thanks for the note, but efficiency issues are still far in my
> learning curve ;-)

Learning not to concatenate lists is part of learning tail recursion - it should be higher up your list ;o)

HTH,


David



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

end of thread, other threads:[~2011-09-29 19:04 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-09-29 15:07 [Caml-list] still puzzled on generic types Walter Cazzola
2011-09-29 15:16 ` David Allsopp
2011-09-29 15:29   ` Walter Cazzola
2011-09-29 19:04     ` David Allsopp
2011-09-29 15:20 ` Pierre Chopin
2011-09-29 15:32   ` Walter Cazzola

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).