caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
* [Caml-list] Repacking modules gives unexpected results
@ 2015-05-12 21:47 peterfrey
  2015-05-12 22:36 ` Jeremy Yallop
  2015-05-15 22:28 ` peterfrey
  0 siblings, 2 replies; 3+ messages in thread
From: peterfrey @ 2015-05-12 21:47 UTC (permalink / raw)
  To: caml-list

(* I am running into a very strange problem with re-packed modules:
   re-packed instances of variables take on their new values, but internal
   functions that depend on those values are still tied to the initial 
values.

   module Make is initialized to buf = "foo" and len = (Bytes.length buf)

   re_pack substitutes buf = "aBar" and len = 4
   gives the result:

E.show():len:3    buf:foo    E.buf:foo    E.len:3
E.show():len:3    buf:foo    E.buf:aBar    E.len:4

   i.e.: the data reported by show() is not changed.
   E.buf and E.len reflect the results of re_pack
   The second line above SHOULD be as follows:

E.show():len:4    buf:aBar    E.buf:aBar    E.len:4

   In fact it is, IFF the line
       let show() = sprintf"len:%i\tbuf:%s" len buf
   is also included int the repacking.

   Perhaps I am trying to do something that is not supported.
*)

open Printf

module type ELT = sig
   val buf : bytes
   val len : int
   val show : unit -> string
end

module Make ( Data: sig val initial : string end) : ELT = struct
   let buf  = Data.initial
   let len  = (Bytes.length Data.initial)
   let show() = sprintf"len:%i\tbuf:%s" len buf
end

module Reg = struct
   let show (module E:ELT) =
   sprintf"E.show():%s\tE.buf:%s\tE.len:%i\n" (E.show()) E.buf E.len

   let re_pack env =
     (module struct include (val env:ELT) let buf = "aBar"
                                          let len = 4
       (* let show() = sprintf"len:%i\tbuf:%s" len buf *)
       (* with this it will 'work' ... *)
     end : ELT )
end

let byte_source_of_string initial =
   (module struct include Make(struct let initial = initial end) end : 
ELT )
;;
open Reg;;
let s = byte_source_of_string "foo";;
print_endline (show s);;
let s' = re_pack s;;
print_endline (show s');;

(*  show s' prints 0 - 2 demonstrating that ofs=2 and E.show() = 0 *)

Peter Frey


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

* Re: [Caml-list] Repacking modules gives unexpected results
  2015-05-12 21:47 [Caml-list] Repacking modules gives unexpected results peterfrey
@ 2015-05-12 22:36 ` Jeremy Yallop
  2015-05-15 22:28 ` peterfrey
  1 sibling, 0 replies; 3+ messages in thread
From: Jeremy Yallop @ 2015-05-12 22:36 UTC (permalink / raw)
  To: peterfrey; +Cc: caml-list

On 12 May 2015 at 22:47, peterfrey <pjfrey@sympatico.ca> wrote:
> (* I am running into a very strange problem with re-packed modules:
>   re-packed instances of variables take on their new values, but internal
>   functions that depend on those values are still tied to the initial
> values.

I think you're thinking of modules as a way of defining something like
objects, where variables bound within the module behave like member
variables that can be overridden.  In fact, modules are not very much
like objects, and variables bound in modules have the same lexical
scope as most of the rest of the language.  In particular, in this
definition:

  struct
    let buf  = Data.initial
    let len  = (Bytes.length Data.initial)
    let show() = sprintf"len:%i\tbuf:%s" len buf
  end

the names 'len' and 'buf' in the definition of 'show' will always
refer to the nearest bindings for those names in the scope *in which
show was defined*, no matter what you do elsewhere in the program.
OCaml programmers tend to think of this kind of lexical scope as a
feature, since it makes it quite straightforward to understand and
refactor code.

A little further down you have

   include (val env:ELT) let buf = "aBar"
                                  let len = 4

which, when you substitute in the value of 'env', and expand the
'include', gives you something equivalent to this:

    let buf  = Data.initial
    let len  = (Bytes.length Data.initial)
    let show() = sprintf"len:%i\tbuf:%s" len buf
    let buf = "aBar"
    let len = 4

Although the names 'buf' and 'len' are rebound, the rebindings don't
have any effect on the uses of the previous bindings in the definition
of 'show'.  Again, there's nothing module-specific going on here;
you'll see the same behaviour if you enter the definitions at the
top-level.

OCaml does have a system of objects and classes which behaves in
something like the way that you're expecting.  For example, you can
write:

  class make ~initial =
    object
      val buf = initial
      val len = String.length initial
      method show = Printf.sprintf "len:%i\tbuf:%s" len buf
      method repack ~buf ~len = {< buf = buf; len = len >}
    end

and then

  # let s = new make ~initial:"foo";;
  val s : make = <obj>
  # s#show;;
  - : string = "len:3\tbuf:foo"
  # let s' = s#repack ~buf:"aBar" ~len:4;;
  val s' : make = <obj>
  # s'#show;;
  - : string = "len:4\tbuf:aBar"

Jeremy.

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

* Re: [Caml-list] Repacking modules gives unexpected results
  2015-05-12 21:47 [Caml-list] Repacking modules gives unexpected results peterfrey
  2015-05-12 22:36 ` Jeremy Yallop
@ 2015-05-15 22:28 ` peterfrey
  1 sibling, 0 replies; 3+ messages in thread
From: peterfrey @ 2015-05-15 22:28 UTC (permalink / raw)
  To: caml-list


On 15-05-12 05:47 PM, peterfrey wrote:
> For quite a while now I have been using first class modules as a sort of
     replacement for objects.  You are right, of course, I did not 
notice that the variables were not
    bound (not even after simplifying the code to almost nothing).
    'Obvious' is not always obvious...
   Thanks a lot, I don't know how much longer I would have stared at this.
>
> Peter Frey
>
>


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

end of thread, other threads:[~2015-05-15 22:28 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-05-12 21:47 [Caml-list] Repacking modules gives unexpected results peterfrey
2015-05-12 22:36 ` Jeremy Yallop
2015-05-15 22:28 ` peterfrey

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