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

syntax problem ?

Expand Messages
  • Radu Grigore
    Hi All, ... open Printf;; let bau () = let a = ref 0 in let f x = a := x in begin printf %d n !a; f 1 end;; bau ();; (* prints 0 *) bau ();; (* prints 0 *)
    Message 1 of 12 , Sep 29, 2004
    • 0 Attachment
      Hi All,

      I don't understand why these two code pieces behave differently:

      --- begin piece A ---
      open Printf;;

      let bau () =
      let a = ref 0 in
      let f x = a := x in
      begin
      printf "%d\n" !a;
      f 1
      end;;
      bau ();; (* prints 0 *)
      bau ();; (* prints 0 *)
      --- end piece A ---

      This code behaves as I expected. However, the following one is beyond
      my current comprehension :)

      --- begin piece B ---
      open Printf;;

      let bau =
      let a = ref 0 in
      let f x = a := x in
      function () ->
      begin
      printf "%d\n" !a;
      f 1
      end;;
      bau ();; (* prints 0 *)
      bau ();; (* prints 1 !!! Why? *)
      --- end piece B ---

      The same happens if instead of "function ()" you have a "real"
      pattern matching.

      regards,
      radu




      __________________________________
      Do you Yahoo!?
      New and Improved Yahoo! Mail - Send 10MB messages!
      http://promotions.yahoo.com/new_mail
    • Richard Jones
      ... In the above code, you create a fresh reference to 0 each time the function is called. So the let f x = a := x and f 1 have no effect - they can be
      Message 2 of 12 , Sep 29, 2004
      • 0 Attachment
        On Wed, Sep 29, 2004 at 09:04:40AM -0700, Radu Grigore wrote:
        > I don't understand why these two code pieces behave differently:
        >
        > --- begin piece A ---
        > open Printf;;
        >
        > let bau () =
        > let a = ref 0 in
        > let f x = a := x in
        > begin
        > printf "%d\n" !a;
        > f 1
        > end;;
        > bau ();; (* prints 0 *)
        > bau ();; (* prints 0 *)
        > --- end piece A ---

        In the above code, you create a fresh reference to 0 each time the
        function is called. So the 'let f x = a := x' and 'f 1' have no
        effect - they can be removed.

        The equivalent in C would be something like:

        bau ()
        {
        int a = 0;
        printf ("%d", a);
        a = 1;
        }

        > --- begin piece B ---
        > open Printf;;
        >
        > let bau =
        > let a = ref 0 in
        > let f x = a := x in
        > function () ->
        > begin
        > printf "%d\n" !a;
        > f 1
        > end;;
        > bau ();; (* prints 0 *)
        > bau ();; (* prints 1 !!! Why? *)
        > --- end piece B ---

        This is quite different. One reference to 0 is created when the
        program first starts up. It is named 'a'. After the function is
        called first time, the reference is updated to 1, so the second time
        the function is called, it prints 1.

        The equivalent in C would be:

        bau ()
        {
        static int a = 0;
        printf ("%d", a);
        a = 1;
        }

        Here's something clever:

        let add_error, get_errors =
        let errors = ref [] in
        let add_error msg = errors := msg :: !errors in
        let get_errors () = let r = List.rev !errors in errors := []; r in
        add_error, get_errors

        # add_error "hello";;
        - : unit = ()
        # add_error "goodbye";;
        - : unit = ()
        # get_errors ();;
        - : string list = ["hello"; "goodbye"]
        # add_error "another thing";;
        - : unit = ()
        # get_errors ();;
        - : string list = ["another thing"]

        Notice how the implementation of the two functions is hidden, and
        could be changed without affecting callers in any way. It's a sort of
        very lightweight abstract datatype.

        Rich.

        --
        Richard Jones. http://www.annexia.org/ http://www.j-london.com/
        Merjis Ltd. http://www.merjis.com/ - improving website return on investment
        Learning Objective CAML for C, C++, Perl and Java programmers:
        http://www.merjis.com/richj/computers/ocaml/tutorial/


        [Non-text portions of this message have been removed]
      • Brian Hurt
        ... This is because of when things get evaluated, most specifically, when the lines: let a = ref 0 in let f x = a := x in ... get evaluated. In the first
        Message 3 of 12 , Sep 29, 2004
        • 0 Attachment
          On Wed, 29 Sep 2004, Radu Grigore wrote:

          >
          > Hi All,
          >
          > I don't understand why these two code pieces behave differently:
          >
          > --- begin piece A ---
          > open Printf;;
          >
          > let bau () =
          > let a = ref 0 in
          > let f x = a := x in
          > begin
          > printf "%d\n" !a;
          > f 1
          > end;;
          > bau ();; (* prints 0 *)
          > bau ();; (* prints 0 *)
          > --- end piece A ---
          >
          > This code behaves as I expected. However, the following one is beyond
          > my current comprehension :)
          >
          > --- begin piece B ---
          > open Printf;;
          >
          > let bau =
          > let a = ref 0 in
          > let f x = a := x in
          > function () ->
          > begin
          > printf "%d\n" !a;
          > f 1
          > end;;
          > bau ();; (* prints 0 *)
          > bau ();; (* prints 1 !!! Why? *)
          > --- end piece B ---
          >

          This is because of when things get evaluated, most specifically, when the
          lines:
          let a = ref 0 in
          let f x = a := x in
          ...

          get evaluated. In the first case, they get re-evaluated every time you
          call the function bau. In the second case they only get called once- when
          the value of bau is calculated (to be a function). In other words, in the
          first case, every call to bau has a different a and a different f, in the
          second case all calls to bau share the same a and f.

          This is more easily demonstrated:

          # let foo1 = fun x y -> let _ = print_string "Got here!\n" in x + y;;
          val foo1 : int -> int -> int = <fun>
          # foo1;;
          - : int -> int -> int = <fun>
          # foo1 2 3 ;;
          Got here!
          - : int = 5
          # let foo2 = let _ = print_string "Got here!\n" in fun x y -> x + y;;
          Got here!
          val foo2 : int -> int -> int = <fun>
          # foo2;;
          - : int -> int -> int = <fun>
          # foo2 2 3;;
          - : int = 5
          # fun x y -> x + y;;
          - : int -> int -> int = <fun>
          #

          --
          "Usenet is like a herd of performing elephants with diarrhea -- massive,
          difficult to redirect, awe-inspiring, entertaining, and a source of
          mind-boggling amounts of excrement when you least expect it."
          - Gene Spafford
          Brian
        • Radu Grigore
          ... Let s see if I have understood. First, these two lines of code are equivalent: let a = ;; let a = fun - ;; Second, for this
          Message 4 of 12 , Sep 29, 2004
          • 0 Attachment
            --- Brian Hurt <bhurt@...> wrote:
            > This is because of when things get evaluated,

            Let's see if I have understood.
            First, these two lines of code are equivalent:
            let a <args> = <expr>;;
            let a = fun <args> -> <expr>;;

            Second, for this binding:
            let a = let u = <eu> in let v = <ev> in <args>
            -> let x = <ex> in let y = <ey> in <ea>;;

            there are two times when expressions get evaluated:
            1. definition time: <eu> and <ev>
            2. application of a: <ex>, <ey>, and <ea>

            Now, what about partial applications of a? Let's say we have:

            let a = let u = <eu> in fun x -> let v = <ev> in
            (fun y z -> let w = <ew> in <ea>);;

            In this case:
            1. at definition time <eu> gets evaluated
            2. when you apply a to the first argument <ev> gets evaluated
            3. if you apply it to two more, then <ew> and <ea> get evaluated.

            I guess that in this case if you apply a to two arguments <ew> will
            get evaluated but not <ea>. Is this correct? And, another question,
            if the paranthesis are dropped in the above definition do the
            semantics remain unchanged?

            regards,
            radu


            __________________________________________________
            Do You Yahoo!?
            Tired of spam? Yahoo! Mail has the best spam protection around
            http://mail.yahoo.com
          • Richard Jones
            ... So let s keep it simple. These two expressions are indeed equivalent: let a = ;; let a = fun - ;; BUT ... what you ve actually
            Message 5 of 12 , Sep 29, 2004
            • 0 Attachment
              On Wed, Sep 29, 2004 at 11:32:10AM -0700, Radu Grigore wrote:
              >
              > --- Brian Hurt <bhurt@...> wrote:
              > > This is because of when things get evaluated,
              >
              > Let's see if I have understood.
              > First, these two lines of code are equivalent:
              > let a <args> = <expr>;;
              > let a = fun <args> -> <expr>;;

              So let's keep it simple. These two expressions are indeed equivalent:

              let a <args> = <expr>;;
              let a = fun <args> -> <expr>;;

              BUT ... what you've actually got is:

              let a <args> = <expr>;;
              ^
              |
              something here

              vs:

              let a = fun <args> -> <expr>;;
              ^
              |
              something here

              and this is where the difference arises. Think about the simpler
              expression:

              let a = <expr>;;

              In this case <expr> is evaluated when the program starts up. (To be
              more precise, it's evaluated when the module containing 'a' is loaded,
              eg. using Dynlink).

              So, the expression:

              let a = fun <args> -> <expr>;;
              ^
              |
              something here

              the 'something here' is evaluated when the program starts up, just
              once. The 'something here' in your original example happens to be
              some code which creates a reference and a function 'f' which sets the
              reference.

              Is that clearer?

              Rich.

              --
              Richard Jones. http://www.annexia.org/ http://www.j-london.com/
              Merjis Ltd. http://www.merjis.com/ - improving website return on investment
              Perl4Caml lets you use any Perl library in your type-safe Objective
              CAML programs. http://www.merjis.com/developers/perl4caml/


              [Non-text portions of this message have been removed]
            • andrew cooke
              in the first case, bau is defined as a function that takes an empty tuple and does various things (creating a reference, printing, assigning values etc).
              Message 6 of 12 , Sep 29, 2004
              • 0 Attachment
                in the first case, bau is defined as a function that takes an empty tuple
                and does various things (creating a reference, printing, assigning values
                etc). those things are done when the function is called.

                in the second case, bau is assigned to the result of a series of commands.
                a is created and a function that is defined that references a. so a
                exists outside of the function (although you cannot access it apart from
                via that function, because there is no other reference available). when
                that function, which is bound to bau, is called, it modifies the value.

                the key point is that in the second case a is *outside* the function bound
                to bau. it has its own existence. in the first case, a is inside the
                function, so is created again each time the function is called.

                for more information, search for "closures" with google.

                andrew

                Radu Grigore said:
                >
                > Hi All,
                >
                > I don't understand why these two code pieces behave differently:
                >
                > --- begin piece A ---
                > open Printf;;
                >
                > let bau () =
                > let a = ref 0 in
                > let f x = a := x in
                > begin
                > printf "%d\n" !a;
                > f 1
                > end;;
                > bau ();; (* prints 0 *)
                > bau ();; (* prints 0 *)
                > --- end piece A ---
                >
                > This code behaves as I expected. However, the following one is beyond
                > my current comprehension :)
                >
                > --- begin piece B ---
                > open Printf;;
                >
                > let bau =
                > let a = ref 0 in
                > let f x = a := x in
                > function () ->
                > begin
                > printf "%d\n" !a;
                > f 1
                > end;;
                > bau ();; (* prints 0 *)
                > bau ();; (* prints 1 !!! Why? *)
                > --- end piece B ---
                >
                > The same happens if instead of "function ()" you have a "real"
                > pattern matching.
                >
                > regards,
                > radu
                >
                >
                >
                >
                > __________________________________
                > Do you Yahoo!?
                > New and Improved Yahoo! Mail - Send 10MB messages!
                > http://promotions.yahoo.com/new_mail
                >
                >
                >
                > Archives up to July 22, 2003 are also at
                > http://www.connettivo.net/cntprojects/ocaml_beginners/ocaml_beginners_archive_220703/
                > The archives of the very official ocaml list (the seniors' one) can be
                > found at http://caml.inria.fr
                > Attachments are banned and you're asked to be polite, avoid flames etc.
                > etc.p://caml.inria.fr
                > Attachments are banned and you're asked to be polite, avoid flames etc.
                > etc.
                > Yahoo! Groups Links
                >
                >
                >
                >
                >
                >
                >
                >


                --
                ` __ _ __ ___ ___| |_____ work web site: http://www.ctio.noao.edu/~andrew
                / _` / _/ _ \/ _ \ / / -_) personal web site: http://www.acooke.org/andrew
                \__,_\__\___/\___/_\_\___| list: http://www.acooke.org/andrew/compute.html
              • Brian Hurt
                ... Yes. ... Yes. u and v are semi-globals. In that all calls to a share the same variables, but no one else can see them. ... By jove, I think he s got it!
                Message 7 of 12 , Sep 29, 2004
                • 0 Attachment
                  On Wed, 29 Sep 2004, Radu Grigore wrote:

                  >
                  > --- Brian Hurt <bhurt@...> wrote:
                  > > This is because of when things get evaluated,
                  >
                  > Let's see if I have understood.
                  > First, these two lines of code are equivalent:
                  > let a <args> = <expr>;;
                  > let a = fun <args> -> <expr>;;

                  Yes.

                  >
                  > Second, for this binding:
                  > let a = let u = <eu> in let v = <ev> in <args>
                  > -> let x = <ex> in let y = <ey> in <ea>;;
                  >
                  > there are two times when expressions get evaluated:
                  > 1. definition time: <eu> and <ev>
                  > 2. application of a: <ex>, <ey>, and <ea>

                  Yes. u and v are semi-globals. In that all calls to a share the same
                  variables, but no one else can see them.

                  >
                  > Now, what about partial applications of a? Let's say we have:
                  >
                  > let a = let u = <eu> in fun x -> let v = <ev> in
                  > (fun y z -> let w = <ew> in <ea>);;
                  >
                  > In this case:
                  > 1. at definition time <eu> gets evaluated
                  > 2. when you apply a to the first argument <ev> gets evaluated
                  > 3. if you apply it to two more, then <ew> and <ea> get evaluated.

                  By jove, I think he's got it!

                  Yep. This is exactly how this works. And it's simple enough to
                  demonstrate:
                  # let f =
                  let _ = print_string "Point 1\n" in
                  fun x ->
                  let _ = print_string "Point 2\n" in
                  fun y ->
                  let _ = print_string "Point 3\n" in
                  x + y
                  ;;
                  Point 1
                  val f : int -> int -> int = <fun>
                  # f 1;;
                  Point 2
                  - : int -> int = <fun>
                  # let g = f 1;;
                  Point 2
                  val g : int -> int = <fun>
                  # g 2;;
                  Point 3
                  - : int = 3
                  # f 1 2;;
                  Point 2
                  Point 3
                  - : int = 3
                  #


                  > I guess that in this case if you apply a to two arguments <ew> will
                  > get evaluated but not <ea>. Is this correct? And, another question,
                  > if the paranthesis are dropped in the above definition do the
                  > semantics remain unchanged?

                  Yes. The semantic remain unchanged.

                  --
                  "Usenet is like a herd of performing elephants with diarrhea -- massive,
                  difficult to redirect, awe-inspiring, entertaining, and a source of
                  mind-boggling amounts of excrement when you least expect it."
                  - Gene Spafford
                  Brian
                • Radu Grigore
                  ... What I ve got is let f x = let a = ref b in which according to my first observation is equivalent to let f = fun x - let a = ref b in which
                  Message 8 of 12 , Sep 29, 2004
                  • 0 Attachment
                    --- Richard Jones <rich@...> wrote:

                    > On Wed, Sep 29, 2004 at 11:32:10AM -0700, Radu Grigore wrote:
                    > >
                    > > --- Brian Hurt <bhurt@...> wrote:
                    > > > This is because of when things get evaluated,
                    > >
                    > > Let's see if I have understood.
                    > > First, these two lines of code are equivalent:
                    > > let a <args> = <expr>;;
                    > > let a = fun <args> -> <expr>;;
                    >
                    > So let's keep it simple. These two expressions are indeed
                    > equivalent:
                    >
                    > let a <args> = <expr>;;
                    > let a = fun <args> -> <expr>;;
                    >
                    > BUT ... what you've actually got is:

                    What I've got is
                    let f x = let a = ref b in <expr>

                    which according to my first observation is equivalent to
                    let f = fun x -> let a = ref b in <expr>

                    which can be analysed according to my second observation.

                    regards,
                    radu




                    __________________________________
                    Do you Yahoo!?
                    New and Improved Yahoo! Mail - Send 10MB messages!
                    http://promotions.yahoo.com/new_mail
                  • Richard Jones
                    ... No, these two are not equivalent. Rich. -- Richard Jones. http://www.annexia.org/ http://www.j-london.com/ Merjis Ltd. http://www.merjis.com/ - improving
                    Message 9 of 12 , Sep 30, 2004
                    • 0 Attachment
                      On Wed, Sep 29, 2004 at 09:47:18PM -0700, Radu Grigore wrote:
                      > What I've got is
                      > let f x = let a = ref b in <expr>
                      >
                      > which according to my first observation is equivalent to
                      > let f = fun x -> let a = ref b in <expr>

                      No, these two are not equivalent.

                      Rich.

                      --
                      Richard Jones. http://www.annexia.org/ http://www.j-london.com/
                      Merjis Ltd. http://www.merjis.com/ - improving website return on investment
                      Learning Objective CAML for C, C++, Perl and Java programmers:
                      http://www.merjis.com/richj/computers/ocaml/tutorial/


                      [Non-text portions of this message have been removed]
                    • Frederic van der Plancke
                      ... You must have been thinking about something else, because I see no semantical difference here. Frédéric.
                      Message 10 of 12 , Sep 30, 2004
                      • 0 Attachment
                        Richard Jones wrote:
                        >
                        > On Wed, Sep 29, 2004 at 09:47:18PM -0700, Radu Grigore wrote:
                        > > What I've got is
                        > > let f x = let a = ref b in <expr>
                        > >
                        > > which according to my first observation is equivalent to
                        > > let f = fun x -> let a = ref b in <expr>
                        >
                        > No, these two are not equivalent.
                        >
                        > Rich.

                        You must have been thinking about something else,
                        because I see no semantical difference here.

                        Frédéric.
                      • Radu Grigore
                        ... [begin note] The function was something like (irrelevant parts omitted): let a = fun x - fun y z - let w = in [end note] Another equivalence to
                        Message 11 of 12 , Sep 30, 2004
                        • 0 Attachment
                          --- Brian Hurt <bhurt@...> wrote:
                          > By jove, I think he's got it!

                          :) Well, thanks again.

                          But I have made one error in my post:

                          > > I guess that in this case if you apply a to two arguments
                          > > <ew> will get evaluated but not <ea>.

                          [begin note]
                          The function was something like (irrelevant parts omitted):
                          let a = fun x -> fun y z -> let w = <ew> in <ea>
                          [end note]

                          Another equivalence to keep in mind:
                          fun x y z ->
                          fun x -> fun y -> fun z ->

                          It follows that a applied to two parameters does _not_ evaluate <ew>.

                          regards,
                          radu





                          __________________________________
                          Do you Yahoo!?
                          New and Improved Yahoo! Mail - 100MB free storage!
                          http://promotions.yahoo.com/new_mail
                        • Richard Jones
                          ... Sorry yes, I was mistaken. What I meant was the following aren t equivalent, which is related (I think) to the original topic: let f x = let a = ref b in
                          Message 12 of 12 , Sep 30, 2004
                          • 0 Attachment
                            On Thu, Sep 30, 2004 at 08:20:38AM +0000, Frederic van der Plancke wrote:
                            >
                            >
                            > Richard Jones wrote:
                            > >
                            > > On Wed, Sep 29, 2004 at 09:47:18PM -0700, Radu Grigore wrote:
                            > > > What I've got is
                            > > > let f x = let a = ref b in <expr>
                            > > >
                            > > > which according to my first observation is equivalent to
                            > > > let f = fun x -> let a = ref b in <expr>
                            > >
                            > > No, these two are not equivalent.
                            > >
                            > > Rich.
                            >
                            > You must have been thinking about something else,
                            > because I see no semantical difference here.

                            Sorry yes, I was mistaken. What I meant was the following aren't
                            equivalent, which is related (I think) to the original topic:

                            let f x = let a = ref b in <expr>
                            let f = let a = ref b in fun x -> <expr>

                            Rich.

                            --
                            Richard Jones. http://www.annexia.org/ http://www.j-london.com/
                            Merjis Ltd. http://www.merjis.com/ - improving website return on investment
                            Learning Objective CAML for C, C++, Perl and Java programmers:
                            http://www.merjis.com/richj/computers/ocaml/tutorial/


                            [Non-text portions of this message have been removed]
                          Your message has been successfully submitted and would be delivered to recipients shortly.