caml-list - the Caml user's mailing list
 help / color / mirror / Atom feed
* RE: Syntax for label, NEW PROPOSAL
@ 2000-03-15 20:40 Don Syme
  2000-03-17  9:48 ` Jacques Garrigue
  0 siblings, 1 reply; 33+ messages in thread
From: Don Syme @ 2000-03-15 20:40 UTC (permalink / raw)
  To: 'Pierre Weis'; +Cc: caml-list


I agree very much with Pierre's comments.  Labels _do_ get in the way, and
probably shouldn't be used in the standard library in 3.00.

It seems pretty clear to me that a typical programmer only keeps an active
vocabulary of roughly 100-200 identifiers. (I mean identifiers from
libraries they are using but have not written themselves - I think you could
do experiments to confirm the figures, but whatever the range we all know
from experience that it is limited). If you accept that, then think about
the impact that labels have on this budget.  A quick grep reveals around 40
different labels.  It's clearly _much_ better to spend the budget on top
level identifiers rather than labels, because otherwise programmers, even
good ones, just become less effective.  The very presence of labels in the
standard library means that new users will look at them, learn them, try to
use them, and the size of their working set of library functions will
decrease as a result.

For example, using the "blit" function from the new version of the array
library module requires knowing not _one_ identifier but _six_.  An existing
user could still use the unlabelled version, but most new users will use
labels, thinking that this is leading to better code and better programming
(incorrectly, I believe, or at best a marginal improvement).  It's like C++
operator overloading - it looks oh so appealing, and a lot of fun for the
language designer to put in, but it nearly always ends up a waste of time to
use.

That's not to say labels are inappropriate everywhere, but it does explain
why they shouldn't be used on functions which users already use accurately,
or where errors in use are already caught by the type checker.  This is the
fundamental test: do labels help programmers use functions with fewer errors
at _runtime_, and is the advantage sufficient to make up for the extra
"weight" of even having the labels around at all?  Remember Caml won out as
the best ML implementation by being Caml-Light, not
Caml-you-must-be-aware-of-the-intricacies-of-my-features-to-learn-to-use-me
;-)

Thus, I'd argue for even stronger rules than Pierre:
  - Labels are only appropriate where a significant number of users 
    routinely make mistakes when using a function, and it is 
    clear that adding labels would solve the problem.
  - This means no labels on functions with 1 or 2 arguments.
  - This means no labels on functions with 3 arguments unless the 
    types are directly ambiguous (and probably not even then).
  - This means no labels on functions where a natural order exists for the
    arguments.
  - This also means no labels on polymorphic functions such as Hash.add (I
think
    it would be very rare that the typechecker wouldn't spot a misuse of
that
    function)
  - No labels inside the arguments of higher order functions.  This 
    will really confuse new users who try not to use labels!
    e.g.. no "acc" in the first argument of
         val fold_right: fun:('b -> acc:'a -> 'a) -> 'b array -> acc:'a ->
'a

And it's not always clear that labels are such a great help - even in the
case
of Array.blit, users may not use the labelled function 
much more accurately, given the time it takes to look up the label names,
correct the errors in misspelling the labels, and given that there is a
natural 
default rule in functional programming that a source operand 
come before a destination.  Even worse, because the programmer has
to remember the damn label names, there may be another 3 or 4 
library functions that they've never learnt to use at all.

Here's a story: In 1990, a new version of the HOL theorem prover (hol90) was
released.  The re-implementation was quite good, but the implementer made a
major mistake - he used labelled versions (actually SML records) of many,
many functions where nothing was gained by doing so.  This was a complete
waste of time, and was a major factor that lead to the splitting of the HOL
effort between "hol-light" and "HOL98", a split that took years to correct.
As Pierre describes, the object system was carefully designed not to put
people off, and if the standard libraries had been objectified then most
existing users would not have moved to OCaml.

Again, that's not to say I don't like labels - they are clearly useful when
functions take many arguments that have no natural order, and will be a god
send for some APIs.  However using them prolifically in the standard library
in this version is simply a bad idea.  Remember, you can always add them to
the standard library later, but you can't take them away!

Cheers,
Don  


-----Original Message-----
From: Pierre Weis [mailto:Pierre.Weis@inria.fr]
Sent: 15 March 2000 14:10
To: caml-redistribution@pauillac.inria.fr
Cc: caml-list@inria.fr
Subject: Re: Syntax for label, NEW PROPOSAL


[Sorry, no french version for this long message]

Abstract:

A long answer to Jacques's proposal. I do not discuss syntax but
semantic issues of the label extension. My conclusion is to be very
careful in adding labels into the standard libraries, and also state
as a extremely desirable design guideline to keep the usage of higher
order functions as simple as possible.

> *** Proposal
> 
> Objective Caml 3.00 is not yet released, and I believe we can still
> have modifications on this point.

Yes, you're perfectly right, we can still modify several points.
However, I think there are many other points that are more important
than the choice of ``%'' instead of ``:'', which is only cosmetic
after all.

Thus, I would prefer to discuss deeper and more semantic problems:

-- Problem1: labels can be reserved keywords. This is questionable
and it has been strongly criticised by some Caml users, especially when
reading in the code the awful sequence fun:begin fun ...

-- Problem2: labels that spread all over the standard libraries, even
when they do not add any good. I would cite:

   * the labels completely redundant with the types
     (E.g. char:char in the type of String.contains or String.index)

   * undesired labels: in many cases I don't want to have labels just
     because I don't want to remember their names. (E.g., I very often
     mispell the label acc since I've always used accu to name an
     accumulator; furthermore, when I do not mispell this label, I feel
     acc:accu extremely verbose). Also because labels are verbose at
     application.

   * labels that prevent you to use comfortably your traditional functions.
     This is particularly evident for the List.map or List.fold_right
     higher-order functionals.

This last point is a real problem. Compare the usual way of using
functionals to define the sum of the elements of a list:

$ 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
-- remove redundant labels: when no ambiguity can occur you need not
   to add a label.
-- use labels when typechecking ambiguity is evident (for instance
when there are two or more parameters with the same type).

Labels must enforce readability of code or help documenting the
libraries, it should not be an extra burden to the programmer and a
way of offuscating code.

Evidently, as any other extension, labels must not offuscate the
overall picture, that is they must not clobber the semantics, nor add
extra exceptional cases to the few general rules we have for the
syntax and semantics of Caml.

In this respect, optional labelled arguments might also be discussed,
particularly for the following facts:

-- syntactically identical patterns and expressions now may have
incompatible types:
   # let f ?style:x _ = x;;
   val f : ?style:'a -> 'b -> 'a option = <fun>

   As a pattern on the left-hand side x has type 'a, while as an
   expression on the right hand side it has type 'a option

-- some expressions can be only written as arguments in an application
   context:
   # let f ?style:x g = ?style:x;;
                        ^
   Syntax error
   # let f ?style:x g = g ?style:x;;
   val f : ?style:'a -> (?style:'a -> 'b) -> 'b = <fun>

-- the simple addition of a default value to an optional argument may
   trigger a typechecking error:

   # let f ?(style:x) g = g ?style:x;;
   val f : ?style:'a -> (?style:'a -> 'b) -> 'b = <fun>

   # let f ?(style:x = 1) g = g ?style:x;;
   This expression has type int but is here used with type 'a option

Do not forget the design decision that has always been used before in
the development of Caml: interesting but not universal extensions to
the language must carefully be kept orthogonal to the core language
and its libraries. This has been successfully achieved for the
important addition of modules (that do not prevent the users from
using the old interface-implementation view of modules) as well as for
the objects system addition that has been also maintained orthogonal
to the rest of the language (in particular the standard library has
never been ``objectified''). I don't know of any reason why labels
cannot follow the same safe guidelines.

> Here is an alternative proposal, to use `%' in place of `:'. Labels
> are kept as a lexical entity. This still breaks some programs, since
> `%' was registered as infix, but this is not so bad.

> Con:
> * I still think that `:' looks better, particularly inside types.
> * On my keyboard I can type in `:' without pressing shift :-)
> * We will need some tool to convert existing code.

I think that % should be the infix integer modulo symbol.

> Do you think it would be better?

No.

> Are there people around who would rather keep `:' ?

Yes. However this is syntax and we have to consider semantics in the
first place.

There are also people around that would like to keep Caml a true
functional language, where usage of higer order functions is easy and
natural.  We have to be careful not to lose what is the actual
strength of the language.

-- 
Pierre Weis

INRIA, Projet Cristal, http://pauillac.inria.fr/~weis



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

* RE: Syntax for label, NEW PROPOSAL
  2000-03-15 20:40 Syntax for label, NEW PROPOSAL Don Syme
@ 2000-03-17  9:48 ` Jacques Garrigue
  2000-03-17 17:34   ` Dave Mason
  0 siblings, 1 reply; 33+ messages in thread
From: Jacques Garrigue @ 2000-03-17  9:48 UTC (permalink / raw)
  To: caml-list

Having seen a number of recent messages against having labels in the
standard library, I have the feeling that there is a lot of confusion
here, and I would like to make a few points clear.

* In default (classic) mode, writing labels is (and will stay) not
  required. For those users that do not like labels, or do not want to
  bother with them, or just are starting to learn ML, labels in the
  standard library are just some form of documentation, like argument
  names in C prototypes.
  Honestly, I have never heard anybody protesting against having
  argument names in C prototypes.

* While not requiring labels, classic mode provides some support for
  them, meaning that casual users can put some labels in their
  programs if they want. This also means that any library written in
  modern mode (where labels matter) will be available with the same
  comfort in both classic and modern mode, and, more interestingly,
  according to the _user_'s taste rather than to the implementor's.

* What we are discussing about is modern mode. This is not pedantic
  mode, this is just another typing discipline. This basically doesn't
  concern people who are not very fond of labels, and will be perfectly
  happy with classic mode.

* Pierre expressed his concern that modern mode would make more
  difficult some nice programming style. I perfectly agree with him,
  but I think this specific problem can be solved without removing
  labels from the library.

Looking at the messages, there are clearly people who prefer (heavily)
labelled style, and others who prefer fewer or no labels. But they all
agree that Caml is and should stay a great _functional_ language.
Let's all live happily together: modern and classic mode are there for
that!

Jacques



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

* Re: Syntax for label, NEW PROPOSAL
  2000-03-17  9:48 ` Jacques Garrigue
@ 2000-03-17 17:34   ` Dave Mason
  2000-03-18  0:26     ` Jacques Garrigue
  0 siblings, 1 reply; 33+ messages in thread
From: Dave Mason @ 2000-03-17 17:34 UTC (permalink / raw)
  To: Jacques Garrigue; +Cc: caml-list

>>>>> On Fri, 17 Mar 2000 18:48:40 +0900, Jacques Garrigue <garrigue@kurims.kyoto-u.ac.jp> said:

> Having seen a number of recent messages against having labels in the
> standard library, I have the feeling that there is a lot of
> confusion here, and I would like to make a few points clear.

> * In default (classic) mode, writing labels is (and will stay) not
> required. For those users that do not like labels, or do not want to
>[...]

> * What we are discussing about is modern mode. This is not pedantic
> mode, this is just another typing discipline. This basically doesn't
> concern people who are not very fond of labels, and will be
> perfectly happy with classic mode.

I have been following this discussion somewhat remotely.  I've not
been able to do much programming lately, and almost no OCAML (I have
dabbled with Olabl a few times).  From what I can see:

1) please do not call it ``modern'' mode.  Call it ``label'' mode.
   The word modern has baggage attached to it.  Other words that would
   be as good but also have (somewhat different) baggage include:
   different, changed, messed-up, experimental...  My point is that we
   should use a word that is not ``good'' or ``bad'', and calling it
   ``label'' mode seems best.  I have no opinion on what ``classic''
   mode should be called, although I think ``classic'' is fine (there
   is a little baggage, but it is split between has-withstood-the-
   test-of-time and old-fashioned, so is fairly neutral overall).

2) I do not expect to use label mode very frequently, except when
   dealing with ugly APIs (typically ones imported from some outside
   world, such as Tk).  If I can, in classic mode, program as I always
   have done, and access these APIs, but otherwise ignore labels
   (especially in the standard libraries!), I will be happy.

3) I hope classic mode will remain the default for a *long* time.

../Dave



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

* Re: Syntax for label, NEW PROPOSAL
  2000-03-17 17:34   ` Dave Mason
@ 2000-03-18  0:26     ` Jacques Garrigue
  2000-03-23 13:07       ` Sven LUTHER
  0 siblings, 1 reply; 33+ messages in thread
From: Jacques Garrigue @ 2000-03-18  0:26 UTC (permalink / raw)
  To: dmason; +Cc: caml-list

From: Dave Mason <dmason@sarg.Ryerson.CA>

> I have been following this discussion somewhat remotely.  I've not
> been able to do much programming lately, and almost no OCAML (I have
> dabbled with Olabl a few times).  From what I can see:
> 
> 1) please do not call it ``modern'' mode.  Call it ``label'' mode.
>    The word modern has baggage attached to it.  Other words that would
>    be as good but also have (somewhat different) baggage include:
>    different, changed, messed-up, experimental...  My point is that we
>    should use a word that is not ``good'' or ``bad'', and calling it
>    ``label'' mode seems best.  I have no opinion on what ``classic''
>    mode should be called, although I think ``classic'' is fine (there
>    is a little baggage, but it is split between has-withstood-the-
>    test-of-time and old-fashioned, so is fairly neutral overall).

You have a very good point. In fact -modern was chosen arbitrarily
when integrating olabl code in ocaml, and was to be changed
before the release.  It might have avoided some confusions.

-labels would be OK. I just avoided it because it seemed to imply that
one couldn't use labels in classic mode, which is not true.

In my opinion -strict or -pedantic would be wrong: this is not the
intended meaning.

