caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
* [Caml-list] Differences between Array and Strings
@ 2011-04-29 11:51 louis.jachiet
  2011-04-29 14:36 ` David Allsopp
  2011-04-30 14:06 ` Philippe Wang
  0 siblings, 2 replies; 6+ messages in thread
From: louis.jachiet @ 2011-04-29 11:51 UTC (permalink / raw)
  To: caml-list

Hi, I'am failing to understand the behavior of the code below. Why the string
is not regenerated ? Why strings and array have not the same behavior ?

> let l () = "1" ;;
> (l ()).[0] <- '2';;
> l ();;
> l()==l();;

> let l () = [|1|] ;;
> (l ()).(0) <- 2;;
> l ();;
> l() == l() ;;

# val l : unit -> string = <fun>
# - : unit = ()
# - : string = "2"
# - : bool = true
#   val l : unit -> int array = <fun>
# - : unit = ()
# - : int array = [|1|]
# - : bool = false

Louis Jachiet

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

* RE: [Caml-list] Differences between Array and Strings
  2011-04-29 11:51 [Caml-list] Differences between Array and Strings louis.jachiet
@ 2011-04-29 14:36 ` David Allsopp
  2011-04-30 14:06 ` Philippe Wang
  1 sibling, 0 replies; 6+ messages in thread
From: David Allsopp @ 2011-04-29 14:36 UTC (permalink / raw)
  To: louis.jachiet, caml-list

Louis Jachiet wrote:
> Hi, I'am failing to understand the behavior of the code below. Why the
> string is not regenerated ? Why strings and array have not the same
> behavior ?

This has been commented on before (see the list archives) - if I understand correctly, it's a consequence of the code generator...

> > let l () = "1" ;;

Compiles to

(let (l/1030 (function param/1032 "1")) (makeblock 0 l/1030))

i.e. a reference to a constant with value "1" - not an allocation. So l always returns the same physical string, rather than allocating a new one. This makes sense if you're assuming that strings are by default used immutably (there have been plenty of discussions in the past on the relative merits of having the same string type for both immutable and mutable strings)

However, the constants clearly aren't used in a pool:

# let f () = "1";;
val f : unit -> string = <fun>
# let g () = "1";;
val g : unit -> string = <fun>

given:

# f () == g ();;
- : bool = false

> > (l ()).[0] <- '2';;
> > l ();;
> > l()==l();;
> 
> > let l () = [|1|] ;;
> > (l ()).(0) <- 2;;

This, however, compiles to

(let (l/1030 (function param/1032 (makearray 1))) (makeblock 0 l/1030))

i.e. it allocates a fresh array each time. The behaviour of the compiler would suggest that its authors considered string "constants" to be just that but the syntax for array literals to be simply sugar for an array allocation followed by initialisation of the members.

As a rule of thumb, if you're dealing with mutable strings, it's a good idea to be very clear who allocated them and where so personally I quite like the fact that the compiler forces you to need to write:

let l () = String.copy "1"

which will behave as you expected.

HTH,


David


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

* Re: [Caml-list] Differences between Array and Strings
  2011-04-29 11:51 [Caml-list] Differences between Array and Strings louis.jachiet
  2011-04-29 14:36 ` David Allsopp
@ 2011-04-30 14:06 ` Philippe Wang
  1 sibling, 0 replies; 6+ messages in thread
From: Philippe Wang @ 2011-04-30 14:06 UTC (permalink / raw)
  To: louis.jachiet; +Cc: caml-list

It's a weird feature of OCaml...

Anyway, if you want to allocate a string, you should write

let l () = String.copy "1"
instead of
let l () = "1"

-- 
Philippe Wang
   mail@philippewang.info



On Fri, Apr 29, 2011 at 1:51 PM,  <louis.jachiet@ens.fr> wrote:
> Hi, I'am failing to understand the behavior of the code below. Why the string
> is not regenerated ? Why strings and array have not the same behavior ?
>
>> let l () = "1" ;;
>> (l ()).[0] <- '2';;
>> l ();;
>> l()==l();;
>
>> let l () = [|1|] ;;
>> (l ()).(0) <- 2;;
>> l ();;
>> l() == l() ;;
>
> # val l : unit -> string = <fun>
> # - : unit = ()
> # - : string = "2"
> # - : bool = true
> #   val l : unit -> int array = <fun>
> # - : unit = ()
> # - : int array = [|1|]
> # - : bool = false
>
> Louis Jachiet


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

