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

How Do I Know When a Function Begins and Ends?

Expand Messages
  • John Smith
    Hi: Coming from a C background, I could always tell where a function began and ended by looking at the brackets (it is also made easier by the fact that C does
    Message 1 of 19 , Dec 25, 2008
      Hi:

      Coming from a C background, I could always tell where a function began and
      ended by looking at the brackets (it is also made easier by the fact that C
      does not officially support nested functions). However, I'm running into
      problems doing this for OCaml. If I understand correctly, both local named
      expressions (those within functions) and nested functions end with the
      keyword "in". The difference between the two is that the former has no
      parameters, while the latter does. However, global named expressions and
      non-nested functions do not end with a keyword. So how do I know when they
      end (I mean when I'm reading the source code)?

      Two examples (they become very problematic especially when indentation is
      missing):

      1) let foo argF1 =
      ......
      let bar argB1 =
      ......

      How do I know whether bar is a nested function or not, if I only read up to
      the line "let bar argB1"? Or must I read the whole source code before I can
      determine this?

      2) let foo =
      ......
      let bar argB1 =
      .......

      How do I know whether bar is part of the definition of foo? Would the
      answer to my question change if bar was a named expression (i.e., "let bar =
      ").

      Cheers,
      legit


      [Non-text portions of this message have been removed]
    • River Cheng
      Hi, First, I think the top level expression is ended with ;; , except when omitting ;; will not introduce ambiguity. The ;; before let , open , type ,
      Message 2 of 19 , Dec 25, 2008
        Hi,

        First, I think the top level expression is ended with ";;", except when
        omitting ";;"
        will not introduce ambiguity. The ";;" before 'let' , 'open', 'type', or the
        end of file can be omitted.

        For your question, I think whether the second 'let' is inside the first
        function is not
        hard to decide. If the expression before the second 'let' is a complete
        expression already,
        then the second 'let' is another expression. Otherwise, it is part of the
        first expression.

        For example,
        let foo x =
        let bar y = ... in
        ...

        The part before second 'let' is not a complete expression, so it is inside
        the first function.

        let foo x =
        if ... then ...
        else
        let bar y = ... in ...

        The second 'let' is also a part of the first expression.

        let foo x = x * x

        let bar y = ...

        In this case since the first expression is already complete, so the second
        'let' begins a new expression.

        In properly formatted code, there is not such kind of question since we can
        decide the
        end of a function by correct indention.

        cheers,
        Cheng Wei




        On Fri, Dec 26, 2008 at 12:59 PM, John Smith <legit.anon@...> wrote:

        > Hi:
        >
        > Coming from a C background, I could always tell where a function began and
        > ended by looking at the brackets (it is also made easier by the fact that C
        > does not officially support nested functions). However, I'm running into
        > problems doing this for OCaml. If I understand correctly, both local named
        > expressions (those within functions) and nested functions end with the
        > keyword "in". The difference between the two is that the former has no
        > parameters, while the latter does. However, global named expressions and
        > non-nested functions do not end with a keyword. So how do I know when they
        > end (I mean when I'm reading the source code)?
        >
        > Two examples (they become very problematic especially when indentation is
        > missing):
        >
        > 1) let foo argF1 =
        > ......
        > let bar argB1 =
        > ......
        >
        > How do I know whether bar is a nested function or not, if I only read up to
        > the line "let bar argB1"? Or must I read the whole source code before I can
        > determine this?
        >
        > 2) let foo =
        > ......
        > let bar argB1 =
        > .......
        >
        > How do I know whether bar is part of the definition of foo? Would the
        > answer to my question change if bar was a named expression (i.e., "let bar
        > =
        > ").
        >
        > Cheers,
        > legit
        >
        > [Non-text portions of this message have been removed]
        >
        >
        >


        [Non-text portions of this message have been removed]
      • Jon Harrop
        ... Not quite. If there are parameters then you know it is a function. If there are no parameters then it could still be a function, e.g. if its body is a
        Message 3 of 19 , Dec 26, 2008
          On Friday 26 December 2008 04:59:50 John Smith wrote:
          > Hi:
          >
          > Coming from a C background, I could always tell where a function began and
          > ended by looking at the brackets (it is also made easier by the fact that C
          > does not officially support nested functions). However, I'm running into
          > problems doing this for OCaml. If I understand correctly, both local named
          > expressions (those within functions) and nested functions end with the
          > keyword "in". The difference between the two is that the former has no
          > parameters, while the latter does.

          Not quite. If there are parameters then you know it is a function. If there
          are no parameters then it could still be a function, e.g. if its body is a
          partial application of another function:

          let f() =
          let print_int = printf "%d\n%!" in
          ...

          Here, the nested "print_int" is a function.

          > However, global named expressions and
          > non-nested functions do not end with a keyword. So how do I know when they
          > end (I mean when I'm reading the source code)?
          >
          > Two examples (they become very problematic especially when indentation is
          > missing):
          >
          > 1) let foo argF1 =
          > ......
          > let bar argB1 =
          > ......
          >
          > How do I know whether bar is a nested function or not, if I only read up to
          > the line "let bar argB1"? Or must I read the whole source code before I
          > can determine this?
          >
          > 2) let foo =
          > ......
          > let bar argB1 =
          > .......
          >
          > How do I know whether bar is part of the definition of foo? Would the
          > answer to my question change if bar was a named expression (i.e., "let bar
          > = ").

          Use automatic indentation and it becomes obvious (the second case cannot even
          occur). Also, top-level definitions are usually separated by a blank line.

          --
          Dr Jon Harrop, Flying Frog Consultancy Ltd.
          http://www.ffconsultancy.com/?e
        • Dario Teixeira
          Hi, ... Personally, I ve never come across *any* Ocaml source code that made this ambiguous. The programmer has to be a masochist to indent their own source
          Message 4 of 19 , Dec 26, 2008
            Hi,

            > Coming from a C background, I could always tell where a function began
            > and ended by looking at the brackets (it is also made easier by the fact
            > that C does not officially support nested functions). However, I'm
            > running into problems doing this for OCaml.

            Personally, I've never come across *any* Ocaml source code that made
            this ambiguous. The programmer has to be a masochist to indent their
            own source code in a manner that induces that sort of confusion. But
            anyway, there's another quick solution to your problem: let the compiler
            do the work for you! Invoke "ocamlc -i file.ml", which will printout
            the inferred signature for the module. There you will see all the
            top-level functions as the compiler sees them.

            Hope that helps!
            Cheers,
            Dario Teixeira
          • Christopher Conway
            ... began and ... that C ... into ... local named ... expressions and ... when they ... indentation is ... read up to ... before I can ... let bar = ... let
            Message 5 of 19 , Dec 26, 2008
              --- In ocaml_beginners@yahoogroups.com, "John Smith" <legit.anon@...>
              wrote:
              >
              > Hi:
              >
              > Coming from a C background, I could always tell where a function
              began and
              > ended by looking at the brackets (it is also made easier by the fact
              that C
              > does not officially support nested functions). However, I'm running
              into
              > problems doing this for OCaml. If I understand correctly, both
              local named
              > expressions (those within functions) and nested functions end with the
              > keyword "in". The difference between the two is that the former has no
              > parameters, while the latter does. However, global named
              expressions and
              > non-nested functions do not end with a keyword. So how do I know
              when they
              > end (I mean when I'm reading the source code)?
              >
              > Two examples (they become very problematic especially when
              indentation is
              > missing):
              >
              > 1) let foo argF1 =
              > ......
              > let bar argB1 =
              > ......
              >
              > How do I know whether bar is a nested function or not, if I only
              read up to
              > the line "let bar argB1"? Or must I read the whole source code
              before I can
              > determine this?
              >
              > 2) let foo =
              > ......
              > let bar argB1 =
              > .......
              >
              > How do I know whether bar is part of the definition of foo? Would the
              > answer to my question change if bar was a named expression (i.e.,
              "let bar =
              > ").
              >
              > Cheers,
              > legit

              "let bar ..." can only be a nested definition if it is immediately
              preceded by an "in" or a semicolon. I.e.,

              let foo argF1 =
              ... (* LONG EXPR *) ... in
              let bar argB1 =
              ... (* foo is bound here *) ...

              or

              let foo argF1 =
              ... (* LONG EXPR *) ... ;
              let bar argB1 =
              ... (* bar is part of the definition of foo *) ...

              In practice, you should try to use a programming environment that can
              figure these things out for you. For example, in Emacs you will "know"
              that "let bar ..." is a top-level expression when you hit TAB and it
              doesn't move from the left margin ;-).

              If your functions get really long, with lots of nesting, you can make
              it easier to spy boundaries using "begin ... end":

              let foo argF1 =
              begin
              ... (* LONG EXPR *) ...
              end

              let bar argB1 =
              begin
              ... (* bar is a top-level definition *) ...
              end

              Probably, if your functions are long and nested enough to start
              confusing you, you should try to break them down into smaller,
              un-nested pieces.

              Regards,
              Chris
            • Richard Jones
              ... Me too ... Perhaps http://ocaml-tutorial.org/ can help. ... That s correct. ... This is one of those yes ... and no answers :-) ... Here is my
              Message 6 of 19 , Dec 26, 2008
                On Thu, Dec 25, 2008 at 11:59:50PM -0500, John Smith wrote:
                > Hi:
                >
                > Coming from a C background,

                Me too ... Perhaps http://ocaml-tutorial.org/ can help.

                > I could always tell where a function began and
                > ended by looking at the brackets (it is also made easier by the fact that C
                > does not officially support nested functions). However, I'm running into
                > problems doing this for OCaml. If I understand correctly, both local named
                > expressions (those within functions) and nested functions end with the
                > keyword "in".

                That's correct.

                > The difference between the two is that the former has no
                > parameters, while the latter does.

                This is one of those "yes ... and no" answers :-)

                > However, global named expressions and
                > non-nested functions do not end with a keyword. So how do I know when they
                > end (I mean when I'm reading the source code)?

                Here is my convention, which I use in virtually all code that I have
                written. I use:


                let f .. =
                in

                for functions, and:

                let v = .. in

                for values (ie. anything that's not a function). In other words, my
                convention is that I put 'in' on its own line if the preceeding is a
                function definition. But if the preceeding is a non-function then the
                'in' will be on the same line after some other stuff.

                In a real example (from http://merjis.com/developers/csv/):

                let state = ref StartField in (* Current state. *)
                let end_of_field () =
                let field_list = List.rev !field in
                let field_len = List.length field_list in
                let field_str = String.create field_len in
                let rec loop i = function
                [] -> ()
                | x :: xs ->
                field_str.[i] <- x;
                loop (i+1) xs
                in
                loop 0 field_list;
                row := field_str :: !row;
                field := [];
                state := StartField
                in

                So 'state', 'field_list', 'field_len' etc are non-functions. Whereas
                'end_of_field' and 'loop' are functions (look at the two 'in's on a
                line of their own).

                The great feature of functional languages is that you can have
                functions as any first-class values. For example, here is how to do
                private state within functions (like C's static variables in a
                function):

                let () =
                let unique =
                let i = ref 0 in
                fun () ->
                incr i; !i
                in
                printf "getting unique number -> %d\n" (unique ());
                printf "getting unique number -> %d\n" (unique ());
                printf "getting unique number -> %d\n" (unique ())

                If you compile the above, it will print:

                getting unique number -> 1
                getting unique number -> 2
                getting unique number -> 3

                Notice that 'unique' is a function. 'i' is its static state.

                Rich.

                --
                Richard Jones
                Red Hat
              • John Smith
                Hi: First off, thanks for all of your timely replies, especially during the holiday season :) River: Yeah, it is easy to see in those examples. I was
                Message 7 of 19 , Dec 26, 2008
                  Hi:

                  First off, thanks for all of your timely replies, especially during the
                  holiday season :)

                  River:
                  Yeah, it is easy to see in those examples. I was referring to those
                  examples where it is not so obvious.

                  Jon:
                  You said that the following is not possible:

                  > 2) let foo =
                  > ......
                  > let bar argB1 =
                  > .......

                  Could you please elaborate? I thought I could have any expression in the
                  body of foo, including a function.

                  Dario:
                  Cool, I didn't know you could do that with the compiler. Do you mean it
                  outputs the signature to standard out, or to a file (an *.mli file
                  perhaps)? In OCaml, can I simply compile one file if it is part of a bigger
                  project (e.g., in C, you can't do this, because you have to tell gcc to
                  compile both node.c and main_program.c)? However, I would prefer to be able
                  to see these things without compiling (I'll do it as a last resort).

                  Christopher:
                  Thanks! I think that piece of information was exactly what I was looking
                  for.

                  Richard:

                  > Me too ... Perhaps http://ocaml-tutorial.org/ can help.

                  Yep, that's been my main site for learning OCaml.

                  > The difference between the two is that the former has no
                  > parameters, while the latter does.
                  >
                  >>This is one of those "yes ... and no" answers :-)

                  Oh, I only meant syntatically.

                  > The great feature of functional languages is that you can have functions
                  as any first-class values. For example, here is how to do
                  > private state within functions (like C's static variables in a function):
                  >
                  > let () =
                  > let unique =
                  > let i = ref 0 in
                  > fun () ->
                  > incr i; !i
                  > in
                  > printf "getting unique number -> %d\n" (unique ());

                  Is the first line correct, since it appears to be defining a function with a
                  "unit" parameter that has no name? Are the printf's inside this
                  function-with-no-name? As well, how can unique be a function if it appears
                  to have no parameters?


                  Finally, most have you have mentioned that the indentation should make it
                  clear. I perhaps should have mentioned that this problem arose when I was
                  reading other people's code, and not writing my own. I'm sure most of you
                  have learned that some programmers have bad indentation practices or make
                  indentation mistakes, and even the best indentation sometimes doesn't
                  survive the journey from one editor to another. This is why I prefer to
                  have some rules which I can apply independent of the indentation. Of
                  course, I will take your style suggestions when it comes time for me to
                  write OCaml code.

                  Thanks, and looking forward to your answers,
                  legit


                  [Non-text portions of this message have been removed]
                • Oliver Bandel
                  ... [...] But C provides labels and goto and setjmp/longjmp, which are ways to make code very confusing. So, C is not better, it s just better, because you
                  Message 8 of 19 , Dec 26, 2008
                    Zitat von John Smith <legit.anon@...>:

                    > Hi:
                    >
                    > Coming from a C background, I could always tell where a function
                    > began and
                    > ended by looking at the brackets (it is also made easier by the fact
                    > that C
                    > does not officially support nested functions).
                    [...]

                    But C provides labels and goto
                    and setjmp/longjmp, which are
                    ways to make code very confusing.

                    So, C is not better, it's just better,
                    because you seem not to have used the
                    confusing possibilities of C.


                    Ciao,
                    Oliver
                  • Jon Harrop
                    ... No, I said that automatic indentation makes this impossible: 2) let foo = ...... let bar argB1 = ....... Specifically, because it is not properly indented.
                    Message 9 of 19 , Dec 27, 2008
                      On Friday 26 December 2008 22:54:39 John Smith wrote:
                      > Jon:
                      >
                      > You said that the following is not possible:
                      > > 2) let foo =
                      > > ......
                      > > let bar argB1 =
                      > > .......
                      >
                      > Could you please elaborate? I thought I could have any expression in the
                      > body of foo, including a function.

                      No, I said that automatic indentation makes this impossible:

                      2) let foo =
                      ......
                      let bar argB1 =
                      .......

                      Specifically, because it is not properly indented.

                      > > private state within functions (like C's static variables in a function):
                      > >
                      > > let () =
                      > > let unique =
                      > > let i = ref 0 in
                      > > fun () ->
                      > > incr i; !i
                      > > in
                      > > printf "getting unique number -> %d\n" (unique ());
                      >
                      > Is the first line correct, since it appears to be defining a function with
                      > a "unit" parameter that has no name?

                      The code is correct: it defines a nameless value. Specifically, the "let"
                      construct binds the result of evaluating an expression to a pattern in the
                      context of "rest":

                      let <pat> = <expr> in <rest>

                      In the case of a top-level definition, there is no "in":

                      let <pat> = <expr>

                      <rest>

                      > Are the printf's inside this
                      > function-with-no-name? As well, how can unique be a function if it appears
                      > to have no parameters?

                      I already explained that in my last post.

                      > Finally, most have you have mentioned that the indentation should make it
                      > clear. I perhaps should have mentioned that this problem arose when I was
                      > reading other people's code, and not writing my own. I'm sure most of you
                      > have learned that some programmers have bad indentation practices or make
                      > indentation mistakes, and even the best indentation sometimes doesn't
                      > survive the journey from one editor to another. This is why I prefer to
                      > have some rules which I can apply independent of the indentation. Of
                      > course, I will take your style suggestions when it comes time for me to
                      > write OCaml code.

                      Use automatic indentation.

                      --
                      Dr Jon Harrop, Flying Frog Consultancy Ltd.
                      http://www.ffconsultancy.com/?e
                    • Richard Jones
                      ... Yes, this program is correct. (You also need open Printf at the top, but with that it will compile and run). let () = ... is a common way of running
                      Message 10 of 19 , Dec 27, 2008
                        On Fri, Dec 26, 2008 at 05:54:39PM -0500, John Smith wrote:
                        > Richard:
                        > > let () =
                        > > let unique =
                        > > let i = ref 0 in
                        > > fun () ->
                        > > incr i; !i
                        > > in
                        > > printf "getting unique number -> %d\n" (unique ());
                        >
                        > Is the first line correct, since it appears to be defining a function with a
                        > "unit" parameter that has no name?

                        Yes, this program is correct. (You also need 'open Printf' at the
                        top, but with that it will compile and run).

                        let () =
                        ...

                        is a common way of running some code ('...') without needing to worry
                        about double-semicolons.

                        This isn't a function, by the way, but a pattern match which matches
                        the code with the value '()'. As long as the final printf returns
                        unit (which printf always does), then the pattern match succeeds. If
                        not, you will get a compile-time error.

                        > Are the printf's inside this function-with-no-name?

                        They're inside the let () = ..., yes.

                        > As well, how can unique be a function if it appears
                        > to have no parameters?

                        That was the point of the example! The following are equivalent.

                        let f () =
                        printf "hello\n" ;;

                        let f =
                        fun () ->
                        printf "hello\n" ;;

                        Both define a function called 'f' which takes a single unit parameter.

                        The second form allows you to stuff some extra code before the
                        fun () -> ... part, which can include static variables, or indeed any
                        code that needs to run once when the function is first defined.

                        The compiler might generate different, slightly less efficient code
                        for the second variation however.

                        Rich.

                        --
                        Richard Jones
                        Red Hat
                      • Dario Teixeira
                        Hi, ... It outputs to stdout (just try it!). This feature is often used as a starting point to define the .mli file: (note the redirection) ocamlc -i
                        Message 11 of 19 , Dec 27, 2008
                          Hi,

                          > Dario:
                          > Cool, I didn't know you could do that with the compiler. Do you mean it
                          > outputs the signature to standard out, or to a file (an *.mli file perhaps)?

                          It outputs to stdout (just try it!). This feature is often used as a
                          starting point to define the .mli file: (note the redirection)

                          ocamlc -i module.ml > module.mli

                          And then you open module.mli and remove the stuff you want to hide
                          from the module's signature.

                          Hope that helps,
                          Dario
                        • John Smith
                          Hi: My apologies Jon, I missed the part in your first post where you explained how named expressions could also be functions. Ok, a lot of information has
                          Message 12 of 19 , Dec 27, 2008
                            Hi:

                            My apologies Jon, I missed the part in your first post where you explained
                            how named expressions could also be functions. Ok, a lot of information has
                            been provided in the last few posts (and from other threads). Let me try to
                            combine it all (please point out any mistakes in my understanding):


                            > Jon:
                            > The code is correct: it defines a nameless value. Specifically, the "let"
                            construct binds the result of evaluating an expression to a pattern in the
                            context of "rest":
                            >
                            > let <pat> = <expr> in <rest>
                            >
                            > In the case of a top-level definition, there is no "in":
                            >
                            > let <pat> = <expr>
                            > <rest>

                            As my program is being executed, whenever a "let" construct is encountered,
                            <expr> is immediately evaluated. In the case of named expressions that
                            don't contain the partial application of a function, <expr> is fully
                            evaluated, and its result is bounded to <pat>. I use "fully evaluated"
                            because <expr> does not depend on inputs, and thus the result of <expr> is
                            known at this time. In the event that the named expression contains the
                            partial application of a function, the "result" is the function, and is
                            again bound to <pat>. It is not possible to "fully evaluate" <expr>, since
                            the function requires inputs. A few questions:

                            1) Suppose I had the following code:

                            let my_func =
                            let i = ref 0 in
                            fun () -> incr i; !i
                            let p = ref 0 in
                            incr p;

                            What is the result that gets binded to my_func? Is space allocated for
                            p, and is p incremented? Basically, I want to know if the partial
                            application of the anonymous function "stalls" the evaluation of expressions
                            that follow it.

                            2) It appears to me that a named local expression is just a special case of
                            a function (i.e., a function without parameters). Is this correct?

                            3) Why does OCaml not evaluate the body of a function when the function is
                            defined (I'm not saying this doesn't make sense, I'm just wondering why,
                            when it will immediately evaluate the body of a named expression)? Does it
                            just "see" that a function has parameters, and refuse to execute the body,
                            even if the first few statements of the body do not depend on the
                            parameters? Or is it a rule that functions are not evaluated immediately,
                            and only when called?


                            -----------------------------------------------------------------------------------------------------

                            Now, <pat> presumably contains the name of the pattern, in addition to the
                            parameter patterns. So calling a function or using a named expression can
                            also be thought of as finding the pattern that has the same name, trying to
                            match the arguments with the parameters (and if successful, bind the value
                            of the arguments to the parameters), and then evaluating <expr> afterwards.
                            The binding and matching part is easy for named expressions, because they
                            don't have any parameters. So is the following code:

                            let () =
                            ........
                            ........

                            defining a nameless (a.k.a. anonymous) function that has a unit parameter,
                            or is it defining a nameless named expression that must evaluate to "()"?
                            If it is the latter (I'm not really doubting you Jon, just trying to provide
                            context for my next questions), then:

                            1) Is there any other way to define a nameless function besides the "fun"
                            and "function" constructs?
                            2) If I defined the following named expression:

                            let [some_constant] =
                            [some_expr]

                            Does that mean some_expr must evaluate to some_constant? Does it also
                            mean that I have no way of referring to this named expression later on in
                            the code?
                            3) If I defined the following named expression:

                            let (3, m) =
                            [some_expr]

                            Is this allowed? If so, does that mean some_expr must evaluate to a
                            tuple with the first element being 3? Will m be bound to the second element
                            of the tuple? If so, can I use m later on in my code, subject to scope
                            rules? If not, what happens?

                            Thanks in advance for your help,
                            legit


                            [Non-text portions of this message have been removed]
                          • Lukasz Stafiniak
                            I ve read just this last message of the thread, so bare with me... ... No, it is not the case when the let construct defines a function: let f x =
                            Message 13 of 19 , Dec 28, 2008
                              I've read just this last message of the thread, so bare with me...

                              On Sun, Dec 28, 2008 at 5:30 AM, John Smith <legit.anon@...> wrote:
                              >
                              > As my program is being executed, whenever a "let" construct is encountered,
                              > <expr> is immediately evaluated.

                              No, it is not the case when the "let" construct defines a function:

                              let f x = <expr>

                              [generally: "let <fun_name> <pat_1> ... <pat_n> = <expr>"]

                              This syntax is a shortcut for

                              let f = function x -> <expr>

                              [generally: "let f = function <pat_1> -> ... -> function <pat_n> -> <expr>"]

                              <expr> inside "function <pat> -> <expr>" is not evaluated at all, never! ;-)
                              This is not because we don't know how to compute the <expr>, but
                              because we want it to be computed when the function is called (think
                              of procedures in imperative languages; OCaml is "impure").

                              > In the case of named expressions that
                              > don't contain the partial application of a function,

                              and don't contain the "function" or "fun" keywords, or the implicit
                              "function" syntax described above,

                              > <expr> is fully
                              > evaluated, and its result is bounded to <pat>.

                              The result is matched against <pat>, and the corresponding values are
                              bound to variables in <pat>.

                              > I use "fully evaluated"
                              > because <expr> does not depend on inputs, and thus the result of <expr> is
                              > known at this time.

                              The thinking here is wrong as I explained above. You are thinking of
                              something sometimes called "symbolic evaluation" or "partial
                              evaluation".

                              > In the event that the named expression contains the
                              > partial application of a function, the "result" is the function, and is
                              > again bound to <pat>. It is not possible to "fully evaluate" <expr>, since
                              > the function requires inputs. A few questions:
                              >
                              > 1) Suppose I had the following code:
                              >
                              > let my_func =
                              > let i = ref 0 in
                              > fun () -> incr i; !i
                              > let p = ref 0 in
                              > incr p;
                              >
                              > What is the result that gets binded to my_func? Is space allocated for
                              > p, and is p incremented? Basically, I want to know if the partial
                              > application of the anonymous function "stalls" the evaluation of expressions
                              > that follow it.

                              Yes, it "stalls" after allocating the space for i and before
                              incrementing i, exactly at the point of "fun ()"; besides, your
                              indentation is misleading, the code reads

                              > let my_func =
                              > let i = ref 0 in
                              > fun () -> incr i; !i
                              >
                              > let p = ref 0 in
                              > incr p;

                              >
                              > 2) It appears to me that a named local expression is just a special case of
                              > a function (i.e., a function without parameters). Is this correct?

                              No, this is wrong, and I don't know what you've been thinking of ;-)

                              >
                              > 3) Why does OCaml not evaluate the body of a function when the function is
                              > defined (I'm not saying this doesn't make sense, I'm just wondering why,
                              > when it will immediately evaluate the body of a named expression)?

                              Because this is how the things go in "normal" programming languages.

                              [...]
                              >
                              > ----------------------------------------------------------
                              >
                              > Now, <pat> presumably contains the name of the pattern, in addition to the
                              > parameter patterns.

                              There is no such thing as "the name of the pattern" (patterns are not
                              "first-class" in OCaml). There are "alias patterns": "<pat> as x"
                              means to match a value against <pat> and additionally to bind the
                              value to x.

                              > So calling a function or using a named expression can
                              > also be thought of as finding the pattern that has the same name,

                              [this language is not correct, and confusing]

                              > trying to
                              > match the arguments with the parameters (and if successful, bind the value
                              > of the arguments to the parameters), and then evaluating <expr> afterwards.

                              You are right with "trying, and if successful, bind", but you are
                              wrong later: evaluating <expr> *before*, so that there is a value that
                              can be matched against a pattern.

                              > The binding and matching part is easy for named expressions, because they

                              Your use of "named expression" is confusing; better term is "named
                              value" -- but functions are also values! They are "evaluated into
                              closures", function application (calling a function) is another
                              expression which is evaluated taking into consideration the body of
                              the function (actually, the closure).

                              > don't have any parameters. So is the following code:
                              >
                              > let () =
                              > ........
                              > ........
                              >
                              > defining a nameless (a.k.a. anonymous) function that has a unit parameter,
                              > or is it defining a nameless named expression that must evaluate to "()"?

                              "nameless named expression" lol ;-)
                              It is defining an expression that will evaluate (immediately at this
                              point) to "()" (as there is no other value of the unit type).

                              > If it is the latter (I'm not really doubting you Jon, just trying to provide
                              > context for my next questions), then:
                              >
                              > 1) Is there any other way to define a nameless function besides the "fun"
                              > and "function" constructs?

                              The other way is by partial application. The partial application can
                              also "increase the number of arguments" a function expects!

                              > 2) If I defined the following named expression:
                              >
                              > let [some_constant] =
                              > [some_expr]
                              >
                              > Does that mean some_expr must evaluate to some_constant?

                              Yes, if it doesn't, this raises an exception.

                              > Does it also
                              > mean that I have no way of referring to this named expression later on in
                              > the code?

                              There is no named expression there. Really.

                              > 3) If I defined the following named expression:
                              >
                              > let (3, m) =
                              > [some_expr]
                              >
                              > Is this allowed? If so, does that mean some_expr must evaluate to a
                              > tuple with the first element being 3? Will m be bound to the second element
                              > of the tuple? If so, can I use m later on in my code, subject to scope
                              > rules? If not, what happens?

                              Yes, yes, yes and yes.

                              >
                              > Thanks in advance for your help,
                              > legit
                              >
                            • Richard Jones
                              ... A good thing to do at this point would be to install a decent editor with a good OCaml mode. I would recommend emacs + tuareg mode.
                              Message 14 of 19 , Dec 28, 2008
                                On Sat, Dec 27, 2008 at 11:30:17PM -0500, John Smith wrote:
                                > 1) Suppose I had the following code:
                                >
                                > let my_func =
                                > let i = ref 0 in
                                > fun () -> incr i; !i
                                > let p = ref 0 in
                                > incr p;

                                A good thing to do at this point would be to install a decent editor
                                with a good OCaml mode. I would recommend emacs + tuareg mode.

                                http://www-rocq.inria.fr/~acohen/tuareg/

                                The editor will indent the above code properly to reveal its structure
                                (after correcting a syntax error):

                                let my_func =
                                let i = ref 0 in
                                fun () ->
                                incr i; !i

                                let p = ref 0 ;;
                                incr p

                                > What is the result that gets binded to my_func?

                                As you can see from the properly formatted code, my_func is bound to
                                the fun () -> ... expression.

                                > Is space allocated for p, and is p incremented?

                                Yes & yes. However this is essentially "dead code". It doesn't do
                                anything visible, unless there is some later part of the program which
                                is using 'p' which you haven't shown us. In any case it is equivalent
                                to writing this:

                                let p = ref 1

                                > Basically, I want to know if the partial application of the
                                > anonymous function "stalls" the evaluation of expressions that
                                > follow it.

                                I'm not really sure what you mean by this. The code above defines a
                                function called 'my_func' and a reference called 'p'. You can see
                                this if you use ocamlc -i:

                                $ ocamlc -i test1.ml
                                val my_func : unit -> int
                                val p : int ref

                                > 2) It appears to me that a named local expression is just a special case of
                                > a function (i.e., a function without parameters). Is this correct?

                                Not exactly.

                                > 3) Why does OCaml not evaluate the body of a function when the function is
                                > defined

                                It just wouldn't make any sense to do this. The whole point of a
                                function is that it isn't evaluated until you call it.

                                However functions (in functional languages like OCaml, but _not_ in C)
                                can capture variables from the surrounding environment. You might
                                want to read up about closures:

                                https://secure.wikimedia.org/wikipedia/en/wiki/Closure_(computer_science)

                                > let () =
                                > ........
                                > ........
                                >
                                > defining a nameless (a.k.a. anonymous) function that has a unit parameter,
                                > or is it defining a nameless named expression that must evaluate to "()"?

                                This is a pattern-matching expression. It matches the code ('.....')
                                with the pattern '()'. Since the unit type is very special in that
                                there is only one possible value of the unit type, this either always
                                matches or will fail at compile time (because the types are
                                incompatible). Therefore this is just a safe way to run code without
                                needing to worry about the "top" let or double semi-colon rules.

                                See also:
                                http://caml.inria.fr/pub/ml-archives/caml-list/2004/09/4f6fa6e1512e47c73742acd74198d6e3.en.html

                                > 1) Is there any other way to define a nameless function besides the "fun"
                                > and "function" constructs?

                                Not in normal OCaml code, no.

                                > 2) If I defined the following named expression:
                                >
                                > let [some_constant] =
                                > [some_expr]
                                >
                                > Does that mean some_expr must evaluate to some_constant? Does it also
                                > mean that I have no way of referring to this named expression later on in
                                > the code?

                                Try it:

                                # let 1 =
                                2 ;;
                                Warning P: this pattern-matching is not exhaustive.
                                Here is an example of a value that is not matched:
                                0
                                Exception: Match_failure ("", 1, 4).

                                This tells you three things: (1) The types are compatible (ie. the
                                code compiled OK). (2) The compiler spotted that your pattern ('1')
                                doesn't exhaustively cover all the cases. (3) When the code ran, you
                                hit an example of a case which isn't covered by your pattern, which
                                caused a runtime exception.

                                Note that case (2) can never happen if the pattern is '()', because
                                there is only one value of the unit type, so pattern matching is
                                always exhaustive.

                                Try some other variations like:

                                let 1 = 1 ;;
                                let 1 = "foo" ;;

                                and see what compile-time and/or run-time warnings/errors you get.

                                > 3) If I defined the following named expression:
                                >
                                > let (3, m) =
                                > [some_expr]
                                >
                                > Is this allowed?

                                Yes, and it binds 'm' for use later on.

                                However, it's not good code, because it will produce a compile-time
                                warning, because the pattern '3' is not exhaustive.

                                A better way to write this is:

                                let m =
                                match [some_expr] with
                                | (3, m) -> m
                                | (i, _) ->
                                failwith (sprintf "expected 3 but got %d\n" i)

                                If you have the OCaml toplevel you can just try this stuff, which is
                                probably easier than posting here.

                                Rich.

                                --
                                Richard Jones
                                Red Hat
                              • John Smith
                                Hi: Lukasz (and Richard made some comments related to this as well) ... Haha, I wasn t trying to mislead you guys - it was due to my poor understanding of
                                Message 15 of 19 , Dec 28, 2008
                                  Hi:

                                  Lukasz (and Richard made some comments related to this as well)
                                  > besides, your indentation is misleading, the code reads

                                  Haha, I wasn't trying to mislead you guys - it was due to my poor
                                  understanding of OCaml. What I was really trying to get at was.

                                  Suppose I have the following code:

                                  let my_func =
                                  ..........
                                  fun () -> Printf.printf "Hello"
                                  [statement_1]
                                  [statement_2]

                                  (I'm using "statement" in the generic sense of "a line of code". In the
                                  thread that you linked to -
                                  http://caml.inria.fr/pub/ml-archives/caml-list/2004/09/4f6fa6e1512e47c73742acd74198d6e3.en.html-
                                  it was stated that there is a difference between "statement" and
                                  "expression", but it never mentioned what that was).

                                  Is it possible to have statement_1 and statement_2 be part of my_func, but
                                  not be part of the anonymous function? Based on what you've said, and in
                                  part by playing around with some code, it seems that this is not possible
                                  (i.e., statement_1 and statement_2 will always be considered part of the
                                  anonymous function in correctly-written code).

                                  Lukasz (I'm paraphrasing here):
                                  > let <fun_name> <pat_1> ... <pat_n> = <expr>"]
                                  > is a shortcut for
                                  > let f = function <pat_1> -> ... -> function <pat_n> -> <expr>

                                  Ah, I see. The reason why I thought the named expression/value was a
                                  special case of a function was because syntatically they looked so similar,
                                  and in many ways, seemed to behave similarly. It seems they are similar,
                                  but not in the way I had originally thought. Thanks for clearing that up.

                                  Cheers,
                                  legit


                                  [Non-text portions of this message have been removed]
                                • Richard Jones
                                  ... This code isn t meaningful OCaml though. Really, get an editor with an OCaml mode and try indenting such code. ... No it s not possible. In any case,
                                  Message 16 of 19 , Dec 29, 2008
                                    On Sun, Dec 28, 2008 at 06:15:34PM -0500, John Smith wrote:
                                    > let my_func =
                                    > ..........
                                    > fun () -> Printf.printf "Hello"
                                    > [statement_1]
                                    > [statement_2]

                                    This code isn't meaningful OCaml though. Really, get an editor with
                                    an OCaml mode and try indenting such code.

                                    > Is it possible to have statement_1 and statement_2 be part of my_func, but
                                    > not be part of the anonymous function? Based on what you've said, and in
                                    > part by playing around with some code, it seems that this is not possible
                                    > (i.e., statement_1 and statement_2 will always be considered part of the
                                    > anonymous function in correctly-written code).

                                    No it's not possible. In any case, what would statement_1 &
                                    statement_2 do in such a function?

                                    Rich.

                                    --
                                    Richard Jones
                                    Red Hat
                                  • Lukasz Stafiniak
                                    ... Yes, OCaml syntax is difficult ... Well I got used to it and I like it... ... (think about it, is it what you meant?) ... [should be instead of
                                    Message 17 of 19 , Dec 29, 2008
                                      On Mon, Dec 29, 2008 at 12:15 AM, John Smith <legit.anon@...> wrote:
                                      > Hi:
                                      >
                                      > Lukasz (and Richard made some comments related to this as well)
                                      >
                                      >> besides, your indentation is misleading, the code reads
                                      >
                                      > Haha, I wasn't trying to mislead you guys - it was due to my poor
                                      > understanding of OCaml. What I was really trying to get at was.
                                      >
                                      Yes, OCaml syntax is "difficult"... Well I got used to it and I like it...

                                      > Suppose I have the following code:
                                      >
                                      > let my_func =
                                      > ..........
                                      > fun () -> Printf.printf "Hello"
                                      > [statement_1]
                                      > [statement_2]
                                      >
                                      > Is it possible to have statement_1 and statement_2 be part of my_func, but
                                      > not be part of the anonymous function? Based on what you've said, and in
                                      > part by playing around with some code, it seems that this is not possible
                                      > (i.e., statement_1 and statement_2 will always be considered part of the
                                      > anonymous function in correctly-written code).
                                      >
                                      It is "possible" this way:

                                      > let my_func =
                                      > ..........
                                      > let result = fun () -> Printf.printf "Hello" in
                                      > [statement_1];
                                      > [statement_2];
                                      > result

                                      (think about it, is it what you meant?)

                                      > Lukasz (I'm paraphrasing here):
                                      >> let <fun_name> <pat_1> ... <pat_n> = <expr>"]
                                      >> is a shortcut for
                                      >> let f = function <pat_1> -> ... -> function <pat_n> -> <expr>
                                      >
                                      [should be <fun_name> instead of f, sorry]

                                      > Ah, I see. The reason why I thought the named expression/value was a
                                      > special case of a function was because syntatically they looked so similar,
                                      > and in many ways, seemed to behave similarly. It seems they are similar,
                                      > but not in the way I had originally thought. Thanks for clearing that up.
                                      >
                                      The basic use of "let" is to bind a name to a value, so that you can
                                      use a computed value multiple times. Defining a function is a special
                                      case of this, functions are just a kind of values. But "let" can also
                                      perform pattern matching as you observed. This "elaborate way to bind
                                      names to values" is a bit more than a syntax sugar.
                                    • John Smith
                                      Hi: Lukasz wrote: ... Nah, my question is probably more of a theoretical one. I was thinking that since the part of a let construct is immediately
                                      Message 18 of 19 , Dec 29, 2008
                                        Hi:

                                        Lukasz wrote:

                                        It is "possible" this way:

                                        > let my_func =
                                        > ..........
                                        > let result = fun () -> Printf.printf "Hello" in
                                        > [statement_1];
                                        > [statement_2];
                                        > result

                                        Nah, my question is probably more of a theoretical one. I was thinking that
                                        since the <expr> part of a "let" construct is immediately evaluated, except
                                        when <expr> contains the partial application of a function, could such a
                                        partial application "stall" the evaluation of statements afterwards? For
                                        example,

                                        let my_func =
                                        [statement_1]
                                        fun() -> Printf.printf "hello %s"
                                        [statement_2]

                                        I was wondering whether you could have the case that statement_2 is part of
                                        my_func, but not the anonymous function. If this was possible, then I was
                                        thinking you might get a weird situation where statement_1 is immediately
                                        evaluated, but statement_2 is evaluated either later (upon first use of
                                        my_func), or is evaluated many times (one for every use of my_func). It now
                                        appears that this is not possible, so I can rest easy :)

                                        Just one more small question - is the following allowed?:

                                        let my_func =
                                        [statement_1]
                                        let result = fun () -> Printf.printf "Hello %s" in
                                        [statement_2];
                                        result

                                        I think statement_1 and statement_2 would be immediately evaluated, and
                                        my_func is now bound to a function which takes in a string and prints it
                                        (i.e., calling my_func "George", would print out "Hello George").

                                        Cheers,
                                        legit


                                        [Non-text portions of this message have been removed]
                                      • Richard Jones
                                        ... No: fun () - ... is an expression which _evaluates_ to a function. The evaluation of the inner code ( ... ) is suspended until the function is called.
                                        Message 19 of 19 , Dec 29, 2008
                                          On Mon, Dec 29, 2008 at 12:42:59PM -0500, John Smith wrote:
                                          > Hi:
                                          >
                                          > Lukasz wrote:
                                          >
                                          > It is "possible" this way:
                                          >
                                          > > let my_func =
                                          > > ..........
                                          > > let result = fun () -> Printf.printf "Hello" in
                                          > > [statement_1];
                                          > > [statement_2];
                                          > > result
                                          >
                                          > Nah, my question is probably more of a theoretical one. I was thinking that
                                          > since the <expr> part of a "let" construct is immediately evaluated, except
                                          > when <expr> contains the partial application of a function, could such a
                                          > partial application "stall" the evaluation of statements afterwards? For
                                          > example,

                                          No:

                                          fun () -> ...

                                          is an expression which _evaluates_ to a function. The evaluation of
                                          the inner code ('...') is suspended until the function is called.

                                          let patt =
                                          [expr1];
                                          [expr2];
                                          [expr3]

                                          evaluates [expr1], [expr2], [expr3] immediately.

                                          let patt =
                                          [expr1];
                                          fun () -> ... ;
                                          [expr3]

                                          does the same thing (the fun () -> ... is just an expression which is
                                          evaluated immediately, returns an anonymous function, and then the
                                          anon function is thrown away).

                                          let patt =
                                          [expr1];
                                          [expr2];
                                          fun () -> ...

                                          does the same thing except this time the function is bound to the
                                          pattern name 'patt', instead of being just thrown away.

                                          > let my_func =
                                          > [statement_1]
                                          > fun() -> Printf.printf "hello %s"
                                          > [statement_2]
                                          >
                                          > I was wondering whether you could have the case that statement_2 is part of
                                          > my_func, but not the anonymous function. If this was possible, then I was
                                          > thinking you might get a weird situation where statement_1 is immediately
                                          > evaluated, but statement_2 is evaluated either later (upon first use of
                                          > my_func),

                                          If you want once-only evaluation, look at the Lazy module in the
                                          standard library.

                                          > Just one more small question - is the following allowed?:
                                          >
                                          > let my_func =
                                          > [statement_1]
                                          > let result = fun () -> Printf.printf "Hello %s" in
                                          > [statement_2];
                                          > result

                                          Yup. In this case the function is bound to 'result', and then
                                          'result' is bound to 'my_func', so it does what you expect.

                                          > I think statement_1 and statement_2 would be immediately evaluated, and
                                          > my_func is now bound to a function which takes in a string and prints it
                                          > (i.e., calling my_func "George", would print out "Hello George").

                                          Yup.

                                          Rich.

                                          --
                                          Richard Jones
                                          Red Hat
                                        Your message has been successfully submitted and would be delivered to recipients shortly.