Loading ...
Sorry, an error occurred while loading the content.

Self-referencing array init

Expand Messages
  • Alan Post
    ocaml 3.06 I m sure there s a simple way to do this, but I just can t think of it. I want to do something like: let arr = Array.init 10 (...use arr...) In my
    Message 1 of 11 , Oct 1, 2003
    • 0 Attachment
      ocaml 3.06

      I'm sure there's a simple way to do this, but I just can't think of
      it.

      I want to do something like:

      let arr = Array.init 10 (...use arr...)

      In my case, I want to stick a bunch of objects in an array, and
      reference that array in one of their callbacks. A simplified (and
      less sensible) version would look something like:

      let arr = Array.init 10
      (fun i -> Some (fun () -> if arr.(9-i) = None then
      prerr_endline "Ouch" ))

      When I feed this to ocaml, it complains about arr being unbound.
      Doing a "let rec" yields the following amusing message:

      This kind of expression is not allowed as right-hand side of `let rec'

      In the silly case above, there's a reasonable default value, but
      that's not the case in my actual (lablgtk2) program.

      I don't like the following alternative:

      let arr = ref None
      in arr := Some (Array.init 10 ...)
    • Remi Vanicat
      ... you could look to : http://pauillac.inria.fr/caml/caml-list/2811.html and use one of the functions Pierre Weis defines there. or make you own. ... Ocaml
      Message 2 of 11 , Oct 1, 2003
      • 0 Attachment
        Alan Post <apost@...> writes:

        > ocaml 3.06
        >
        > I'm sure there's a simple way to do this, but I just can't think of
        > it.
        >
        > I want to do something like:
        >
        > let arr = Array.init 10 (...use arr...)
        >
        > In my case, I want to stick a bunch of objects in an array, and
        > reference that array in one of their callbacks. A simplified (and
        > less sensible) version would look something like:
        >
        > let arr = Array.init 10
        > (fun i -> Some (fun () -> if arr.(9-i) = None then
        > prerr_endline "Ouch" ))

        you could look to :

        http://pauillac.inria.fr/caml/caml-list/2811.html

        and use one of the functions Pierre Weis defines there.
        or make you own.


        >
        > When I feed this to ocaml, it complains about arr being unbound.
        > Doing a "let rec" yields the following amusing message:
        >
        > This kind of expression is not allowed as right-hand side of `let
        > rec'

        Ocaml make a lot of statical check. So he forbid what you are trying
        (the right-hand side of let rec must not be the result of the
        evaluation of some function).

        >
        > In the silly case above, there's a reasonable default value, but
        > that's not the case in my actual (lablgtk2) program.

        I don't know what you are trying exactly, but why don't you create
        first your array, then iterate over it for creating your callback.

        --
        Rémi Vanicat
        remi.vanicat@...
      • Nicolas Cannasse
        [...] ... This is not an alternative, since arr will still be None until Array.init is finished. BTW, you can t have an array referencing itself because it s
        Message 3 of 11 , Oct 1, 2003
        • 0 Attachment
          [...]
          > I don't like the following alternative:
          >
          > let arr = ref None
          > in arr := Some (Array.init 10 ...)

          This is not an alternative, since arr will still be None until Array.init is
          finished.
          BTW, you can't have an array referencing itself because it's type would be :

          array array array array array .....

          (recursive type :)

          Nicolas Cannasse
        • Alan Post
          ... My callbacks won t get called until after the array is initialized. I just want to be able to tear off arr into the closure context. ... In the example
          Message 4 of 11 , Oct 1, 2003
          • 0 Attachment
            In article <001b01c38805$f781f890$6f01a8c0@PWARP>, Nicolas Cannasse wrote:
            > [...]
            >> I don't like the following alternative:
            >>
            >> let arr = ref None
            >> in arr := Some (Array.init 10 ...)
            >
            > This is not an alternative, since arr will still be None until Array.init is
            > finished.

            My callbacks won't get called until after the array is initialized. I
            just want to be able to "tear off" arr into the closure context.

            > BTW, you can't have an array referencing itself because it's type would be :
            >
            > array array array array array .....
            >
            > (recursive type :)

            In the example I posted:

            let arr = Array.init 10
            (fun i -> Some (fun () -> if arr.(9-i) = None then
            prerr_endline "Ouch" ))

            the type of arr is just fine: it is an array of (unit -> unit)
            options.
          • Alan Post
            ... I will do that. I was just hoping to initialize it properly the first time. I still don t see what the problem is with passing around the address of the
            Message 5 of 11 , Oct 1, 2003
            • 0 Attachment
              In article <877k3ps1gh.dlv@...>, Remi Vanicat wrote:
              >>
              >> In the silly case above, there's a reasonable default value, but
              >> that's not the case in my actual (lablgtk2) program.
              >
              > I don't know what you are trying exactly, but why don't you create
              > first your array, then iterate over it for creating your callback.

              I will do that. I was just hoping to initialize it properly the first
              time. I still don't see what the problem is with passing around the
              address of the beginning of an array during its initialization.
            • Richard Jones
              ... Similar to a problem I ve just encountered. Here s my minimal test case: # type tree = Leaf of int | Node of (string * tree) list ;; type tree = Leaf of
              Message 6 of 11 , Oct 1, 2003
              • 0 Attachment
                On Wed, Oct 01, 2003 at 12:21:18PM +0200, Remi Vanicat wrote:
                > Ocaml make a lot of statical check. So he forbid what you are trying
                > (the right-hand side of let rec must not be the result of the
                > evaluation of some function).

                Similar to a problem I've just encountered. Here's my minimal test case:

                # type tree = Leaf of int | Node of (string * tree) list ;;
                type tree = Leaf of int | Node of (string * tree) list

                # let empty = Node [] ;;
                val empty : tree = Node []

                # let top = Node [ "Entry", entry1 ]
                and entry1 = empty ;;
                Unbound value entry1

                # let rec top = Node [ "Entry", entry1 ]
                and entry1 = empty ;;
                This kind of expression is not allowed as right-hand side of `let rec'

                My aim here was to define the tree in a natural order (top-level nodes
                at the top of the page, and so on down the page). So I used let ... and
                or let rec ... and.

                But I don't understand why let rec has this restriction (ordinary
                'let' would work just fine).

                Rich.

                --
                Richard Jones. http://www.annexia.org/ http://freshmeat.net/users/rwmj
                Merjis Ltd. http://www.merjis.com/ - all your business data are belong to you.
                MONOLITH is an advanced framework for writing web applications in C, easier
                than using Perl & Java, much faster and smaller, reusable widget-based arch,
                database-backed, discussion, chat, calendaring:
                http://www.annexia.org/freeware/monolith/
              • Martin Jambon
                ... You simply can t destructure the value that you are creating. For example this can t work: let rec array = Array.init n (fun i - array.(i)) If you want to
                Message 7 of 11 , Oct 1, 2003
                • 0 Attachment
                  On Wed, 1 Oct 2003, Alan Post wrote:

                  > When I feed this to ocaml, it complains about arr being unbound.
                  > Doing a "let rec" yields the following amusing message:
                  >
                  > This kind of expression is not allowed as right-hand side of `let rec'

                  You simply can't destructure the value that you are creating.
                  For example this can't work:

                  let rec array = Array.init n (fun i -> array.(i))

                  If you want to create a recursive data structure, you can't use function
                  calls using the object you are creating as an argument.

                  This is allowed:
                  let rec list = 1 :: list (* :: is not a function *)

                  type a = A of a
                  let rec a = A a (* pointer to itself *)



                  This not allowed:
                  let rec x = x + 1 (* ( + ) is a function *)

                  let rec l = (fun _ -> []) l

                  let rec l = l (* one type constructor is required *)



                  -- Martin
                • Alan Post
                  ... I guess the problem is that the compiler is not able to distinguish a safe use ( tearing off the value for later use in a closure) from an unsafe use
                  Message 8 of 11 , Oct 1, 2003
                  • 0 Attachment
                    In article <Pine.LNX.4.40.0310011220400.1489-100000@pc-bioinfo1>, Martin Jambon wrote:
                    > On Wed, 1 Oct 2003, Alan Post wrote:
                    >
                    >> When I feed this to ocaml, it complains about arr being unbound.
                    >> Doing a "let rec" yields the following amusing message:
                    >>
                    >> This kind of expression is not allowed as right-hand side of `let rec'
                    >
                    > You simply can't destructure the value that you are creating.
                    > For example this can't work:
                    >
                    > let rec array = Array.init n (fun i -> array.(i))

                    I guess the problem is that the compiler is not able to distinguish a
                    safe use ("tearing off" the value for later use in a closure) from an
                    unsafe use (using the value before it is initialized). So it
                    disallows all but the simplest of uses.

                    Sorry, it was just hard to wrap my brain around, given my day job as a
                    C++ coder.
                  • Remi Vanicat
                    ... Look to the following in pseudo ocaml : class [ a] foo = object method callback f = (f () : a) end let rec array = Array.init 100 (fun _ - let f = new
                    Message 9 of 11 , Oct 1, 2003
                    • 0 Attachment
                      Alan Post <apost@...> writes:

                      > In article <877k3ps1gh.dlv@...>, Remi Vanicat wrote:
                      >>>
                      >>> In the silly case above, there's a reasonable default value, but
                      >>> that's not the case in my actual (lablgtk2) program.
                      >>
                      >> I don't know what you are trying exactly, but why don't you create
                      >> first your array, then iterate over it for creating your callback.
                      >
                      > I will do that. I was just hoping to initialize it properly the first
                      > time. I still don't see what the problem is with passing around the
                      > address of the beginning of an array during its initialization.
                      >

                      Look to the following in pseudo ocaml :

                      class ['a] foo =
                      object
                      method callback f = (f () : 'a)
                      end

                      let rec array = Array.init 100
                      (fun _ -> let f = new foo in f #callback (fun () -> array.(20)))

                      what this code should do ? there is no obvious semantic for it, so
                      ocaml forbid it.

                      In fact a lot of problem may appear when the right hand side of a let
                      rec is the result of the application of some function.


                      --
                      Rémi Vanicat
                      remi.vanicat@...
                    • Remi Vanicat
                      Alan Post writes: [...] ... this is exactly the problem. [...] -- Rémi Vanicat remi.vanicat@laposte.net
                      Message 10 of 11 , Oct 1, 2003
                      • 0 Attachment
                        Alan Post <apost@...> writes:

                        [...]

                        > I guess the problem is that the compiler is not able to distinguish a
                        > safe use ("tearing off" the value for later use in a closure) from an
                        > unsafe use (using the value before it is initialized). So it
                        > disallows all but the simplest of uses.

                        this is exactly the problem.

                        [...]


                        --
                        Rémi Vanicat
                        remi.vanicat@...
                      • Remi Vanicat
                        ... I was surprised this doesn t work, so I ve just test it : # type tree = Leaf of int | Node of (string * tree) list ;; type tree = Leaf of int | Node of
                        Message 11 of 11 , Oct 1, 2003
                        • 0 Attachment
                          Richard Jones <rich@...> writes:

                          > On Wed, Oct 01, 2003 at 12:21:18PM +0200, Remi Vanicat wrote:
                          >> Ocaml make a lot of statical check. So he forbid what you are trying
                          >> (the right-hand side of let rec must not be the result of the
                          >> evaluation of some function).
                          >
                          > Similar to a problem I've just encountered. Here's my minimal test case:
                          >
                          > # type tree = Leaf of int | Node of (string * tree) list ;;
                          > type tree = Leaf of int | Node of (string * tree) list
                          >
                          > # let empty = Node [] ;;
                          > val empty : tree = Node []
                          >
                          > # let top = Node [ "Entry", entry1 ]
                          > and entry1 = empty ;;
                          > Unbound value entry1
                          >
                          > # let rec top = Node [ "Entry", entry1 ]
                          > and entry1 = empty ;;
                          > This kind of expression is not allowed as right-hand side of `let
                          > rec'


                          I was surprised this doesn't work, so I've just test it :

                          # type tree = Leaf of int | Node of (string * tree) list ;;
                          type tree = Leaf of int | Node of (string * tree) list
                          # let empty = Node [] ;;
                          val empty : tree = Node []
                          # let rec top = Node [ "Entry", entry1 ]
                          and entry1 = empty ;;
                          val top : tree = Node [("Entry", Node [])]
                          val entry1 : tree = Node []


                          This is working... in ocaml 3.07, but not in ocaml 3.06. Good news
                          isn't it ?

                          By the way, camlp4 give you the possibility of defining a where clause
                          (it is one easily available example).

                          So you could write things like :

                          let top = Node [ "Entry", entry1 ]
                          where entry1 = empty ;;

                          which is translated by camlp4 into :

                          let top =
                          let entry1 = empty in
                          Node [ "Entry", entry1 ]


                          before been compiled by ocaml

                          [...]


                          --
                          Rémi Vanicat
                          remi.vanicat@...
                        Your message has been successfully submitted and would be delivered to recipients shortly.