> 2) I do not expect to use label mode very frequently, except when
>    dealing with ugly APIs (typically ones imported from some outside
>    world, such as Tk).  If I can, in classic mode, program as I always
>    have done, and access these APIs, but otherwise ignore labels
>    (especially in the standard libraries!), I will be happy.

This is the intended behaviour. If you have problems in accessing
those APIs in classic mode, then this means something should be done
about it in the API. The implementor of a labelled library may not
realise that one parameter order is not so nice, just because he
doesn't care about it.

For instance, if you use LablTk in classic mode, you will have to put
the widget as last parameter in most functions. If you feel this is
weird, then you should report the inconvenience.

> 3) I hope classic mode will remain the default for a *long* time.

There are no plans to change this.
At least a consensus would be needed.

Jacques



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

* Re: Syntax for label, NEW PROPOSAL
  2000-03-18  0:26     ` Jacques Garrigue
@ 2000-03-23 13:07       ` Sven LUTHER
  0 siblings, 0 replies; 33+ messages in thread
From: Sven LUTHER @ 2000-03-23 13:07 UTC (permalink / raw)
  To: Jacques Garrigue; +Cc: dmason, caml-list

On Sat, Mar 18, 2000 at 09:26:54AM +0900, Jacques Garrigue wrote:
> > 3) I hope classic mode will remain the default for a *long* time.
> 
> There are no plans to change this.
> At least a consensus would be needed.

I think what would be very nice, is to be able to commute argument for some
functions, while using the classic mode for the rest of the code.

this could (or maybe can already) be done as follows :

...
lot of classic code
...

#open "commute" (* or "label", or "whatever" ...)

some label/commute/modern code

#close "commute"

...
rest of classic code
...

if that is possible, all is fine with me, best would be to have it be done
automatically, but since it don't seem to be possible, ...

Friendly,

Sven LUTHER



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

* Re: Syntax for label, NEW PROPOSAL
  2000-03-21 16:51       ` Pascal Brisset
@ 2000-03-23 11:14         ` Nicolas barnier
  0 siblings, 0 replies; 33+ messages in thread
From: Nicolas barnier @ 2000-03-23 11:14 UTC (permalink / raw)
  To: caml-list

I'm quite tired with all this polemic. I agree
with Pierre Weis: labels are a pain within HO
args (acc:, i:) and fun:(fun ...) is ugly and
verbose (and it contains its own sad smiley :).
So I do not want (arbitrary) labels in my good
old standard library, but I find them very useful
in Labltk. Moreover, two compile modes are not
a very good idea for obvious portability reasons.
So I think we should switch to a single modern
mode because labels in modern mode are useful
and simple (at least in Labltk), and withdraw
labels in the standard library because they're
often a pain (and the lib is small enough to
learn without the need for labels). We would
then keep labels an orthogonal improvment.

Cheers

-- Nicolas

P.S.: I saw in the lib that the *.mli are
written with labels whereas the *.ml do not
contain a single one. Can we conclude on which
side stands Xavier ?



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

* Re: Syntax for label, NEW PROPOSAL
  2000-03-16  2:55     ` Jacques Garrigue
  2000-03-17 15:13       ` Pierre Weis
@ 2000-03-21 16:51       ` Pascal Brisset
  2000-03-23 11:14         ` Nicolas barnier
  1 sibling, 1 reply; 33+ messages in thread
From: Pascal Brisset @ 2000-03-21 16:51 UTC (permalink / raw)
  To: caml-list; +Cc: Jacques Garrigue, Pierre.Weis

Jacques Garrigue writes:
> From: Pierre Weis <Pierre.Weis@inria.fr>
> >    * undesired labels: in many cases I don't want to have labels just
> >      because I don't want to remember their names. (E.g., I very often
> >      mispell the label acc since I've always used accu to name an
> >      accumulator; furthermore, when I do not mispell this label, I feel
> >      acc:accu extremely verbose). Also because labels are verbose at
> >      application.
> 
> Isn't there a classic mode for that?

 Something I do not understand: how could I use Labltk, for which I want
to be modern, and List.fold_right, for which I do not want labels, in the
same file ?
 By the way, the label "acc" (or even "accu") does not mean anything for me
in fold_right: the iterator associates one function to each
constructor of the type so I would prefer

