Re: Syntax for label, ANOTHER NEW PROPOSAL

From: Steven Thomson (sthomson@zeta.org.au)
Date: Sat Mar 18 2000 - 01:04:22 MET

  • Next message: Julian Assange: "finalisation/gc"

    Pierre Weis wrote: [part of long post omitted]
    >
    > $ ocaml
    > Objective Caml version 2.99+10
    >
    > # let sum l = List.fold_right ( + ) l 0;;
    > val sum : int list -> int = <fun>
    >
    > Clearly application is denoted in ML with only one character: a space.
    >
    > Now, consider using the so-called ``Modern'' versions of these
    > functionals, obtained with the -modern option of the compiler:
    >
    > $ ocamlpedantic
    > Objective Caml version 2.99+10
    >
    > # let sum l = List.fold_right ( + ) l 0;;
    > ^^^^^
    > This expression has type int -> int -> int but is here used with type 'a list
    >
    > Clearly, there is something wrong now! We may remark that the error
    > message is not that clear, but this is a minor point, since error
    > messages are never clear enough anyway!
    >
    > The real problem is that fixing the code makes no good at all to its
    > readability (at least that's what I would say):
    >
    > # let sum l = List.fold_right fun:begin fun x acc:y -> x + y end acc:0;;
    > val sum : 'a -> int list -> int = <fun>
    >
    > It seems that, in the ``modern'' mode, application of higher order
    > functions is now denoted by a new kind of parens opening by
    > ``fun:begin fun'' and ending by ``end''. This is extremely explicit
    > but also a bit heavy (in my mind).
    >
    > For all these reasons, I would suggest to carefully use labels into
    > the standard libraries:
    >
    > -- remove labels from higher-order functional

    I don't think that merely omitting labels from higher-order functional
    arguments really solves the problem. Consider the following:

      $ ocaml -modern
              Objective Caml version 2.99 (99/12/08)

      # let add' :acc x = acc + x;;
            val add' : acc:int -> int -> int = <fun>
      # let rec fold_left' f accu l =
        match l with
          [] -> accu
        | a::l -> fold_left' f (f accu a) l;;
            val fold_left' : ('a -> 'b -> 'a) -> 'a -> 'b list -> 'a = <fun>
      # let sum' = fold_left' add' 0;;
          Characters 24-28:
      This expression has type acc:int -> int -> int but is here used with
    type
        'a -> 'b -> 'a

    If the definition of fold_left' does NOT use a label, we still get a
    compile error whenever we try to use an argument that DOES have a label.

    My proposal is to introduce an operator that can be used to tell the
    compiler to ignore labels when type-checking a higher-order functional
    argument. This could be thought of as a pragma which locally switches
    the compiler from modern to classic mode.

    Some possible variations:

    1. A prefix operator, here shown as "~", that causes only the following
    expression to be evaluated in classic mode:

      let sum = List.fold_left fun:~(+) acc:0
      let sum' = fold_left' ~add' 0

    2. A bracketing construct, here shown as [~ ~], that causes everything
    inside the brackets to be evaluated in classic mode.

      let sum = List.fold_left fun:[~(+)~] acc:0
      let sum' = fold_left' [~add'~] 0

    option 2 is not as visually lightweight, but might be more useful if
    there are several arguments that need to be altered:
      let aaa = bbb ccc:~ddd eee:~fff ggg:~hhh ~iii jjj
    versus
      let aaa = bbb [~ ccc:ddd eee:fff ggg:hhh iii ~] jjj



    This archive was generated by hypermail 2b29 : Sat Mar 18 2000 - 19:28:05 MET