* Re: [Caml-list] Differences between Array and Strings
  2011-04-30 13:34   ` David Allsopp
@ 2011-04-30 23:10     ` Martin Jambon
  0 siblings, 0 replies; 6+ messages in thread
From: Martin Jambon @ 2011-04-30 23:10 UTC (permalink / raw)
  To: caml-list

On 04/30/11 06:34, David Allsopp wrote:
> Radu Grigore wrote:
>> On Friday, April 29, 2011 12:51:59 PM UTC+1, louis....@ens.fr wrote:
>>>> let l () = "1" ;;
>>>> [...]
>>>> l()==l();;
>>> # val l : unit -> string = <fun>
>>> # [...]
>>> # - : bool = true
>>
>> Is there a good reason for this behavior?
> 
> Whether it's good is debatable, but in most instances you don't want a fresh string being allocated each time for a constant value as it would be a waste of time and memory (most strings are used immutably).

I concur.
And the strings that we mutate are buffers which are not created from
string literals anyway.


Martin

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

* RE: [Caml-list] Differences between Array and Strings
  2011-04-30 11:03 ` Radu Grigore
@ 2011-04-30 13:34   ` David Allsopp
  2011-04-30 23:10     ` Martin Jambon
  0 siblings, 1 reply; 6+ messages in thread
From: David Allsopp @ 2011-04-30 13:34 UTC (permalink / raw)
  To: caml-list

Radu Grigore wrote:
> On Friday, April 29, 2011 12:51:59 PM UTC+1, louis....@ens.fr wrote:
> > > let l () = "1" ;;
> > > [...]
> > > l()==l();;
> > # val l : unit -> string = <fun>
> > # [...]
> > # - : bool = true
> 
> Is there a good reason for this behavior?

Whether it's good is debatable, but in most instances you don't want a fresh string being allocated each time for a constant value as it would be a waste of time and memory (most strings are used immutably).

> My first thought was that that code should behave the same as
> 
>   let f () = ref () in f () == f ()
> (A satisfying explanation would *not* involve the compiler.)

Look at the OCaml language specification - "1" is a constant and the result of that expression is the constant itself (6.7.1). [|1|] is an array expression and the result of that expression is a "1-element array, whose element(s) are initialized with the value(s) 1" (roughly quoting section 6.7.3). i.e. an array expression implies the creation of the array as its result but a constant evaluation does not.

C behaves in the same (or at least in a very similar) way... not that that could ever be used as a justification for behaviour in a sane language like OCaml ;o)
 

David 


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

* Re: [Caml-list] Differences between Array and Strings
       [not found] <fa.YVp+LBcZBn2VVSqyBV+/Bw0Mb/I@ifi.uio.no>
@ 2011-04-30 11:03 ` Radu Grigore
  2011-04-30 13:34   ` David Allsopp
  0 siblings, 1 reply; 6+ messages in thread
From: Radu Grigore @ 2011-04-30 11:03 UTC (permalink / raw)
  To: fa.caml; +Cc: caml-list

On Friday, April 29, 2011 12:51:59 PM UTC+1, louis....@ens.fr wrote:
> > let l () = "1" ;;
> > [...]
> > l()==l();;
> # val l : unit -> string = <fun>
> # [...]
> # - : bool = true

Is there a good reason for this behavior? My first thought was that that code should behave the same as

  let f () = ref () in f () == f ()

(A satisfying explanation would *not* involve the compiler.)

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

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

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-04-29 11:51 [Caml-list] Differences between Array and Strings louis.jachiet
2011-04-29 14:36 ` David Allsopp
2011-04-30 14:06 ` Philippe Wang
     [not found] <fa.YVp+LBcZBn2VVSqyBV+/Bw0Mb/I@ifi.uio.no>
2011-04-30 11:03 ` Radu Grigore
2011-04-30 13:34   ` David Allsopp
2011-04-30 23:10     ` Martin Jambon

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