val fold_right: cons:(hd:'a -> tl:'b -> 'b) -> nil:'b -> list:'a list -> 'b

[...]

> It would cost nothing to add 4 more unlabelled functions to the List
> module.

 Please add a smiley when you write such a sentence !

[...]

> Or do you think that the problem is deeper, and that labels are
> breaking the foundations of the language ?

 Please ! The debate is about presence of labels in the standard library,
not in the language.
 Today, it is possible to teach Ocaml without speaking about objects,
modules (functors are not so common in libraries), streams, etc. If labels
are in the standard library you will have to explain one more (nice
and not so simple) feature before being able to use one
simple list iterator ...

Amicalement

--Pascal



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

* Re: Syntax for label, NEW PROPOSAL
  2000-03-17 21:33 Damien Doligez
  2000-03-18 21:07 ` Frank Atanassow
@ 2000-03-18 22:40 ` John Prevost
  1 sibling, 0 replies; 33+ messages in thread
From: John Prevost @ 2000-03-18 22:40 UTC (permalink / raw)
  To: Damien Doligez; +Cc: caml-list

Damien Doligez <Damien.Doligez@inria.fr> writes:

> >From: Don Syme <dsyme@microsoft.com>
> >  - No labels inside the arguments of higher order functions.  This 
> >    will really confuse new users who try not to use labels!
> >    e.g.. no "acc" in the first argument of
> >       val fold_right: fun:('b -> acc:'a -> 'a) -> 'b array -> acc:'a -> 'a
> 
> But that argument doesn't really work because new users who try not
> to use labels will not use label mode.

Actually, that's over-simplifying.  In fact, I would simply turn off
label mode--EXCEPT that I might want to use something like tk, which
has an API I don't think is usable without labels.

So I would either have a mixture of source files, some compiled with
labels on some with off, or all labels.  And even in the files where I
want labels, I'd rather not use them on the standard library, but I
would have to.  :(

John.



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

* Re: Syntax for label, NEW PROPOSAL
  2000-03-17 21:33 Damien Doligez
@ 2000-03-18 21:07 ` Frank Atanassow
  2000-03-18 22:40 ` John Prevost
  1 sibling, 0 replies; 33+ messages in thread
From: Frank Atanassow @ 2000-03-18 21:07 UTC (permalink / raw)
  To: Damien Doligez; +Cc: caml-list

Damien Doligez writes:
 > I agree, and I would even go further.  I think the current labeling of
 > the standard library is way too verbose.  "fun" should not be "func"
 > or even "fn", but simply "f".  That's the usual name for a generic
 > function.  Likewise, we should replace char:char with c:char and so
 > on (maybe even the predicate function in List.for_all should be
 > labeled f).

If you hold that the point of labels is to provide extra "type checking", then
naming labels according to the type they annotate is exactly the wrong way to
proceed. For example, if you have a function f : char -> char -> t, you would
want to disambiguate the role of the two characters, since the type checker
cannot catch it, but using the generic label name 'c' will not help you here.

By that token, a convention for picking label names should distinguish
arguments according to their "role" (some semantics above and beyond what can
be expressed with the type system), not their type.

BTW, this thought just occurred to me regarding semantics: you might view
labels as a class of unary type constructors which are the identity on
types. This implies you would write:

  val pow : int Base -> int Exp -> int

The capitalization distinguishes these "identity" constructors from abstract
and primitive ones.

To define pow, you restrict the argument patterns explicitly:

  let pow (b:'a Base) (e:'a Exp) = ...

To use pow, we can either restrict the argument types explicitly:

  pow (2:'a Base) (3:'a Exp)

or rely on type inference. Of course, this doesn't address the issue of
reordering (IMHO the idea of reordering is a little dubious, esp. considering
the interaction with side-effects) and having to insert the type variables is
ugly, but at least it provides some documentation and a less ad hoc approach
to the syntax. Anyway, it's only the germ of an idea.

Another idea is to stipulate a class of kinds (in the sense of "type of a
type") of labels, and distinguish the syntax for kind restriction of values,
say term :: kind (bad choice, I know) from the syntax for type restriction for
values, term : type. However, kind restriction of types is still written
":". Then you write something like:

  val pow : int : base -> int : exp -> int
  let pow (b :: base) (e :: exp) = ..
  pow (b :: base) (e :: exp)

Also you must demand that every label kind is a subkind of the kind Type so
that, for example, (->) can operate on labelled types.

Does this make sense? I'm a little too tired to think very clearly... One
thing I don't like about this is that the label names don't get declared
anywhere, they just seem spring into existence. I guess you could insist that
they get declared somewhere with a new syntactic construct, but I don't see
much point in it.

-- 
Frank Atanassow, Dept. of Computer Science, Utrecht University
Padualaan 14, PO Box 80.089, 3508 TB Utrecht, Netherlands
Tel +31 (030) 253-1012, Fax +31 (030) 251-3791



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

* Re: Syntax for label, NEW PROPOSAL
  2000-03-17 15:13       ` Pierre Weis
  2000-03-17 17:33         ` Wolfram Kahl
@ 2000-03-18 11:59         ` Jacques Garrigue
  1 sibling, 0 replies; 33+ messages in thread
From: Jacques Garrigue @ 2000-03-18 11:59 UTC (permalink / raw)
  To: Pierre.Weis; +Cc: caml-list

From: Pierre Weis <Pierre.Weis@inria.fr>

> > The rationale behind allowing the use of keywords as labels is that
> > there are lots of keywords in Caml, and many of them are good
> > candidates for labels. Not allowing them makes often choice more
> > difficult, or forces to use longer names.
> 
> The problem is that we have just a few rule for the Caml syntax, and
> this violates this elementary one:
> 
> ``In Caml, keywords are RESERVED identifiers''

This can be discussed indeed. Formally the rule is not broken: in the
manual labels are defined as an alphanumeric string ending by `:',
which is lexically different from any keyword. But this definition may
seem strange.  Before definitively deciding on this, we can start by
the standard library.

> > This would mean:
> > 
> > fun -> func
> 
> Could also consider fn

I don't know why, but I don't like very much fn:, maybe because it
reminds me of another language :-)
In general, I think consonant-only labels are not very good, because
you have to mentally add the missing vowels when reading.
That's pretty subjective, though.

> > > -- Problem2: labels that spread all over the standard libraries, even
> > > when they do not add any good.
> > 
> > Well, the current policy (as defined in the manual) is to put labels
> > on at least all arguments but one (with some very special exceptions
> > like printf). This is necessary to allow commuting between arguments,
> > which is also an important theme of labels. As such I would not say
> > that they do not do any good.
> 
> I'm afraid I don't agree with you: commuting between arguments is not
> worth the extra burden of having labels, I'm not sure it is even
> desirable. I think that when arguments of a function are not always
> passed in the same order the readibility of the code is jeopardized.

That's where I think there are really two approaches and two
philosophies.

I thought that the goal of the merger between ocaml and olabl was not
only to integrate some olabl features, but also to merge the two
communities.
The O'Labl community has a different philosophy of programming.
If you consider this as an heresy, we cannot go very far.

I really believed that, especially because it is ocaml, we could have
an oecumenic approach: accept everybody and every style, with their
differences.

To achieve this goal, the classic mode was carefully designed so as to
allow what is your view of labels: an optional help to readability,
but no commutation.
It also ensures the interoperability between both styles.
I'm really curious of why you persist in ignoring its existence (and
the fact this is the default mode).

On the other hand, the modern mode, which should probably renamed
-labels or rather -commute mode, since this is its main difference
with classic mode, is really intended for people who more or less
agree with the olabl philosophy, and consider label commutation as an
important feature.

If you consider that such diversity is bad, and that there should be
only one mode, I do not really see what we can do. One solution would
be to have two different standard libraries, but this creates 3
problems:
* technical problems when linking code based on the two libraries.
* basically it doesn't solve the problem of all other libraries.
  Non-labellers will still find that there are too many labels in
  labelled libraries, and they will be discouraged from adding
  documentation labels to their own libraries, which in turn will make
  them incomfortable to use for labellers.
* ocamlbrowser looses a great part of its interest, which is to be
  able to see the labels as documentation.

> > I suppose we should have a precise idea of what labels are there for.
> > For me they are a systematic mechanism, and the fact we allow to have
> > no label on one argument in function types is just a little comfort,
> > particularly useful when working with functionals.
> 
> Wao! So, the normal evolution would be to have labels as ``a
> systematic mechanism'' ? I'm afraid this is really a dogmatic view,
> and may be some Caml users will object ...

The meaning of systematic here is just about the standard way to put
labels, not the way to use them. I do not intend to impose the use of
labels to anybody. Nor to force anybody to comply with the standard.

The theoretical background of the commuting mode is the selective
lambda-calculus, in which no label is also a label.  From this point
of view having functions with no labels is just having functions where
all arguments have the same label.  This is just a pain.

> > > # let sum l = List.fold_right ( + ) l 0;;
> > > val sum : int list -> int = <fun>
> > 
> > Whether you consider this readable or not is a question of taste.  I
> > personally believe that you need quite a background in HO formalisms
> > to understand the above. But of course most current Caml users have
> > this background.
> 
> No, this is not a question of taste, since whatever readable you
> consider this definition, it is still more readable, easier to
> understand and easier to write than the labelized version:

I maintain this is a subjective judgment. The labelled version is in
my opinion easier to understand from an algorithmic point of view.

But I don't ask you to agree with that, just to admit that other
people may have other opinions. I perfectly respect yours.

> > Remark that here you didn't care about whether acc is the first or
> > second argument of the passed function, just because (+) is
> > commutative. However, in general functions are not commutative, and I
> > always have to think a lot when using List.fold_left or
> > List.fold_right without labels, just because I may write wrong code
> > without the type checker telling me anything.
> 
> Yes functions in general are not commutative, but I cannot imagine how
> labels may prevent you from thinking when using List.fold_right...

Here is an example:

# let make_set l =
    List.fold_right (fun x l -> if List.mem x l then l else x::l) [] l ;;
val make_set : 'a list -> 'a list = <fun>

At first sight it looks right. But if you look carefully you will
realise that in List.fold_right (contrary to List.fold_left) the
starting value comes last. So this function is just the identity!

Now, if I put a label (even in classic mode),
# let make_set l =
    List.fold_right (fun x l -> if List.mem x l then l else x::l) acc:[] l ;;
                                                                      ^^
Expecting function has type 'a list -> acc:'b -> 'b
This argument cannot be applied with label acc:

The system tells me that this is wrong, and I do not have to think
carefully about whether the accumulator comes first or last.

I'm just waiting for the day we will discover this kind of bug inside
the compiler itself...

By the way, this also connects to the fact we need two different
typings for folding functions, depending on whether the used function
is a symmetrical one (which has no label) or an asymmetric one like
above.

That is, if considering both that having acc: in the expected function
is a pain, and that acc: on fold itself is useful, we choose the type

val fold_left : fun:('a -> 'b -> 'a) -> acc:'a -> 'b list -> 'a

we are no longer able to write fold_matrix as we can now:

# let fold_matrix fun:f = List.fold_left fun:(List.fold_left fun:f);;
val fold_matrix : fun:(acc:'a -> 'b -> 'a) -> acc:'a -> 'b list list -> 'a

So we need two functions: one with acc: in both places, and one with
neither.

> In several ways, I think labels may help obfuscating code, for
> instance if they allows you to treat the arguments of functions as a
> set instead of an ordered list: if arguments are never passed in the
> same order, the code is much harder to read, since it is much more
> difficult to remember the profile of functions (unless you remember
> the set of labels associated with the function's profile AND the types
> associated with the labels).

On what experience do you base this judgment ?
This is certainly not that of olabl users.

By the way the point is that you do not need to remember the profile
of functions at reading: it is explicit in the syntax.  Labels are
often more informative than types.

> > >    # let f ?style:x _ = x;;
> > >    val f : ?style:'a -> 'b -> 'a option = <fun>
> > > 
> > >    As a pattern on the left-hand side x has type 'a, while as an
> > >    expression on the right hand side it has type 'a option
> > 
> > Well, internally the left-hand side is also 'a option, but option is
> > abbreviated because it is redundant. I do not think people want to see
> > the left-hand side option, but maybe this technical part should be
> > made more explicit in the manual.
> 
> This is not the problem: the problem is this is an exception to a simple
> and intuitive rule of the Caml static semantics:
> 
> ``In Caml, variables bound by patterns have a unique type''
> 
> Corollary: when used in expressions, variables bound by patterns have
> the same type as their pattern type.

But this is the case (they have same type).  I do not see how they
could have a different type.  'a is not the type of the pattern, but
of the expected value, and where option is abbreviated for the above
reason.

The "exception" actually is not the above case, but rather

# let f ?(:style = 0) () = style;;
val f : ?style:int -> unit -> int = <fun>

Here the type of the pattern is int (not int option, since there is a
default value), but the type of the expected value is int option.

We could make everything consistent and just say that the expected
value is of type int rather than int option, by requiring a default
value for all optional arguments, and hide completely the
implementation.
However, this would greatly weaken the system: the nice thing with
optional arguements is that they can depend on each other, and that we
can checked whether a value was passed or not. Remark also that if we
do that we loose nice properties of the current system (particularly
compared with other systems of default arguments, that are often based
on overloading), like eta-expansion:

# fun ?:style -> f ?:style;; 
- : ?style:int -> unit -> int = <fun>

> > Conversion from 'a to 'a option is done at application. I do not
> > think there is any semantical problem here.
> 
> I do think there is a problem here, since once more this violates a
> simple rule of Caml semantics:
> 
> ``In Caml, there is no implicit coercions.''

No, this conversion is not based on types, and there is an untyped
semantics for optional arguments in both classic and commuting modes.

Types are used in the compiler, but just to make it more efficient.

> > > -- some expressions can be only written as arguments in an application
> > >    context:
> > >    # let f ?style:x g = ?style:x;;
> > 
> > ?style:x is not an expression: labels are part of the application
> > node, not of the arguments.
> 
> I know that and find it counter-intuitive, since once more it breaks
> a very simple and intuitive rule of Caml:
> 
> ``Caml expressions possess the sub-term property: sub-expressions are
> also expressions''

This is false: (1 +) is not an expression in Caml.

> Once more, I know those technical reasons, but I do not get for
> granted that technical reasons are a valid answer to violations of the
> simplicity and intuitive understanding of the language. If technical
> reasons cannot handle some nice feature but force you to turn this
> feature into a bad hack, then you must choose not to incorporate the
> feature since it is no more a nice feature.

Yes in general, but do you really think that there is a deep
violation, and that this is a bad hack?

All the systems of optional arguments I know of are based on worse
hacks, like overloading, dynamic processing of a list of pairs
label/value, values in interfaces, etc...
I would rather say that we can be proud of avoiding all these.

> > Whether this is a good idea to have such syntactic sugar in
> > the language is an interesting question. However I believe it provides
> > some real comfort.
> 
> You must carefully balance this comfort with the extra cost in terms
> of complexity and exceptions to the usual semantics (either static or
> dynamic) ...

Agreed.  Dynamic semantics get (much) more complex.  However, you can
understand it as a series of conservative extensions over the original
simple semantics of Caml.

> > Now, the problem we are talking about seems to boil down to higher
> > order functions in modern mode. And more particularly List.fold_left
> > and List.fold_right, since these are about the only two functions
> > where the argument itself has labels.
> > 
> > It would cost nothing to add 4 more unlabelled functions to the List
> > module.
> 
> And do the same for modules List and Hashtbl and Array and Set and
> Map, ... this will cost a bit I think.

Well, not in Hashtbl and Map since there the operation accepted by
fold takes 3 arguments, meaning that you won't apply it to an
arbitrary predefined operator.

So, this is only List, Array and Set (currently).
I don't know what is you scale for cost, but I just meant that this is
only adding
        let foldl = fold_left
to the implementation, and
        val foldl : ...
to the interface, with no code duplication.

By the way, this is not the first time we have to add one more
function just for typing reasons. Remember Sys.signal and
Sys.set_signal.

> > Or do you think that the problem is deeper, and that labels are
> > breaking the foundations of the language ?
> 
> In my opinion some fundamental rules are broken in the current
> situation of the labels addition, and I think we should try to
> overcome this drawback to let the language simple to explain and
> use.

I'm afraid there is no miracle to expect there.  OLabl itself was
based on serious theoretical work, and we have thought seriously
(together) of how to make OCaml 2.99 clean.  If anybody has a perfect
solution, which also satisfies olabl users, then I applaude, but I am
very dubitative.

Amicalement,

Jacques
---------------------------------------------------------------------------
Jacques Garrigue      Kyoto University     garrigue at kurims.kyoto-u.ac.jp
		<A HREF=http://wwwfun.kurims.kyoto-u.ac.jp/~garrigue/>JG</A>



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

* Re: Syntax for label, NEW PROPOSAL
@ 2000-03-17 21:33 Damien Doligez
  2000-03-18 21:07 ` Frank Atanassow
  2000-03-18 22:40 ` John Prevost
  0 siblings, 2 replies; 33+ messages in thread
From: Damien Doligez @ 2000-03-17 21:33 UTC (permalink / raw)
  To: caml-list

First of all, I don't think I'm going to use label mode anytime soon,
but the same is true of objects, I haven't looked at variants yet, and
I consider higher-order functors an exotic feature that I'll probably
never need (and I do use double-semicolons).

But that's no reason to go to war against labels.  It's just I'm in
love with the small simple functional language that is at the heart of
O'Caml. As long as I can use it, I'm happy.

Now a few random comments on the discussion.


>From: Don Syme <dsyme@microsoft.com>
>  - No labels inside the arguments of higher order functions.  This 
>    will really confuse new users who try not to use labels!
>    e.g.. no "acc" in the first argument of
>       val fold_right: fun:('b -> acc:'a -> 'a) -> 'b array -> acc:'a -> 'a

But that argument doesn't really work because new users who try not
to use labels will not use label mode.


>o The "just documentation" response doesn't really hold water,
>because if the labels were just documentation, then they would
>different.  For example, "fun", being a keyword, is highly confusing
>and not terribly descriptive - any sensible prototype would probably
>just use "f".

I agree, and I would even go further.  I think the current labeling of
the standard library is way too verbose.  "fun" should not be "func"
or even "fn", but simply "f".  That's the usual name for a generic
function.  Likewise, we should replace char:char with c:char and so
on (maybe even the predicate function in List.for_all should be
labeled f).

Also, in the List module, I found this:

    val nth : 'a list -> pos:int -> 'a

This is really bad design, unless the goal is to confuse the reader
(two different names for the same number).  It should be either

    val nth : 'a list -> n:int -> 'a

or

    val posth : 'a list -> pos:int -> 'a
.

I think we need to develop a systematic set of abbreviations (and a
document to explain it) that will allow us to limit almost all labels
to be at most one character in length.  It would (at least partially)
solve the problem of expression cluttering that we have with the long
labels currently in the library.  As a side-effect, it would also
solve the problem of keywords as labels: there isn't any keyword of
length 1.


>From: Dave Mason <dmason@sarg.Ryerson.CA>
>1) please do not call it ``modern'' mode.  Call it ``label'' mode.

This is an excellent suggestion, and I have implemented it (as of
version 2.99+12) : I replaced the command-line option "-modern" with
"-label".  I kept "-modern" as an alias to "-label" for the time
being, but I certainly hope we'll retire it before we release 3.00.

-- Damien



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

* Re: Syntax for label, NEW PROPOSAL
  2000-03-17 17:03 Don Syme
@ 2000-03-17 19:24 ` John Prevost
  0 siblings, 0 replies; 33+ messages in thread
From: John Prevost @ 2000-03-17 19:24 UTC (permalink / raw)
  To: Don Syme; +Cc: 'Jacques Garrigue', 'caml-list@inria.fr'

Don Syme <dsyme@microsoft.com> writes:

> o To ensure "living happily together", my feeling is you should
>   leave the standard library alone (though I could live with 2 or 3
>   functions having labels), but go wild with labels and variants in
>   the places were no one doubts they will be useful.

I think I agree here.  I do see labels as useful in a number of places
(certainly places like Tk where you have large numbers of arguments,
many of which are optional.)  But, in places in the standard library,
you can create some big nasty messes.  The List.fold_right example is
a good one.  On the one hand, I do have to think about which way the
folding is going to happen, and which argument to the f argument is
which.  On the other, there are very few places where a function which
is useful for folding has an acc argument.

Arguing that a consistent labelling style is good is a nice point.  If
every function that uses an argument in a certain way has the same
label, it makes it easier to remember what's going on.  But the
functions which need labels most (those which have many arguments)
have the most specialized labels.  And the functions which are most
standard have little ambiguity, leaving reordering of arguments the
only benefit:

let foo l = map l
  fun:function
    ...
    ...
    ...

I like the ability to move the "heaviest" clause of my expression to
the end, but I'm not willing to put up with the acc thing in
fold_right to get it.  And of course, reordering is only available in
"modern" mode.

If we could come up with a semantics where labels are always optional,
I think I would accept things like acc in the standard library.  But
when you have to make a choice between optional labels and no useful
functionality, it's a harder sell.

I can imagine a system in which an unlabelled argument means "the next
argument in the argument list, regardless of label" and a labelled
argument means "the next argument in the argument list with this
label".  Of course, this leads to oddness.  Let's look at map for a
simple example:

map : f:('a -> 'b) -> 'a list -> 'b list

(I assume this hasn't changed.  I'm using f instead of fun.)

map x : 'a list -> 'b list
map f:x : 'a list -> 'b list

without a label for the 'a list, there's no way in this optional-label
scheme to re-order the argument earlier.  So this would seem to imply
that labels would only be useful if there were many different labels,
or if unlabelled arguments were "first":

map2 : 'a list -> f:('a -> 'b) -> 'b list

this option is irritating because it changes the default ordering.
And the standard ordering makes a lot more sense, even when you can
write:

map2 fun:f

to get the old behavior.

map3 : f:('a -> 'b) -> list:('a list) -> 'b list

this option preserves the standard ordering, but we had to define a
label for the second argument.  That's more okay than it would be in a
system where labels are mandatory, but it means more work for people
writing libraries using labels.  The now need to think about a
"standard" ordering for the arguments, as well as a "labelling" which
allows reordering.


Summary:

The standard library should not have labels unless labels undergo a
massive change in semantics which will remove the known-ness of
labels' utility in O'Labl.

I want labels for working with things like LablTk and LablGtk.  But
when it comes to the standard library, I agree with the SML people.
"Gross!"  I use O'Caml because it has a nicer, cleaner syntax than
SML.  Mucking it up like this, even as an optional mode, is bad.


John.



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

* Re: Syntax for label, NEW PROPOSAL
  2000-03-17 15:13       ` Pierre Weis
@ 2000-03-17 17:33         ` Wolfram Kahl
  2000-03-18 11:59         ` Jacques Garrigue
  1 sibling, 0 replies; 33+ messages in thread
From: Wolfram Kahl @ 2000-03-17 17:33 UTC (permalink / raw)
  To: caml-list


As a long time user of OLabl, I was very happy when the ``great merger''
was announced. I was also very happy that there were quite a few
very positive reactions on this list, and that there was the understanding
that the merger should serve both those who wanted to stay in their old
worlds, be it the world with or the world without labels
(by making libraries written in the other world accessible to them),
and those who wanted to do some border-crossing.

In the last few days, however,
the tone seems to have changed considerably ---
before a religious war breaks out,
I would recommend reading ``Nathan der Weise'' by Lessing ;-)


More to the point:

Pierre Weis <Pierre.Weis@inria.fr> writes:
 > I'm afraid I don't agree with you: commuting between arguments is not
 > worth the extra burden of having labels, I'm not sure it is even
 > desirable. I think that when arguments of a function are not always
 > passed in the same order the readibility of the code is jeopardized.

To me, for some functions the arguments are in the wrong order
whichever order you put them.
Even for some functions in the standard library.

So when writing applications of these functions,
I have to look them up anyway --- and for me it is faster
to do this via LablBrowser/CamlBrowser than via the local
installation of the HTML version of the manual.

When reading the code, however, with labels
I do not have to look up the function at all!


I find code with heavy use of functions with more than three arguments
hard to read without labels --- no matter whether ML or Haskell.
I find myself routinely writing functions
with around ten non-optional arguments.
And I am glad that I can add another five optional arguments,
should the need arise,
to spare me the copy-and-paste of the function definition for a new variant.
I find labels indispensable for this.
I often do copy-and-paste for the labelled applications ;-),
and labels help to find the place to be changed.
But the real pay-off comes at the time of reading the code
(which I do, sometimes :-),
when I can read it without having to look up the definition.


Of course, there are other programming styles, too,
and very algebraic combinator-style programming
will profit much less from labels, and look nicer in classic style.


I love higher order functions, too, so initially the requirement
to do long eta normal forms seemed to be a drawback to me
just the same way as to some people on the list.


However, nowadays I find myself doing ``fold_right (+)'' much less
than ``fold_right myfunction'', where ``myfunction'' often is
a partial application of a more-argument function
that has been let-defined a few lines above ---
this application can still be multi-line,
but since the more-argument function has been let-defined for the purpose
of having its instances used in fold_right,
I find that adding this one extra label in the let-definition
does no harm at all, on the contrary,
it adds to the readability of the definition of the more-argument function.


So for me, labels have proved to be the right thing for what I do
with OCaml/OLabl --- but then, I do not claim to be a typical user:
When doing combinator-style programming, I prefer Haskell,
and, half joking, I consider OCaml/OLabl an imperative programming language
just by virtue of its not being purely functional
(I do not use other imperative programming languages,
 (except shells), and I also recommend my students not
 to use other imperative programming languages ---
 some even understand and follow :-).


Maybe the question to be discussed
is which kind of mixtures between the two styles
should be enabled by the compiler.
For my perception of OCaml-3.0, however,
I think it is sufficient if it just puts the two worlds
of no-label-users and label-users
on a common technical basis,
without forcing anybody to really change their style
(which is, as I perceive and understand it,
 the design philosophy followed so far).


Best regards,

Wolfram



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

* RE: Syntax for label, NEW PROPOSAL
@ 2000-03-17 17:03 Don Syme
  2000-03-17 19:24 ` John Prevost
  0 siblings, 1 reply; 33+ messages in thread
From: Don Syme @ 2000-03-17 17:03 UTC (permalink / raw)
  To: 'Jacques Garrigue', 'caml-list@inria.fr'


I really don't see people clamouring for lots of labels in the standard
library (besides the inventors of the language feature, who don't really
count, for lots of obvious reasons - over exposure to the feature, over
familiarity with the label names, a natural bent to program in a particular
way that led them to the feature in the first place, self-selection as
people who think the feature is the best thing ever).

I reiterate my bottom line: only add labels to a particular function if you
can strongly argue that they will actually decrease the number of mistakes
made by typical users that are not already caught by the typechecker.  Don't
argue about "labels being good practice" - programmers don't care about what
someone else sees as good practice (we'd all be using Ada if they did) -
they care about getting 90% of their code right first time, which is what
the Caml type checker already ensures.

That is, you need to argue when and where labels are _good_, and not just
why they are _harmless_.  (And in the world of language design, no extra
language feature is truly harmless).  IMHO, one of the only functions in the
standard library that comes close to needing labels is "blit", and I've
already argued why it's marginal that they are even of much help there.

Four more points:

o The fact that you've had to resort to "modes" at all indicates something
is wrong.  The point about O'Caml is that you shouldn't have to understand
_anything_ about labels, objects, modules or syntax modes to use the system
as a new user.  You shouldn't have to see any labels, nor have to ask "what
are these two modes all about", nor have to try to understand why some of
the arguments have labels and some don't.

o The "just documentation" response doesn't really hold water, because if
the labels were just documentation, then they would different.  For example,
"fun", being a keyword, is highly confusing and not terribly descriptive -
any sensible prototype would probably just use "f".  And C prototypes look
_horrible_ when you have both higher order arguments and argument names.

o A quick poll of 2 of my Standard ML friends down the corridor about what
they think of labels going in the standard library, and they all said
"gross".

o To ensure "living happily together", my feeling is you should leave the
standard library alone (though I could live with 2 or 3 functions having
labels), but go wild with labels and variants in the places were no one
doubts they will be useful.

Cheers!
Don


-----Original Message-----
From: Jacques Garrigue [mailto:garrigue@kurims.kyoto-u.ac.jp]
Sent: 17 March 2000 15:23
To: caml-redistribution@pauillac.inria.fr
Subject: RE: Syntax for label, NEW PROPOSAL


Having seen a number of recent messages against having labels in the
standard library, I have the feeling that there is a lot of confusion
here, and I would like to make a few points clear.

* In default (classic) mode, writing labels is (and will stay) not
  required. For those users that do not like labels, or do not want to
  bother with them, or just are starting to learn ML, labels in the
  standard library are just some form of documentation, like argument
  names in C prototypes.
  Honestly, I have never heard anybody protesting against having
  argument names in C prototypes.

* While not requiring labels, classic mode provides some support for
  them, meaning that casual users can put some labels in their
  programs if they want. This also means that any library written in
  modern mode (where labels matter) will be available with the same
  comfort in both classic and modern mode, and, more interestingly,
  according to the _user_'s taste rather than to the implementor's.

* What we are discussing about is modern mode. This is not pedantic
  mode, this is just another typing discipline. This basically doesn't
  concern people who are not very fond of labels, and will be perfectly
  happy with classic mode.

* Pierre expressed his concern that modern mode would make more
  difficult some nice programming style. I perfectly agree with him,
  but I think this specific problem can be solved without removing
  labels from the library.

Looking at the messages, there are clearly people who prefer (heavily)
labelled style, and others who prefer fewer or no labels. But they all
agree that Caml is and should stay a great _functional_ language.
Let's all live happily together: modern and classic mode are there for
that!

Jacques



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

* Re: Syntax for label, NEW PROPOSAL
  2000-03-17 14:05         ` Jacques Garrigue
@ 2000-03-17 16:08           ` Pierre Weis
  0 siblings, 0 replies; 33+ messages in thread
From: Pierre Weis @ 2000-03-17 16:08 UTC (permalink / raw)
  To: Jacques Garrigue; +Cc: caml-list

> There may indeed be good reasons for let-binding.
> However, if you look at the sources of ocaml, you will see that in
> many, many places such functions are defined inline without
> let-binding. I see two reasons for that:
> * you often don't want to think of a name for such a function
>   (most of them are just 2 or 3 line long)

Is this argument relevant to the problem at hand ? You were speaking
of the advantage of using a label fun: for applying map to a ``long
multi line function definition'':

>               fun:(fun long multi line function  definition here)

If the function is ``long'' and multi line, I definitively prefer a let
binding. If it is not ``long'' I prefer no label and a short and
elegant (fun x -> ...).

> * it forces you to move the code around in a way that is not
>   necessarily very natural. It's a bit like RPN: first define a
>   function, then apply a functional to it.
>   (We could of course ressucite the where clause :-)

Yes that's fundamentally the way it goes in Caml: define first
something then use it (static binding). I'm sorry, we removed the
where construct a long time ago exactly with this argument.

As you say below ``More generally, my experience is that''

* once anonymous functions are named, the code is clearer
* when anonymous functions are ``long multi line'' the code is obscure.

> More generally, my experience is that more freedom in the way to
> layout them increases the use of functionals. After all there are many
> ways to see the same function, different logical understanding of its
> meaning. And the fact you can use all these ways with the same function
> avoids confusion.
> Why should we decide that one way is right, and others are wrong?

You already answered to this question in your paragraph: I would answer
in the first place with the very reasons you are advocating to ask why
we should decide; you wrote ``my experience'', ``logical
understanding'', ``avoids confusion''.

So, we should decide that one way is right based on experience, theorems,
confusion avoidance, logical understanding, ....

Amicalement,

-- 
Pierre Weis

INRIA, Projet Cristal, http://pauillac.inria.fr/~weis



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

* Re: Syntax for label, NEW PROPOSAL
  2000-03-16  2:55     ` Jacques Garrigue
@ 2000-03-17 15:13       ` Pierre Weis
  2000-03-17 17:33         ` Wolfram Kahl
  2000-03-18 11:59         ` Jacques Garrigue
  2000-03-21 16:51       ` Pascal Brisset
  1 sibling, 2 replies; 33+ messages in thread
From: Pierre Weis @ 2000-03-17 15:13 UTC (permalink / raw)
  To: Jacques Garrigue; +Cc: caml-list

> > Thus, I would prefer to discuss deeper and more semantic problems:
> > 
> > -- Problem1: labels can be reserved keywords. This is questionable
> > and it has been strongly criticised by some Caml users, especially when
> > reading in the code the awful sequence fun:begin fun ...
> 
> Well, maybe just because I've grown used to it, I do not find it awful
> at all.

At least more verbose than (fun ) or f (if the function is named as I
would recommend to any programmer that is fond of readability).

> The rationale behind allowing the use of keywords as labels is that
> there are lots of keywords in Caml, and many of them are good
> candidates for labels. Not allowing them makes often choice more
> difficult, or forces to use longer names.

The problem is that we have just a few rule for the Caml syntax, and
this violates this elementary one:

``In Caml, keywords are RESERVED identifiers''

Following this rule, we cannot use keywords as identifiers, even if it
would be very convenient ones such as ``val'' and, even if there is no
syntactic ambiguity, ``val'' is not allowed in patterns.

> This would mean:
> 
> fun -> func

Could also consider fn

[...]

> Beware however that label changes are inherently dangerous: you often
> realize afterwards that a choice was not so good, and I really hoped
> that we could definitively fix the standard library labels in 3.00.
> 
> > -- Problem2: labels that spread all over the standard libraries, even
> > when they do not add any good.
> 
> Well, the current policy (as defined in the manual) is to put labels
> on at least all arguments but one (with some very special exceptions
> like printf). This is necessary to allow commuting between arguments,
> which is also an important theme of labels. As such I would not say
> that they do not do any good.

I'm afraid I don't agree with you: commuting between arguments is not
worth the extra burden of having labels, I'm not sure it is even
desirable. I think that when arguments of a function are not always
passed in the same order the readibility of the code is jeopardized.

> > I would cite:
> > 
> >    * the labels completely redundant with the types
> >      (E.g. char:char in the type of String.contains or String.index)
> 
> Following the above policy, I would say that these are not ideal
> choices, but then what other possibility is there?

Remove the label.

> Moreover, even if this label is redundant in types, it is not
> necessarilly so in code.

May be not redundant, we can say useless or nocive ?

> >    * undesired labels: in many cases I don't want to have labels just
> >      because I don't want to remember their names. (E.g., I very often
> >      mispell the label acc since I've always used accu to name an
> >      accumulator; furthermore, when I do not mispell this label, I feel
> >      acc:accu extremely verbose). Also because labels are verbose at
> >      application.
> 
> Isn't there a classic mode for that?
> If you think that labels are verbose, you can use it, and it even
> provides some partial support for label checking when you want it.

If we must always use the no modern option of the compiler, I think
there is some kind of drawback in the label world...

> I suppose we should have a precise idea of what labels are there for.
> For me they are a systematic mechanism, and the fact we allow to have
> no label on one argument in function types is just a little comfort,
> particularly useful when working with functionals.

Wao! So, the normal evolution would be to have labels as ``a
systematic mechanism'' ? I'm afraid this is really a dogmatic view,
and may be some Caml users will object ...

> >    * labels that prevent you to use comfortably your traditional functions.
> >      This is particularly evident for the List.map or List.fold_right
> >      higher-order functionals.
> > 
> > This last point is a real problem. Compare the usual way of using
> > functionals to define the sum of the elements of a list:
> > 
> > # let sum l = List.fold_right ( + ) l 0;;
> > val sum : int list -> int = <fun>
> 
> Whether you consider this readable or not is a question of taste.  I
> personally believe that you need quite a background in HO formalisms
> to understand the above. But of course most current Caml users have
> this background.

No, this is not a question of taste, since whatever readable you
consider this definition, it is still more readable, easier to
understand and easier to write than the labelized version:

let sum = List.fold_right fun:begin fun x acc:y -> x + y end acc:0;;

> > # let sum l = List.fold_right ( + ) l 0;;
> >                               ^^^^^
> > This expression has type int -> int -> int but is here used with type 'a list
> 
> Aargh, that's right, error messages are a pain. I believe I worked a
> lot making them informative, but there are still difficult situations.
> I'll try to improve this.
> 
> Remark however that, in modern mode, it is already strange to have an
> application with no labels at all...

Aargh, is that the future of Caml programming, as the ``modern'' flag
tends to suggest ? :(

> > 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 = List.fold_right fun:begin fun x acc:y -> x + y end acc:0;;
> > val sum : 'a -> int list -> int = <fun>
> 
> You do not have to use begin .. end everywhere.
> I do personally write:
> # let sum = List.fold_right acc:0 fun:(fun x :acc -> x + acc);;

Hum... I do personnaly got this idea by reading the code from the files
editor.ml, fileselect.ml, jg_multibox.ml, searchid.ml, ..., in the
directory otherlibs/labltk/browser/ of the compiler distribution.

> Remark that here you didn't care about whether acc is the first or
> second argument of the passed function, just because (+) is
> commutative. However, in general functions are not commutative, and I
> always have to think a lot when using List.fold_left or
> List.fold_right without labels, just because I may write wrong code
> without the type checker telling me anything.

Yes functions in general are not commutative, but I cannot imagine how
labels may prevent you from thinking when using List.fold_right...

> > For all these reasons, I would suggest to carefully use labels into
> > the standard libraries: 
> > 
> > -- remove labels from higher-order functional
> > -- remove redundant labels: when no ambiguity can occur you need not
> >    to add a label.
> > -- use labels when typechecking ambiguity is evident (for instance
> > when there are two or more parameters with the same type).
> > 
> > Labels must enforce readability of code or help documenting the
> > libraries, it should not be an extra burden to the programmer and a
> > way of offuscating code.
> 
> This seems to boil down to using labels for documentation purposes
> only. If you reduce them to such an extent, I'm afraid they will not
> do very much for code readability anymore. And I stated above, you get
> typechecking holes in functionals.

Do you suggest the current version of Objective Caml comes with a
typechecker that gives you ``holes in functionals'' ?

> By the way, I do not see how labels can help obfuscating code.

In several ways, I think labels may help obfuscating code, for
instance if they allows you to treat the arguments of functions as a
set instead of an ordered list: if arguments are never passed in the
same order, the code is much harder to read, since it is much more
difficult to remember the profile of functions (unless you remember
the set of labels associated with the function's profile AND the types
associated with the labels).

> What you are probably intending to say is that they make more
> difficult to write some combinator-based HO-style code. Does it mean
> we should have a version of the List module without labels for such
> uses?

You said so.

> > Evidently, as any other extension, labels must not offuscate the
> > overall picture, that is they must not clobber the semantics, nor add
> > extra exceptional cases to the few general rules we have for the
> > syntax and semantics of Caml.
> > 
> > In this respect, optional labelled arguments might also be discussed,
> > particularly for the following facts:
> > 
> > -- syntactically identical patterns and expressions now may have
> > incompatible types:
> >    # let f ?style:x _ = x;;
> >    val f : ?style:'a -> 'b -> 'a option = <fun>
> > 
> >    As a pattern on the left-hand side x has type 'a, while as an
> >    expression on the right hand side it has type 'a option
> 
> Well, internally the left-hand side is also 'a option, but option is
> abbreviated because it is redundant. I do not think people want to see
> the left-hand side option, but maybe this technical part should be
> made more explicit in the manual.

This is not the problem: the problem is this is an exception to a simple
and intuitive rule of the Caml static semantics:

``In Caml, variables bound by patterns have a unique type''

Corollary: when used in expressions, variables bound by patterns have
the same type as their pattern type.

> Conversion from 'a to 'a option is done at application. I do not
> think there is any semantical problem here.

I do think there is a problem here, since once more this violates a
simple rule of Caml semantics:

``In Caml, there is no implicit coercions.''

Admittedly, this is a burden for arithmetic operations, but this is
also extraordinarily simple to explain and understand.

> > -- some expressions can be only written as arguments in an application
> >    context:
> >    # let f ?style:x g = ?style:x;;
> 
> ?style:x is not an expression: labels are part of the application
> node, not of the arguments.

I know that and find it counter-intuitive, since once more it breaks
a very simple and intuitive rule of Caml:

``Caml expressions possess the sub-term property: sub-expressions are
also expressions''

(Hence, if e1 e2 is an application, then e1 and e2 are valid expressions).

> > -- the simple addition of a default value to an optional argument may
> >    trigger a typechecking error:
> > 
> >    # let f ?(style:x) g = g ?style:x;;
> >    val f : ?style:'a -> (?style:'a -> 'b) -> 'b = <fun>
> > 
> >    # let f ?(style:x = 1) g = g ?style:x;;
> >    This expression has type int but is here used with type 'a option
> 
> That one is more serious. This is not a "simple addition". Default
> values unroll some syntactic sugar, changing the type of the
> argument.

Once more, I know those technical reasons, but I do not get for
granted that technical reasons are a valid answer to violations of the
simplicity and intuitive understanding of the language. If technical
reasons cannot handle some nice feature but force you to turn this
feature into a bad hack, then you must choose not to incorporate the
feature since it is no more a nice feature.

> Whether this is a good idea to have such syntactic sugar in
> the language is an interesting question. However I believe it provides
> some real comfort.

You must carefully balance this comfort with the extra cost in terms
of complexity and exceptions to the usual semantics (either static or
dynamic) ...

> > Do not forget the design decision that has always been used before in
> > the development of Caml: interesting but not universal extensions to
> > the language must carefully be kept orthogonal to the core language
> > and its libraries. This has been successfully achieved for the
> > important addition of modules (that do not prevent the users from
> > using the old interface-implementation view of modules) as well as for
> > the objects system addition that has been also maintained orthogonal
> > to the rest of the language (in particular the standard library has
> > never been ``objectified''). I don't know of any reason why labels
> > cannot follow the same safe guidelines.
> 
> I just believed that it was agreed that labelizing the standard
> library was a progress.

It can be a progress if labels are introduced when they avoid
some (common) errors or ambiguities.

> A first approach would be to say that one can always use classic mode.
> Modern is not pedantic, it is just another typing discipline.
> But this would endanger the unicity of the language, so this cannot be
> an universal answer.

You're right, so we still have to think hard on the subject, and try
not to violate the few intuitive rules we have in Caml.

> Now, the problem we are talking about seems to boil down to higher
> order functions in modern mode. And more particularly List.fold_left
> and List.fold_right, since these are about the only two functions
> where the argument itself has labels.
> 
> It would cost nothing to add 4 more unlabelled functions to the List
> module.

And do the same for modules List and Hashtbl and Array and Set and
Map, ... this will cost a bit I think.

[...]

> One may even insist that fun: is superfluous.
> Then it would probably be better to have another List module without
> labels at all. Again, this is pretty easy to do, and does not incur
> any code blow in general.
>
> Or do you think that the problem is deeper, and that labels are
> breaking the foundations of the language ?

In my opinion some fundamental rules are broken in the current
situation of the labels addition, and I think we should try to
overcome this drawback to let the language simple to explain and use.

Amicalement,
-- 
Pierre Weis

INRIA, Projet Cristal, http://pauillac.inria.fr/~weis



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

* Re: Syntax for label, NEW PROPOSAL
  2000-03-17  8:30       ` Pierre Weis
@ 2000-03-17 14:05         ` Jacques Garrigue
  2000-03-17 16:08           ` Pierre Weis
  0 siblings, 1 reply; 33+ messages in thread
From: Jacques Garrigue @ 2000-03-17 14:05 UTC (permalink / raw)
  To: Pierre.Weis; +Cc: remi.vanicat, caml-list

> > also i do want the fun: label (you may change the name, but a label
> > here is useful) to be able to write 
> > 
> > let sum l = List.fold_right acc:0
> >               fun:(fun long multi line function  definition here)
> > 
> > but i agreed that the acc label (in fun x acc:y -> x + y) is a pain,
> > because he forbid the use of usual function here 
> 
> I don't think this ``long multi line function  definition here'' is a
> really good argument. Several years ago, I thought the same, so that I
> defined *_on version of list functionals with list in the first place
> instead of at the end; for instance, I could write:
> 
> map_on l (fun x -> long multi line function)
> 
> Now I'm sure this is not the right solution to a real problem: the
> elegant way to deal with that is to name the function using a let.
> 
> let eta_expand x =
>  ... in
> 
> map eta_expand l.
> 
> Several arguments are in favor of a let binding:
> 
> - we still have only one functional and one way to call it
> - we have no unreadable long inline function definitions
> - the name we give to the function helps to understand its semantics
> - we can use the same construction in case of more complex function
> even in case of recursive function, where the fun x -> construct is
> hopeless (to solve this problem a ``fun rec'' construct have been
> proposed once, but the let rec way is much simpler, regular and
> elegant!)
> - the let way is a general solution to the general problem of long
> multi-line expressions in every construct of the language, including
> arithmetic operations.

There may indeed be good reasons for let-binding.
However, if you look at the sources of ocaml, you will see that in
many, many places such functions are defined inline without
let-binding. I see two reasons for that:
* you often don't want to think of a name for such a function
  (most of them are just 2 or 3 line long)
* it forces you to move the code around in a way that is not
  necessarily very natural. It's a bit like RPN: first define a
  function, then apply a functional to it.
  (We could of course ressucite the where clause :-)

More generally, my experience is that more freedom in the way to
layout them increases the use of functionals. After all there are many
ways to see the same function, different logical understanding of its
meaning. And the fact you can use all these ways with the same function
avoids confusion.

Why should we decide that one way is right, and others are wrong?

Jacques



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

* Re: Syntax for label, NEW PROPOSAL
  2000-03-16  8:50     ` Pascal Brisset
@ 2000-03-17 11:15       ` Sven LUTHER
  0 siblings, 0 replies; 33+ messages in thread
From: Sven LUTHER @ 2000-03-17 11:15 UTC (permalink / raw)
  To: Pascal Brisset; +Cc: Pierre Weis, Jacques Garrigue, caml-list

On Thu, Mar 16, 2000 at 09:50:49AM +0100, Pascal Brisset wrote:
> Pierre Weis writes:
> > For all these reasons, I would suggest to carefully use labels into
> > the standard libraries: 
> > 
> > -- remove labels from higher-order functional
> > -- remove redundant labels: when no ambiguity can occur you need not
> >    to add a label.
> > -- use labels when typechecking ambiguity is evident (for instance
> > when there are two or more parameters with the same type).
> 
>  Would it be possible to organize a vote for removing all labels from the
> standard library ?

I thought that all labels added to the standard library are only there because
they can be added in a totally transparent way of doing things, because a
labeled function can be used unlabeled if you like it. 

Friendly,

Sven LUTHER



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

* Re: Syntax for label, NEW PROPOSAL
  2000-03-15 17:04     ` John Prevost
@ 2000-03-17 10:11       ` Jacques Garrigue
  0 siblings, 0 replies; 33+ messages in thread
From: Jacques Garrigue @ 2000-03-17 10:11 UTC (permalink / raw)
  To: prevost; +Cc: caml-list

Hi John,

> I think this could be made sane by a reform of how the optional
> arguments work.  There are a couple of interesting possibilities:
> 
> # let f ?style:x _ = x;;
> - val f : ?style:('a option) -> 'b -> 'a option
> 
> # let f (style:x : 'a option) _ = x
> - val f : style:('a option) -> 'b -> 'a option

Bingo, you've just found how it's implemented!
Omitting the option constructor for optional arguments is just
a small comfort. This can be pretty important when you have 10 or 20
optional arguments in the same function.

By the way, having a default case for a non-optional argument was
legal in O'Labl. I just didn't include it in O'Caml because I thought
I would be more confusing than useful.

> The first is dirty because there are two kinds of special arguments
> (optional and non-optional).  The second because it gets into the type
> system.  I think the second must lose, since "knowing" that something
> is an option type is complex.

In fact the distinction between optional and non-optional arguments is
useful, because it allows a nice interaction between classic and
modern mode.  Optional ones behave the same in both modes, only
non-optional ones behave differently.

[..]
> Of course, this is all radically different from O'Labl, so it will
> never happen.

I do not intend to be so exclusive...
In fact there are even a number of differences between ocaml 2.99 and
olabl, and some from you.
The only point is that O'Labl has been around for a while, and we have
had the time to test in practice that this model works, and is not
difficult to grasp. Another model would take lots of time testing
again.

Best regards,

Jacques



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

* Re: Syntax for label, NEW PROPOSAL
  2000-03-15 19:11     ` Remi VANICAT
@ 2000-03-17  8:30       ` Pierre Weis
  2000-03-17 14:05         ` Jacques Garrigue
  0 siblings, 1 reply; 33+ messages in thread
From: Pierre Weis @ 2000-03-17  8:30 UTC (permalink / raw)
  To: Remi VANICAT; +Cc: caml-list

> > # let sum l = List.fold_right fun:begin fun x acc:y -> x + y end acc:0;;
> > val sum : 'a -> int list -> int = <fun>
> 
> here, i prefer to use parenthesis as :
> 
> let sum l = List.fold_right fun:(fun x acc:y -> x + y) acc:0;;
> 
> it's more readable

:)

Me too, ``here, i prefer to use parenthesis as :'' List.fold_right ( + ) 0

> also i do want the fun: label (you may change the name, but a label
> here is useful) to be able to write 
> 
> let sum l = List.fold_right acc:0
>               fun:(fun long multi line function  definition here)
> 
> but i agreed that the acc label (in fun x acc:y -> x + y) is a pain,
> because he forbid the use of usual function here 

I don't think this ``long multi line function  definition here'' is a
really good argument. Several years ago, I thought the same, so that I
defined *_on version of list functionals with list in the first place
instead of at the end; for instance, I could write:

map_on l (fun x -> long multi line function)

Now I'm sure this is not the right solution to a real problem: the
elegant way to deal with that is to name the function using a let.

let eta_expand x =
 ... in

map eta_expand l.

Several arguments are in favor of a let binding:

- we still have only one functional and one way to call it
- we have no unreadable long inline function definitions
- the name we give to the function helps to understand its semantics
- we can use the same construction in case of more complex function
even in case of recursive function, where the fun x -> construct is
hopeless (to solve this problem a ``fun rec'' construct have been
proposed once, but the let rec way is much simpler, regular and
elegant!)
- the let way is a general solution to the general problem of long
multi-line expressions in every construct of the language, including
arithmetic operations.

Best regards,
-- 
Pierre Weis

INRIA, Projet Cristal, http://pauillac.inria.fr/~weis



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

* Re: Syntax for label, NEW PROPOSAL
  2000-03-15 15:26     ` Sven LUTHER
@ 2000-03-17  7:44       ` Pierre Weis
  0 siblings, 0 replies; 33+ messages in thread
From: Pierre Weis @ 2000-03-17  7:44 UTC (permalink / raw)
  To: luther; +Cc: caml-list

> >         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
> 
> Is this not because the new definition of List.fold_right wants the list
> first, and then only the function ?

Unfortunately no: List.fold_right expects its arguments as usual:

latour:~ ocaml -modern
        Objective Caml version 2.99+10

# List.fold_right;;
- : fun:('a -> acc:'b -> 'b) -> 'a list -> acc:'b -> 'b = <fun>

Friendly,
-- 
Pierre Weis

INRIA, Projet Cristal, http://pauillac.inria.fr/~weis



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

* Re: Syntax for label, NEW PROPOSAL
  2000-03-15 13:58   ` Pierre Weis
                       ` (5 preceding siblings ...)
  2000-03-16  2:55     ` Jacques Garrigue
@ 2000-03-16  8:50     ` Pascal Brisset
  2000-03-17 11:15       ` Sven LUTHER
  6 siblings, 1 reply; 33+ messages in thread
From: Pascal Brisset @ 2000-03-16  8:50 UTC (permalink / raw)
  To: Pierre Weis; +Cc: Jacques Garrigue, caml-list

Pierre Weis writes:
> For all these reasons, I would suggest to carefully use labels into
> the standard libraries: 
> 
> -- remove labels from higher-order functional
> -- remove redundant labels: when no ambiguity can occur you need not
>    to add a label.
> -- use labels when typechecking ambiguity is evident (for instance
> when there are two or more parameters with the same type).

 Would it be possible to organize a vote for removing all labels from the
standard library ?

--Pascal Brisset



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

* Re: Syntax for label, NEW PROPOSAL
  2000-03-15 13:58   ` Pierre Weis
                       ` (4 preceding siblings ...)
  2000-03-15 21:30     ` John Max Skaller
@ 2000-03-16  2:55     ` Jacques Garrigue
  2000-03-17 15:13       ` Pierre Weis
  2000-03-21 16:51       ` Pascal Brisset
  2000-03-16  8:50     ` Pascal Brisset
  6 siblings, 2 replies; 33+ messages in thread
From: Jacques Garrigue @ 2000-03-16  2:55 UTC (permalink / raw)
  To: Pierre.Weis; +Cc: caml-list

From: Pierre Weis <Pierre.Weis@inria.fr>

> > *** Proposal
> > 
> > Objective Caml 3.00 is not yet released, and I believe we can still
> > have modifications on this point.
> 
> Yes, you're perfectly right, we can still modify several points.
> However, I think there are many other points that are more important
> than the choice of ``%'' instead of ``:'', which is only cosmetic
> after all.

Well, I think I've got enough reactions to rule out %.
These are of the small details of syntax you want to check for
sure. And that are very hard to change afterwards.

> Thus, I would prefer to discuss deeper and more semantic problems:
> 
> -- Problem1: labels can be reserved keywords. This is questionable
> and it has been strongly criticised by some Caml users, especially when
> reading in the code the awful sequence fun:begin fun ...

Well, maybe just because I've grown used to it, I do not find it awful
at all.

The rationale behind allowing the use of keywords as labels is that
there are lots of keywords in Caml, and many of them are good
candidates for labels. Not allowing them makes often choice more
difficult, or forces to use longer names.

On the other hand, their particular use in the standard library may be
another subject of discussion.
If I remember correctly, there are only 2 keywords used as label in
the standard library: `fun' (in functionals) and `to' (in output
functions).

If we want to remove them, I think a good policy would be to change
the "default" length of labels from 3 to 4. Since many Caml keywords
are of length 3, we avoid lots of conflicts!

This would mean:

fun -> func
to -> chan or dest
acc -> accu             :-)
src -> orig             (src meant a lot to a now disappeared company)
dst -> dest             (maybe because I'm French, dst reminds me of something)
buf -> buff             ???
...
Still it seems reasonable to keep pos: and len:.

Beware however that label changes are inherently dangerous: you often
realize afterwards that a choice was not so good, and I really hoped
that we could definitively fix the standard library labels in 3.00.

> -- Problem2: labels that spread all over the standard libraries, even
> when they do not add any good.

Well, the current policy (as defined in the manual) is to put labels
on at least all arguments but one (with some very special exceptions
like printf). This is necessary to allow commuting between arguments,
which is also an important theme of labels. As such I would not say
that they do not do any good.

> I would cite:
> 
>    * the labels completely redundant with the types
>      (E.g. char:char in the type of String.contains or String.index)

Following the above policy, I would say that these are not ideal
choices, but then what other possibility is there?

Moreover, even if this label is redundant in types, it is not
necessarilly so in code.

>    * undesired labels: in many cases I don't want to have labels just
>      because I don't want to remember their names. (E.g., I very often
>      mispell the label acc since I've always used accu to name an
>      accumulator; furthermore, when I do not mispell this label, I feel
>      acc:accu extremely verbose). Also because labels are verbose at
>      application.

Isn't there a classic mode for that?
If you think that labels are verbose, you can use it, and it even
provides some partial support for label checking when you want it.

I suppose we should have a precise idea of what labels are there for.
For me they are a systematic mechanism, and the fact we allow to have
no label on one argument in function types is just a little comfort,
particularly useful when working with functionals.

>    * labels that prevent you to use comfortably your traditional functions.
>      This is particularly evident for the List.map or List.fold_right
>      higher-order functionals.
> 
> This last point is a real problem. Compare the usual way of using
> functionals to define the sum of the elements of a list:
> 
> # let sum l = List.fold_right ( + ) l 0;;
> val sum : int list -> int = <fun>

Whether you consider this readable or not is a question of taste.  I
personally believe that you need quite a background in HO formalisms
to understand the above. But of course most current Caml users have
this background.

> # let sum l = List.fold_right ( + ) l 0;;
>                               ^^^^^
> This expression has type int -> int -> int but is here used with type 'a list

Aargh, that's right, error messages are a pain. I believe I worked a
lot making them informative, but there are still difficult situations.
I'll try to improve this.

Remark however that, in modern mode, it is already strange to have an
application with no labels at all...

> 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 = List.fold_right fun:begin fun x acc:y -> x + y end acc:0;;
> val sum : 'a -> int list -> int = <fun>

You do not have to use begin .. end everywhere.
I do personally write:
# let sum = List.fold_right acc:0 fun:(fun x :acc -> x + acc);;

Remark that here you didn't care about whether acc is the first or
second argument of the passed function, just because (+) is
commutative. However, in general functions are not commutative, and I
always have to think a lot when using List.fold_left or
List.fold_right without labels, just because I may write wrong code
without the type checker telling me anything.

> For all these reasons, I would suggest to carefully use labels into
> the standard libraries: 
> 
> -- remove labels from higher-order functional
> -- remove redundant labels: when no ambiguity can occur you need not
>    to add a label.
> -- use labels when typechecking ambiguity is evident (for instance
> when there are two or more parameters with the same type).
> 
> Labels must enforce readability of code or help documenting the
> libraries, it should not be an extra burden to the programmer and a
> way of offuscating code.

This seems to boil down to using labels for documentation purposes
only. If you reduce them to such an extent, I'm afraid they will not
do very much for code readability anymore. And I stated above, you get
typechecking holes in functionals.

By the way, I do not see how labels can help obfuscating code.
What you are probably intending to say is that they make more
difficult to write some combinator-based HO-style code. Does it mean
we should have a version of the List module without labels for such
uses?

> Evidently, as any other extension, labels must not offuscate the
> overall picture, that is they must not clobber the semantics, nor add
> extra exceptional cases to the few general rules we have for the
> syntax and semantics of Caml.
> 
> In this respect, optional labelled arguments might also be discussed,
> particularly for the following facts:
> 
> -- syntactically identical patterns and expressions now may have
> incompatible types:
>    # let f ?style:x _ = x;;
>    val f : ?style:'a -> 'b -> 'a option = <fun>
> 
>    As a pattern on the left-hand side x has type 'a, while as an
>    expression on the right hand side it has type 'a option

Well, internally the left-hand side is also 'a option, but option is
abbreviated because it is redundant. I do not think people want to see
the left-hand side option, but maybe this technical part should be
made more explicit in the manual.

Conversion from 'a to 'a option is done at application. I do not
think there is any semantical problem here.

> -- some expressions can be only written as arguments in an application
>    context:
>    # let f ?style:x g = ?style:x;;

?style:x is not an expression: labels are part of the application
node, not of the arguments.

> -- the simple addition of a default value to an optional argument may
>    trigger a typechecking error:
> 
>    # let f ?(style:x) g = g ?style:x;;
>    val f : ?style:'a -> (?style:'a -> 'b) -> 'b = <fun>
> 
>    # let f ?(style:x = 1) g = g ?style:x;;
>    This expression has type int but is here used with type 'a option

That one is more serious. This is not a "simple addition". Default
values unroll some syntactic sugar, changing the type of the
argument. Whether this is a good idea to have such syntactic sugar in
the language is an interesting question. However I believe it provides
some real comfort.

> Do not forget the design decision that has always been used before in
> the development of Caml: interesting but not universal extensions to
> the language must carefully be kept orthogonal to the core language
> and its libraries. This has been successfully achieved for the
> important addition of modules (that do not prevent the users from
> using the old interface-implementation view of modules) as well as for
> the objects system addition that has been also maintained orthogonal
> to the rest of the language (in particular the standard library has
> never been ``objectified''). I don't know of any reason why labels
> cannot follow the same safe guidelines.

I just believed that it was agreed that labelizing the standard
library was a progress. Of course this also means that you do not stay
100% compatible in modern mode. Still, there are no optional arguments
in the standard library, meaning that you stay 100% compatible in classic
mode.

> There are also people around that would like to keep Caml a true
> functional language, where usage of higer order functions is easy and
> natural.  We have to be careful not to lose what is the actual
> strength of the language.

Of course, I agree with that.

A first approach would be to say that one can always use classic mode.
Modern is not pedantic, it is just another typing discipline.
But this would endanger the unicity of the language, so this cannot be
an universal answer.

Now, the problem we are talking about seems to boil down to higher
order functions in modern mode. And more particularly List.fold_left
and List.fold_right, since these are about the only two functions
where the argument itself has labels.

It would cost nothing to add 4 more unlabelled functions to the List
module.

val foldl : fun:('a -> 'b -> 'a) -> 'a -> 'b list -> 'a
val foldr : fun:('a -> 'b -> 'b) -> 'a list -> 'b -> 'b
val foldl2 : fun:('a -> 'b -> 'c -> 'a) -> 'a -> 'b list -> 'c list -> 'a
val foldr2 : fun:('a -> 'b -> 'c -> 'c) -> 'a list -> 'b list -> 'c -> 'c

This way you can write

# let sum l = List.foldr fun:(+) l 0

The same additions would also apply to the Array module.
There is also the problem of iteri and mapi, where i: may be not
that important in practice (even when working on an array of integers,
I wouldn't expect anybody to make such a mistake).

val iteri : fun:(i:int -> 'a -> unit) -> 'a array -> unit
val mapi : fun:(i:int -> 'a -> 'b) -> 'a array -> 'b array

One may even insist that fun: is superfluous.
Then it would probably be better to have another List module without
labels at all. Again, this is pretty easy to do, and does not incur
any code blow in general.

Or do you think that the problem is deeper, and that labels are
breaking the foundations of the language ?

Amicalement,

Jacques
---------------------------------------------------------------------------
Jacques Garrigue      Kyoto University     garrigue at kurims.kyoto-u.ac.jp
		<A HREF=http://wwwfun.kurims.kyoto-u.ac.jp/~garrigue/>JG</A>



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

* Re: Syntax for label, NEW PROPOSAL
  2000-03-15  6:58   ` Christophe Raffalli
@ 2000-03-15 21:54     ` Julian Assange
  0 siblings, 0 replies; 33+ messages in thread
From: Julian Assange @ 2000-03-15 21:54 UTC (permalink / raw)
  To: Christophe Raffalli; +Cc: Jacques Garrigue, dsyme, caml-list, proff

Christophe Raffalli <Christophe.Raffalli@univ-savoie.fr> writes:

> Jacques Garrigue wrote:
> > 
> > In this case, I suppose we should read `%' as `is'.
> > 
> 
> >         Objective Caml version 2.99+10
> > 
> > # List.map;;
> > - : fun%('a -> 'b) -> 'a list -> 'b list = <fun>
> > # List.map [1;2;3] fun%succ;;
> > - : int list = [2; 3; 4]
> > # let sub ?(%pos = 0) ?%len s =
> >     let len = match len with Some x -> x | None -> String.length s - pos in
> >     String.sub %pos %len s;;
> > val sub : ?pos%int -> ?len%int -> string -> string = <fun>
> > 
> 
> I really do think that it looks better !

I don't. % is a heavy character, only '#' and '@' are worse. '-' would
be far better, although this might break existing code. The natural
meaning is closest to "-" and ":". There is no relation to '%' or '#'.

Cheers,
Julian.



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

* Re: Syntax for label, NEW PROPOSAL
  2000-03-15 13:58   ` Pierre Weis
                       ` (3 preceding siblings ...)
  2000-03-15 19:11     ` Remi VANICAT
@ 2000-03-15 21:30     ` John Max Skaller
  2000-03-16  2:55     ` Jacques Garrigue
  2000-03-16  8:50     ` Pascal Brisset
  6 siblings, 0 replies; 33+ messages in thread
From: John Max Skaller @ 2000-03-15 21:30 UTC (permalink / raw)
  To: Pierre Weis; +Cc: Jacques Garrigue, caml-list

Pierre Weis wrote:

> 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!

	This is not a 'minor' point, but the most significant obstacle
in the way of adoption of languages (like ocaml) that do a lot of type
inference. Incomprehensible -- indeed plain wrong -- error messages
crop up regularly with ocaml, and vie with the kind of gibberish
errors instantiating C++ templates usually give for 
'most obscuficated error message' competition :-)

	The recent addition of better error messages in the case
of missing cases of matches has been a _major_ improvement IMHO:
it has already saved me significant time; since I often enhance
the set of cases of a variant, and need to chase down every
match and update it.

	I'm not using -modern mode and the main reason is the scary
error messages. Even the polymorphic variants are scary, since one
looses the ability to 'spell check' variant tags. I actually tried
to take a fairly large, fundamental, type in Vyper (the type of most
language terms and runtime values) and use polymorphic variants
to classify them (the classes overlap, which ordinary variants
cannot handle), and gave up, because I couldn't understand the
error messages.

	Recent discussions in the Python types-SIG concerning
type inference showed a strong indication (mainly from ex-ML 
users) NOT to use any kind of type inference that could lead
to incomprehensible error messages.

	I personally use errors to drive development.
I expect a compiler to tell me the line that next needs editing.
Ocaml is fairly good here now, but I still cringe in fear
when i get too incompatible object types and pages of
method signatures the compiler claims are different.

Why can't it tell me the differences more often?
I does well sometimes telling me that one sig has a method the
other lacks. 

-- 
John (Max) Skaller, mailto:skaller@maxtal.com.au
10/1 Toxteth Rd Glebe NSW 2037 Australia voice: 61-2-9660-0850
checkout Vyper http://Vyper.sourceforge.net
download Interscript http://Interscript.sourceforge.net



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

* Re: Syntax for label, NEW PROPOSAL
  2000-03-15 13:58   ` Pierre Weis
                       ` (2 preceding siblings ...)
  2000-03-15 17:06     ` Markus Mottl
@ 2000-03-15 19:11     ` Remi VANICAT
  2000-03-17  8:30       ` Pierre Weis
  2000-03-15 21:30     ` John Max Skaller
                       ` (2 subsequent siblings)
  6 siblings, 1 reply; 33+ messages in thread
From: Remi VANICAT @ 2000-03-15 19:11 UTC (permalink / raw)
  To: caml-list

Pierre Weis <Pierre.Weis@inria.fr> writes:

> $ 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>

here, i prefer to use parenthesis as :

let sum l = List.fold_right fun:(fun x acc:y -> x + y) acc:0;;

it's more readable

also i do want the fun: label (you may change the name, but a label
here is useful) to be able to write 

let sum l = List.fold_right acc:0
              fun:(fun long multi line function  definition here)

but i agreed that the acc label (in fun x acc:y -> x + y) is a pain,
because he forbid the use of usual function here 

-- 
Rémi Vanicat
vanicat@labri.u-bordeaux.fr
http://dept-info.labri.u-bordeaux.fr/~vanicat



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

* Re: Syntax for label, NEW PROPOSAL
  2000-03-15 13:58   ` Pierre Weis
  2000-03-15 15:26     ` Sven LUTHER
  2000-03-15 17:04     ` John Prevost
@ 2000-03-15 17:06     ` Markus Mottl
  2000-03-15 19:11     ` Remi VANICAT
                       ` (3 subsequent siblings)
  6 siblings, 0 replies; 33+ messages in thread
From: Markus Mottl @ 2000-03-15 17:06 UTC (permalink / raw)
  To: Pierre Weis; +Cc: OCAML

> -- Problem1: labels can be reserved keywords. This is questionable
> and it has been strongly criticised by some Caml users, especially when
> reading in the code the awful sequence fun:begin fun ...

Although this is a bit off-topic, I would also like to point out some
identifier problems with polymorphic variants as they are implemented at
the moment (maybe this could also be changed before the major release):

First of all, the initial quote ` can be followed by whitespace - and
worse: by comments! I feel that this is really somewhat insane, even if
most users won't use polymorphic variants like this.

Secondly, I am not sure whether it is such a good idea to allow lowercase
initial letters. They can sometimes clash with keywords and here they
really do, because (see above) of they way they are parsed. This can lead
to syntax errors which will surely confuse beginners (and also confused me
once...). If parsing were changed, this wouldn't be a problem anymore, but
I think that the relation between normal variants and polymorphic ones
should stay evident - having to use capitals for the first letter with both
of them seems more regular to me.

> -- Problem2: labels that spread all over the standard libraries, even
> when they do not add any good. I would cite:
> 
>    * labels that prevent you to use comfortably your traditional functions.
>      This is particularly evident for the List.map or List.fold_right
>      higher-order functionals.

I fully agree - labels in higher order functions make their application
really a pain, especially if one wants to use curried functions. Being able
to just pass the name of functions as argument is one of the major
"features" of functional languages - it's probably not worse the extra type
checking information to lose it.

What concerns syntax: I would also rather prefer the version with ":"...

> Do not forget the design decision that has always been used before in
> the development of Caml: interesting but not universal extensions to
> the language must carefully be kept orthogonal to the core language
> and its libraries.

This is an aspect I particularly like about OCaml - one can try out new
styles of programming without being forced to use them throughout.

Regards,
Markus Mottl

-- 
Markus Mottl, mottl@miss.wu-wien.ac.at, http://miss.wu-wien.ac.at/~mottl



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

* Re: Syntax for label, NEW PROPOSAL
  2000-03-15 13:58   ` Pierre Weis
  2000-03-15 15:26     ` Sven LUTHER
@ 2000-03-15 17:04     ` John Prevost
  2000-03-17 10:11       ` Jacques Garrigue
  2000-03-15 17:06     ` Markus Mottl
                       ` (4 subsequent siblings)
  6 siblings, 1 reply; 33+ messages in thread
From: John Prevost @ 2000-03-15 17:04 UTC (permalink / raw)
  To: Pierre Weis; +Cc: Jacques Garrigue, caml-list

As usual, best most consistent idea is at the end.  Please forgive my
rambling.

Pierre Weis <Pierre.Weis@inria.fr> writes:

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

Whoa.  You can't just use fun:(+)??  There's a new acc label that's
used for folds?  I might have argued that fun: (or an alternative
which isn't a reserved word, which I would support) isn't so bad to
type.  But with the labeled argument to the argument of the HOF, this
is too much.

As for the other semantic badness (which I actually think is syntactic
badness to some degree) let's see what we can do:

> -- syntactically identical patterns and expressions now may have
> incompatible types:
>    # let f ?style:x _ = x;;
>    val f : ?style:'a -> 'b -> 'a option = <fun>
> 
>    As a pattern on the left-hand side x has type 'a, while as an
>    expression on the right hand side it has type 'a option

I think this could be made sane by a reform of how the optional
arguments work.  There are a couple of interesting possibilities:

# let f ?style:x _ = x;;
- val f : ?style:('a option) -> 'b -> 'a option

# let f (style:x : 'a option) _ = x
- val f : style:('a option) -> 'b -> 'a option

In the first case, the type of an optional labelled argument is always
an option.  (This makes sense in the context of what I'll say about
arguments with default values below.)

In the second case, any labelled argument with an option type becomes
an optional argument.  This has the disadvantage that it's impossible
to have a required option argument.  But one might argue that this
interpretation makes sense.

The first is dirty because there are two kinds of special arguments
(optional and non-optional).  The second because it gets into the type
system.  I think the second must lose, since "knowing" that something
is an option type is complex.

> -- some expressions can be only written as arguments in an application
>    context:
>    # let f ?style:x g = ?style:x;;
>                         ^
>    Syntax error
>    # let f ?style:x g = g ?style:x;;
>    val f : ?style:'a -> (?style:'a -> 'b) -> 'b = <fun>

I think you have to consider this sort of thing in the context of
"application involves labelled arguments now" and "this syntax is part
of application syntax and argument pattern syntax, not expressions or
arbitrary patterns".  It is a little dirty, but survivable.  A syntax
which made it more obvious what was going on might be nice.  I might write:

# let f ?style x g = ?style x
  Syntax error (label in non-application position)
# let f ?style x g = g ?style x
- val f : ?style 'a -> ?style ('a -> 'b) -> 'b

Now, ?label is a special token that changes the meaning of
application.  To some degree, like methods on objects.  ? would "bind"
more closely than application, because it's sort of like an infix.
But like #, it's more of a special effect on the following symbol.
This is why I write:

fooobj #method val

instead of

fooobj#method val

when I use the object syntax.

> -- the simple addition of a default value to an optional argument may
>    trigger a typechecking error:
>
>    # let f ?(style:x) g = g ?style:x;;
>    val f : ?style:'a -> (?style:'a -> 'b) -> 'b = <fun>
>
>    # let f ?(style:x = 1) g = g ?style:x;;
>    This expression has type int but is here used with type 'a option

Okay.  This is where my thought about changing the way this works
comes in.  From the point of view of the called function, an optional
argument with a default value is not optional at all!  From the
outside, of course, it is.  But what if we did it like this:

# let f ?(style:x) g = g ?style:x;;
- val f : ?style:('a option) -> ((?style:'a option) -> 'b) -> 'b = <fun>
# let f ?(style:x = 1) g = g ?style:x;;
                    -
  This expression has type int but here is used with type 'a option
# let f (style:x = 1) g = g ?style:x;;
                                   -
  This expression has type int but here is used with type 'a option
# let f ?(style:x = Some 1) g = g ?style:x;;
- val f : ?style:('a option) -> ((?style:'a option) -> 'b) -> 'b = <fun>
# let f (style:x = Some 1) g = g ?style:x;;
- val f : style:('a option) -> ((?style:'a option) -> 'b) -> 'b = <fun>


What's going on here?  The idea is that ? forms *always* require an
option as their value, and the bound value is always an option.  When
you pass a value with:

foo (?style:x)

foo must have type:

foo : (?style:'a option) -> 'b

Note that I have both optional and non-optional argument syntax above
with default values.  Above, we see how changes effect local code in
our function.  (As expected, if we cause the type of the bound
variable to change, the function breaks.  Otherwise it doesn't.)

What happens to people outside?  Well, if we switch from a ? form to a
non-? form, we're removing the implicit optionizing of the argument.
That is:

# let f (?style:x) = x;;
- val f : ?style:('a option) -> 'a option

# let f (style:x) = x;;
- val f : style:'a -> 'a

# let f (?style:x = Some 5) = x;;
- val f : ?style:('a option) -> 'a option

# let f (style:x = 5) = x;;
- val f : ?style:int -> int

Now, what's going on here?  The ? in the type relates only to whether
the argument is required or not.  When the argument is declared with
?, this must be an option!  When it is declared without ?, it may be
anything.


Come to think of it, this doesn't work either.  It makes everything
keep working as long as you keep the external type the same--but I
just realized that telling the difference between labels that should
be "optioned" and labels that shouldn't is hard.

Okay.  One last try.

What if we drop back one and say that there is only one kind of
labeled argument, written in this way (for my sake writing this):

# let f ?style x = x;;
- val f : ?style 'a -> 'a

Okay.  So how to optional arguments work?

# let f ?style x () = x;;
- val f : ?style 'a -> unit -> 'a
# f ();;
- : '_a option = None
# f ?style (Some 27) ();;
- : int option = Some 27

What's going on here?  Well--let's extend the syntax to cover default
arguments:

# let f (?style x = 5) () = x;;
- val f : ?style int -> int
# f ();;
- : int = 5

# let f (?style x = None) () = x;;
- val f : ?style 'a option -> 'a option
# f ();;
- : '_a option = None

and again, for reference:

# let f (?style x) () = x;;
- val f : ?style 'a -> 'a
# f ();;
- : '_a option = None

So how is this happening--what's the interpretation?





Oh shoot.  This doesn't work either.  I was going to suggest that you
can always leave out a label, and that the default value will be
substituted in, or if you didn't give a default, None will be
substituted in.  But that doesn't account for the top case above.  One
possibility is that it doesn't make sense to use a non-option default
value:

# let f (?style x = 5) () = x;;
- val f : ?style int -> int
* Warning: default value is not an option

# f ();;
  f ?style None ();;
           ----
  This expression has type 'a option but is here used with type int

# f ?style 3 ();;
- : int = 3

This is consistent, but sort of weird.  It does certainly provide a
fairly simple model of what optional arguments are, though.  The only
nastiness is that you need to do extra typing for each optional value
given.  I think this is a reasonable price to pay for sanity.

# let f (?style x = Some 5) () = x;;
- val f : ?style int option -> int option
# let g (?style Some x = Some 5) () = x
  Warning: this pattern-matching is not exhaustive.
  Here is an example of a value that is not matched:
  None
- val g : ?style int option -> int = <fun>
# f ();;
- : int option = Some 5
# g ();;
- : int = 5



Of course, this is all radically different from O'Labl, so it will
never happen.

John.



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

* Re: Syntax for label, NEW PROPOSAL
  2000-03-15 13:58   ` Pierre Weis
@ 2000-03-15 15:26     ` Sven LUTHER
  2000-03-17  7:44       ` Pierre Weis
  2000-03-15 17:04     ` John Prevost
                       ` (5 subsequent siblings)
  6 siblings, 1 reply; 33+ messages in thread
From: Sven LUTHER @ 2000-03-15 15:26 UTC (permalink / raw)
  To: Pierre Weis; +Cc: Jacques Garrigue, caml-list

On Wed, Mar 15, 2000 at 02:58:30PM +0100, Pierre Weis wrote:
> $ 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

Is this not because the new definition of List.fold_right wants the list
first, and then only the function ?

Friendly,

Sven LUTHER



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

* Re: Syntax for label, NEW PROPOSAL
  2000-03-15  3:15 ` Syntax for label, NEW PROPOSAL Jacques Garrigue
  2000-03-15  6:58   ` Christophe Raffalli
  2000-03-15 11:56   ` Wolfram Kahl
@ 2000-03-15 13:58   ` Pierre Weis
  2000-03-15 15:26     ` Sven LUTHER
                       ` (6 more replies)
  2 siblings, 7 replies; 33+ messages in thread
From: Pierre Weis @ 2000-03-15 13:58 UTC (permalink / raw)
  To: Jacques Garrigue; +Cc: caml-list

[Sorry, no french version for this long message]

Abstract:

A long answer to Jacques's proposal. I do not discuss syntax but
semantic issues of the label extension. My conclusion is to be very
careful in adding labels into the standard libraries, and also state
as a extremely desirable design guideline to keep the usage of higher
order functions as simple as possible.

> *** Proposal
> 
> Objective Caml 3.00 is not yet released, and I believe we can still
> have modifications on this point.

Yes, you're perfectly right, we can still modify several points.
However, I think there are many other points that are more important
than the choice of ``%'' instead of ``:'', which is only cosmetic
after all.

Thus, I would prefer to discuss deeper and more semantic problems:

-- Problem1: labels can be reserved keywords. This is questionable
and it has been strongly criticised by some Caml users, especially when
reading in the code the awful sequence fun:begin fun ...

-- Problem2: labels that spread all over the standard libraries, even
when they do not add any good. I would cite:

   * the labels completely redundant with the types
     (E.g. char:char in the type of String.contains or String.index)

   * undesired labels: in many cases I don't want to have labels just
     because I don't want to remember their names. (E.g., I very often
     mispell the label acc since I've always used accu to name an
     accumulator; furthermore, when I do not mispell this label, I feel
     acc:accu extremely verbose). Also because labels are verbose at
     application.

   * labels that prevent you to use comfortably your traditional functions.
     This is particularly evident for the List.map or List.fold_right
     higher-order functionals.

This last point is a real problem. Compare the usual way of using
functionals to define the sum of the elements of a list:

$ 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
-- remove redundant labels: when no ambiguity can occur you need not
   to add a label.
-- use labels when typechecking ambiguity is evident (for instance
when there are two or more parameters with the same type).

Labels must enforce readability of code or help documenting the
libraries, it should not be an extra burden to the programmer and a
way of offuscating code.

Evidently, as any other extension, labels must not offuscate the
overall picture, that is they must not clobber the semantics, nor add
extra exceptional cases to the few general rules we have for the
syntax and semantics of Caml.

In this respect, optional labelled arguments might also be discussed,
particularly for the following facts:

-- syntactically identical patterns and expressions now may have
incompatible types:
   # let f ?style:x _ = x;;
   val f : ?style:'a -> 'b -> 'a option = <fun>

   As a pattern on the left-hand side x has type 'a, while as an
   expression on the right hand side it has type 'a option

-- some expressions can be only written as arguments in an application
   context:
   # let f ?style:x g = ?style:x;;
                        ^
   Syntax error
   # let f ?style:x g = g ?style:x;;
   val f : ?style:'a -> (?style:'a -> 'b) -> 'b = <fun>

-- the simple addition of a default value to an optional argument may
   trigger a typechecking error:

   # let f ?(style:x) g = g ?style:x;;
   val f : ?style:'a -> (?style:'a -> 'b) -> 'b = <fun>

   # let f ?(style:x = 1) g = g ?style:x;;
   This expression has type int but is here used with type 'a option

Do not forget the design decision that has always been used before in
the development of Caml: interesting but not universal extensions to
the language must carefully be kept orthogonal to the core language
and its libraries. This has been successfully achieved for the
important addition of modules (that do not prevent the users from
using the old interface-implementation view of modules) as well as for
the objects system addition that has been also maintained orthogonal
to the rest of the language (in particular the standard library has
never been ``objectified''). I don't know of any reason why labels
cannot follow the same safe guidelines.

> Here is an alternative proposal, to use `%' in place of `:'. Labels
> are kept as a lexical entity. This still breaks some programs, since
> `%' was registered as infix, but this is not so bad.

> Con:
> * I still think that `:' looks better, particularly inside types.
> * On my keyboard I can type in `:' without pressing shift :-)
> * We will need some tool to convert existing code.

I think that % should be the infix integer modulo symbol.

> Do you think it would be better?

No.

> Are there people around who would rather keep `:' ?

Yes. However this is syntax and we have to consider semantics in the
first place.

There are also people around that would like to keep Caml a true
functional language, where usage of higer order functions is easy and
natural.  We have to be careful not to lose what is the actual
strength of the language.

-- 
Pierre Weis

INRIA, Projet Cristal, http://pauillac.inria.fr/~weis



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

* Re: Syntax for label, NEW PROPOSAL
  2000-03-15  3:15 ` Syntax for label, NEW PROPOSAL Jacques Garrigue
  2000-03-15  6:58   ` Christophe Raffalli
@ 2000-03-15 11:56   ` Wolfram Kahl
  2000-03-15 13:58   ` Pierre Weis
  2 siblings, 0 replies; 33+ messages in thread
From: Wolfram Kahl @ 2000-03-15 11:56 UTC (permalink / raw)
  To: caml-list; +Cc: garrigue


Jacques Garrigue <garrigue@kurims.kyoto-u.ac.jp> mentions ``%''
as possible alternative to ``:'' in the labelling syntax and writes:
 > 
 > In this case, I suppose we should read `%' as `is'.

I have difficulties with this --- after all
it is a ``percent'' glyph,
and more comfortable in a division context.

It would even be easier for me to read ``&'' as ``is'',
after all, ``&'' is ``et'',
so there is only one ``s'' missing to ``est''.    ;-)


For me, an additional argument for keeping ``:''
is that ``:'' is punctuation,
which I find appropriate for this use,
while ``%'' and ``#'' look more like infix operators.

I definitely prefer ``:''.


Concerning the use of ``:'' in type signatures,
I would write the blanks even if I didn't have to.
(I do so in Haskell.)


Regards,

Wolfram



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

* Re: Syntax for label, NEW PROPOSAL
  2000-03-15  3:15 ` Syntax for label, NEW PROPOSAL Jacques Garrigue
@ 2000-03-15  6:58   ` Christophe Raffalli
  2000-03-15 21:54     ` Julian Assange
  2000-03-15 11:56   ` Wolfram Kahl
  2000-03-15 13:58   ` Pierre Weis
  2 siblings, 1 reply; 33+ messages in thread
From: Christophe Raffalli @ 2000-03-15  6:58 UTC (permalink / raw)
  To: Jacques Garrigue; +Cc: dsyme, caml-list

Jacques Garrigue wrote:
> 
> In this case, I suppose we should read `%' as `is'.
> 

>         Objective Caml version 2.99+10
> 
> # List.map;;
> - : fun%('a -> 'b) -> 'a list -> 'b list = <fun>
> # List.map [1;2;3] fun%succ;;
> - : int list = [2; 3; 4]
> # let sub ?(%pos = 0) ?%len s =
>     let len = match len with Some x -> x | None -> String.length s - pos in
>     String.sub %pos %len s;;
> val sub : ?pos%int -> ?len%int -> string -> string = <fun>
> 

I really do think that it looks better !

You could continue to use ":" in types: because you are giving
information about the type of a label. this would make

# List.map;;
- : fun:('a -> 'b) -> 'a list -> 'b list = <fun>
# List.map [1;2;3] fun%succ;;
 - : int list = [2; 3; 4]
# let sub ?(%pos = 0) ?%len s =
    let len = match len with Some x -> x | None -> String.length s - pos
in
    String.sub %pos %len s;;
val sub : ?pos:int -> ?len:int -> string -> string = <fun>

-- 
Christophe Raffalli
Université de Savoie
Batiment Le Chablais, bureau 21
73376 Le Bourget-du-Lac Cedex

tél: (33) 4 79 75 81 03
fax: (33) 4 79 75 87 42
mail: Christophe.Raffalli@univ-savoie.fr
www: http://www.lama.univ-savoie.fr/~RAFFALLI



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

* Re: Syntax for label, NEW PROPOSAL
  2000-03-14 16:53 Syntax for label Don Syme
@ 2000-03-15  3:15 ` Jacques Garrigue
  2000-03-15  6:58   ` Christophe Raffalli
                     ` (2 more replies)
  0 siblings, 3 replies; 33+ messages in thread
From: Jacques Garrigue @ 2000-03-15  3:15 UTC (permalink / raw)
  To: dsyme, Christophe.Raffalli; +Cc: caml-list

I include a proposal at the end, please comment if you feel concerned.

From: Don Syme <dsyme@microsoft.com>

> And why not "as", i.e. "t as x", as I explained once in a previous post.
> I never did get an explanation as to why this wasn't an better solution.  It
> reuses a rarely-used keyword in a perfectly backward-compatible way.  
> I think it's simply a typical case of a new (and not necessarily terribly 
> crucial) language feature muscling in on the limited "ultra-convenient" 
> concrete syntax that's available!   No offence intended ;-)

An none taken.

Seriously, I believe the decision for the syntax of labels has be done
on a number of bases, including ideas collected on the caml list (sorry
if we didn't give feedback for every proposition).

Basically the strongest criteria were

1) comfort. Call it crucial or not, in typical modern mode code you
   have several labels by line of code. Anything more than one
   character is going to be heavy. Remember that ML is this wonderful
   language in which application is expressed by 0 characters!

2) inertia. Objective Label has been around for several years already
   (in fact, just as long as Objective Caml), and users seemed to be
   satisfied with the syntax.

3) homogeneity. The only change has been in the syntax for default
   parameters, which is a bit more homogeneous now. The idea was from John
   Prevost.

From: Christophe Raffalli [mailto:Christophe.Raffalli@univ-savoie.fr]
> It is clear that labels are a good thing ...
> But why did you use the same character ":" for types and labels !
> 
> whit not (for instance) x:t to say that x as type t
> and                     l#x to say that x as label l


Our conclusion on that point was that spaces are significant, and
there is no real ambiguity. You have to put spaces around : in type
annotations.

Also, the superficial similarity is in fact good in some cases:

	val sub : string -> pos:int -> len:int -> string

Argument types here "look like" type annotations.

> the syntax l#x:t is much better than l:x : t !!

Well, you do not write the above directly. Here are real cases:

(t type of the result)
	let f l#x:t = ...
	let f l:x : t = ...
(t type of the argument)
	let f (l#x:t) = ...
	let f (l: x : t) = ...

Do you really think that not putting spaces enhances readability?
And that once you have put the spaces, it is still hard to read?

If you do, then it might mean that our choice was wrong.

*** Proposal

Objective Caml 3.00 is not yet released, and I believe we can still
have modifications on this point.

Here is an alternative proposal, to use `%' in place of `:'. Labels
are kept as a lexical entity. This still breaks some programs, since
`%' was registered as infix, but this is not so bad.

In this case, I suppose we should read `%' as `is'.

Pro:
* `%' reminds a bit of substitution, which is the intuitive role of
  labels in applications.
* I checked it on a reasonable corpus of code, and it is
  readable enough. Particularly -shumacher-clean-* looks nice.
* changes to the compiler are very small.

Con:
* I still think that `:' looks better, particularly inside types.
* On my keyboard I can type in `:' without pressing shift :-)
* We will need some tool to convert existing code.

Do you think it would be better?
Are there people around who would rather keep `:' ?

Examples:

        Objective Caml version 2.99+10

# List.map;;
- : fun%('a -> 'b) -> 'a list -> 'b list = <fun>
# List.map [1;2;3] fun%succ;;
- : int list = [2; 3; 4]
# let sub ?(%pos = 0) ?%len s =
    let len = match len with Some x -> x | None -> String.length s - pos in
    String.sub %pos %len s;;
val sub : ?pos%int -> ?len%int -> string -> string = <fun>

Regards,

Jacques
---------------------------------------------------------------------------
Jacques Garrigue      Kyoto University     garrigue at kurims.kyoto-u.ac.jp
		<A HREF=http://wwwfun.kurims.kyoto-u.ac.jp/~garrigue/>JG</A>



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

end of thread, other threads:[~2000-03-24 15:19 UTC | newest]

Thread overview: 33+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2000-03-15 20:40 Syntax for label, NEW PROPOSAL Don Syme
2000-03-17  9:48 ` Jacques Garrigue
2000-03-17 17:34   ` Dave Mason
2000-03-18  0:26     ` Jacques Garrigue
2000-03-23 13:07       ` Sven LUTHER
  -- strict thread matches above, loose matches on Subject: below --
2000-03-17 21:33 Damien Doligez
2000-03-18 21:07 ` Frank Atanassow
2000-03-18 22:40 ` John Prevost
2000-03-17 17:03 Don Syme
2000-03-17 19:24 ` John Prevost
2000-03-14 16:53 Syntax for label Don Syme
2000-03-15  3:15 ` Syntax for label, NEW PROPOSAL Jacques Garrigue
2000-03-15  6:58   ` Christophe Raffalli
2000-03-15 21:54     ` Julian Assange
2000-03-15 11:56   ` Wolfram Kahl
2000-03-15 13:58   ` Pierre Weis
2000-03-15 15:26     ` Sven LUTHER
2000-03-17  7:44       ` Pierre Weis
2000-03-15 17:04     ` John Prevost
2000-03-17 10:11       ` Jacques Garrigue
2000-03-15 17:06     ` Markus Mottl
2000-03-15 19:11     ` Remi VANICAT
2000-03-17  8:30       ` Pierre Weis
2000-03-17 14:05         ` Jacques Garrigue
2000-03-17 16:08           ` Pierre Weis
2000-03-15 21:30     ` John Max Skaller
2000-03-16  2:55     ` Jacques Garrigue
2000-03-17 15:13       ` Pierre Weis
2000-03-17 17:33         ` Wolfram Kahl
2000-03-18 11:59         ` Jacques Garrigue
2000-03-21 16:51       ` Pascal Brisset
2000-03-23 11:14         ` Nicolas barnier
2000-03-16  8:50     ` Pascal Brisset
2000-03-17 11:15       ` Sven LUTHER

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).