Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Suggestions for "The OCaml system release 4.06" #7698

Closed
vicuna opened this issue Dec 24, 2017 · 7 comments
Closed

Suggestions for "The OCaml system release 4.06" #7698

vicuna opened this issue Dec 24, 2017 · 7 comments

Comments

@vicuna
Copy link

vicuna commented Dec 24, 2017

Original bug ID: 7698
Reporter: jfehrle
Assigned to: @Octachron
Status: assigned (set by @Octachron on 2018-01-02T13:58:02Z)
Resolution: open
Priority: normal
Severity: minor
Version: 4.06.0
Category: documentation
Monitored by: @nojb @yakobowski

Bug description

I found "The OCaml system release 4.06" was not so easy to read and understand. This will tend to slow down and discourage people who want to learn and use OCaml. I will be looking at some OCaml books, but so far I haven't found one that looks to be what I want. Something that's as readable as "The C Programming Language" would be fabulous.

These comments are for the first 2 1/2 chapters. I'd be happy to a) read revisions and b) submit comments on the other chapters if someone undertakes improving the document.

Additional information

OCaml Comments:

Page 13:

“A good familiarity with programming in conventional languages (say, Pascal or C) is assumed, but no prior exposure to functional languages is assumed.”

The text assumes a number of details that would be unfamiliar to a C programmer. No need to mention Pascal any more, it is little used. You might refer to Java or C++, which could be useful for comparison in Chapter 3.

“1.1 Basics”

I’d like a very high-level overview of OCaml in just a few pages before seeing any examples. This is to get context and so I have an idea what to expect in the document before providing a full discussion of a topic. Some repetition is helpful to the reader. From my OCaml beginner’s perspective, some of the interesting points to get out early would be:

  • The extensive type system
  • Type inference (but you can specify explicitly when necessary in some places?)
  • The use of type variables
  • Creating variant types that are unions of other types
  • The fact that the type checking is totally rigorous and that there are no automatic conversions
  • That type information is not available at runtime (unlike Reflection in Java, for example).
  • Data types (primitive, arrays, lists, tuples, records, classes/objects, ?)
  • Patterns
  • Support for functional, imperative and object-oriented paradigms
  • Modules for managing large projects
  • Differences between the top level and compiled programs (e.g. for modules) (Note that the top level is good for experimentation but probably not as useful for large multi-file projects such as Coq)

What is the relation to ML? Would any of the ML documentation be helpful in learning OCaml?

Also, it would great to include some motivational examples of things that you do easily in OCaml that are harder to do in C++/Java.

Explain ;; would generally not be used in programs complied from source files rather than typed into the top level.

Explain that “float -> float” or “int -> int -> int” is a function signature. This notation would be completely unknown to C/Java developers. Also say a little about where this notation came from (mathematical logic) and why it is preferred over more common notation such as “f(int, int) -> int” or “int f(int, int)”.

Page 14:

“General mechanisms for defining your own data structures are also provided.”

How about saying “There are also general mechanisms for defining your own data structures. These are records and classes, which will be covered shortly.”?

“List patterns have the exact same shape as list expressions.”

Unless “shape” is a technical term, I think “form” is probably a much word choice.

“and” in code example – would be helpful to say what this means rather than let the reader guess. Why use the “and” instead of 2 top-level let’s? Also, somewhere say something about indentation conventions. This seems like it may be the convention, but it is unfamiliar to C/Java developers:

let x = … in
let y = … in
last_expression

Page 15:

“modify in-place a list” -> “modify a list in place” (English syntax)

“sin’” – mention what characters are allowed in identifiers. Apostrophe is not allowed in C or Java.

Page 16:

“to expand directly” -> “to directly expand”

Page 17:

Mention “with” is a keyword.

“all possible shapes” -> “all possible forms”

In “Float of float”, the “of” is a keyword, just syntactic sugar? And the “int” or “float” could be any type, such as an array of int tuples?

“Constructor names are capitalized” – would be good to naming conventions a short section so it can be found later and indexed.

“match (n1, n2)” – this is matching on a tuple, right? Maybe worth noting. Can you match on simple types (booleans, ints)? Anything else?

Page 18:

“’a” - Mention the convention that a symbol starting with an apostrophe is a type variable.

“two subtrees containing also” -> “two subtrees also containing”

Page 19:

“Arrays are given in extension between [| and |] brackets, …” – the first part of the sentence lets you give the values of the array elements, while Array.make is much less flexible. “given in extension” is not standard English. Maybe split into 2 sentences. “Arrays containing values can be provided as a series of semicolon-separated values betwees [| and |] brackets.”

“… references, which are mutable indirection cells (or one-element arrays)” seems inconsistent with the statement on page 20: “… references: they are implemented as a single-field mutable record, as follows:”

Page 20:

“let ( ! ) = …” Would you explain the syntax of “( ! )”? You couldn’t do this in C/Java. Probably in C++.

Just curious: Is there a way to explicitly specify the type of a functions’ arguments? Or is it always inferred?

“Without user-provided type annotations, this is not allowed, as polymorphism is only introduced on a global level.” This sentence is hard to understand; the negative “without” and “not allowed” are a little confusing. Maybe say something like “Doing this requires user-provided type annotation, since polymorphism is only introduced automatically for global (top-level?) definitions.”?

“mutable id: ’a. ‘a -> ‘a” The period is just to mark the end of the type of id?

Page 21:

“Exceptions can also be used as a general-purpose non-local control structure.” At least within the Java community, I think many people would disagree with this. It can easily be abused. Exceptions should be for truly exceptional conditions (errors), not as a general-purpose control structure.

“The with part is actually a regular pattern-matching on the exception value.” “regular” makes me think of regular expressions. I think you mean it does the usual/normal pattern matching. Maybe
say “The with part does pattern matching on the exception value.”?

“then raising again the exception” -> “then raising the exception again”

Page 22:

“expression * expression” – I don’t fully understand the syntax. Is this defining a tuple? Why is the “” needed? Of course, it is not multiplication, but a little odd to see in an expression evaluator when the comments use “” to mean multiplication, slightly confusing, maybe worth a short comment.

Page 27:

When I hear the term “structure,” it makes me think of data structures. In C, “struct” is a keyword used to define their equivalent to records.

The simpler use of modules is to manage a large body of code and its name spaces. Functors more complex and are fairly similar to parameterized classes in Java. I would introduce these two uses in that order. Key points on managing a large body of code:

  • Each module has its own namespace
  • By default, each source file defines a separate module matching the file name.
  • Use PrioQueue.empty to refer to an item in module PrioQueue. (How do you distinguish between the modules from 2 source files dir1/foo.ml and dir2/foo.ml?)
  • Use open to include another module’s definitions in the current name space. (What happens if the name is used in 2 imports? Or used in an import but also defined in the current module?)
  • “let open xxx in” construct
  • Creating multiple modules in one source file? (Is it possible and is it a good practice? Seem like it would simpler to stick to using the file name as the module name.)
  • Can module definitions be nested? If that’s useful.
  • The relationship between .mli files and modules (section 2.5 with some editing to avoid introducing signatures)

I wouldn’t mention signatures or show them in examples until after the above points are covered.

Page 31:

“Functors are ‘functions’ from structures to structures” They are not general functions at all, are they? As far as I can tell, they only allow substitution for specific parameters. So the first sentence is misleading and would best be removed. The paragraph could begin with “Functors let you create parameterized signatures and then provide the parameter(s) to get a specific implementation. For instance …”

The example is so long it’s a bit hard to follow. Maybe it could be done in two parts: first, a skeleton of the high-level structure with a few comments, such as:

module type ORDERED_TYPE =  sig …
module Set = 
	functor (Elt: ORDERED_TYPE) ->  struct …
module OrderedString = struct …	(* matching the signature of ORDERED_TYPE *)
module StringSet = Set(OrderedString);;

Then show the details of ORDERED_TYPE, Set and OrderedString.

Page 33:

For the first example, it would help to describe what’s been changed or highlight the differences more thoroughly. That saves the reader from having to do a diff in their heads between the two pages. If the differences could be in boldface, that would be great.

Also, I notice the signature for ‘add’ is slightly different between this example and the earlier one. Maybe worth mentioning/explaining?

The rest of section 2.4 is too much detail at this point. Plus it’s a bit of work to pick out the differences compared to the earlier examples. The lengthy discussion and example makes me think it’s complicated.

Page 37:

To me, this section seems to be showing how powerful the type system is and how you can get all kinds of different behavior for subclassing, self, etc. It’s too much. I would suggest taking examples from Java and C++ classes/objects and showing how to create equivalent constructs in OCaml—more of a cookbook approach. It seems to me there are a huge number of things you can do with the type system, of which only a few are really useful. If you’re writing a program with classes and objects, you probably want them all to have similar behavior with regards to subclassing, self, etc. just for your own sanity.

Page 39:

The first example (with “new point;;” and “new point 7;;”) is confusing. In the latter, “new point” is done first, then the resulting function is called with an argument of 7? Then seems to go against the grain of OCaml expressions and is worthy of explanation. “new” is a keyword, right?

Page 40:

“let minmax x y =”

This is contrived example. No one would write this in real life. Would be better to have a realistic example. Also using more lines for the example with better indentation would help readability.

Page 41:

“can send messages to self” This is confusing. I think what’s meant is that it’s possible to refer to methods and variables that are part of the object. I’m vaguely aware of an object metaphor based on messages, but it seems to me OCaml does not actually create messages.

Page 42:

“Virtual methods” Could mention that these are called abstract methods in Java. C++ has virtual methods but I think the concept is slightly different.

I’ll stop here. Enough for now.

Scoping?
Flow of control (and loops, etc.)

@vicuna
Copy link
Author

vicuna commented Dec 24, 2017

Comment author: @dra27

Thanks for this - it's always useful to have the perspective of someone new to OCaml on the documentation, as it's so hard after years of using it to put oneself into the shoes of a newcomer!

The sources for the manual are included in our repository (https://github.com/ocaml/ocaml) - some of the smaller changes would be easier to discuss if you are able/willing to contribute a pull request?

Some brief comments on a whiz through your points:

  • Page 14: "records and classes" are not the only mechanisms for defining your own data structues; this underscores your point that it could be expanded.

  • Page 16: both forms are valid English, but I (and I expect at least one other British English core developer) will certainly not see the manual go into the realm of split infinitives, boldly or otherwise!

  • Pages 17, 18: interestingly, both your mentioning of the "of" keyword, capitalised constructors and apostrophes beginning type variables (in this context) are not conventions, but syntatic requirements of the language.

  • Page 21: the Java/C++ comment on exceptions is irrelevant, since exceptions in OCaml (and ML in general) are considerably more lightweight. That point is worth underscoring, but not the opinion that they should be eschewed completely. There are occasionally mailing list wars on the subject of using exceptions or 'a option/result types to signal exceptional conditions, so even stating that they should be used for exceptional conditions is a loaded statement in OCaml! That said, within the next 12-18 months, exceptions for this will have been superceded by algebraic effects.

  • Page 31: one sentence contradicts the other, functors are "'functions' from structures to structures" and hence not general at all. They are however functions in the sence that they can be partially applied, with all the fun which comes with that. The module system is much more powerful than your reduced description implies, but it would be worth rewording it to reflect both the simpler interpretation and their expressive power.

  • Page 37: should definitely not be constructed by taking C++ and Java examples and translating to the OCaml object system. Most idiomatic C++ and Java use cases should not be translated to OCaml - cookbook-style translations might be interesting, but most would not use the object system.

  • Page 41: the use of the word "messages" is largely accurate, I believe.

@vicuna
Copy link
Author

vicuna commented Dec 24, 2017

Comment author: jfehrle

See https://github.com/ocaml/ocaml/pull/1545/files

@vicuna
Copy link
Author

vicuna commented Jan 2, 2018

Comment author: @Octachron

Some comments on your comments that were not addressed in your PR:

— "1.1 Basics":

  • A good high-level overview would be nice, but it is not an easy piece of writing. And it would be probably the best place for motivational examples.
  • OCaml is language in the ML family
  • It seems that the manual is lacking a subsection on partial application, which would be the most natural place to explain the "arg_1 -> arg_2 -> return" notation. Thanks for noticing this point.

— Lexical conventions
It is probably a good idea to be more explicit with lexical convention inside the tutorial part of the manual:
* mentioning that "of" and "with" are keywords
* adding a footnote for allowed character in identifiers
* making clearer that capitalization is meaningful
(outside of module type, polymorphic variants and type variables names)
* 'a is a type variable name
* parenthesised form of operators, e.g. ( ! )

— Page 17:
* detailing a little more the possibility of pattern matching
is probably a good idea

— Page 19:

Type annotation can added to make types explicit.
The section on polymorphic record field could probably be moved to
the polymorphism chapter.

— Page 22:

The multiplication operator is used to represent cartesian product,
this is shortly explained in the section 1.4.
But it might worthwhile to expand this explanation
(by detailing the type of tuples for instance).

— Page 27:

At this point the C++ terminology and OCaml terminology diverges completely
(since OCaml functors also have little to do with C++ functors).
Avoiding loaded C++ term would be impossible here.

  • Signatures are an essential part of managing namespaces and abstractions.
    Nevertheless, introducing a transparent module without an explicit
    signature first might help to reduce the information density in
    this chapter.
  • Detailing the shadowing rules for open might be worth some investigations.
  • Nesting modules is perfectly possible.
  • Since mli files are signatures, it is not really possible to explain
    them without introducing signatures.

@vicuna
Copy link
Author

vicuna commented Jan 3, 2018

Comment author: jfehrle

re Page 37:

Poor wording on my part. Certainly I wouldn't include Java or C++ code examples. But it would make sense to list various attributes commonly used in object systems, such as: inheritance, hiding of information and methods, self, abstract methods/classes, virtual/static methods, diamond inheritance, calling a superclass method. And perhaps very briefly, maybe in a short table, identify the similar/equivalent Java/C++ features. And then explaining how to do each of these in OCaml in cookbook form.

Page 122: The end of the syntax description is cut off in the tex output. Needs to be split.

@XVilka
Copy link
Contributor

XVilka commented Oct 31, 2019

Should be this added for 4.11 release? Seems a good target for a junior-job label, as well as, probably for creating Documentation project.

@Octachron
Copy link
Member

This issue could be split into smaller and more delimited issues worthy of a junior-job label.

But as it stands, there are too many concerns mixed in the same issue and I cannot guarantee that this issue is a good junior job .

Taking in account the fact that a significant part of the comments were addressed in #1545,
I will implement the remaining smaller points, split the individual items into distinct issues,
and close the issue.

@github-actions
Copy link

github-actions bot commented Nov 2, 2020

This issue has been open one year with no activity. Consequently, it is being marked with the "stale" label. What this means is that the issue will be automatically closed in 30 days unless more comments are added or the "stale" label is removed. Comments that provide new information on the issue are especially welcome: is it still reproducible? did it appear in other contexts? how critical is it? etc.

@github-actions github-actions bot added the Stale label Nov 2, 2020
@github-actions github-actions bot closed this as completed Dec 2, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants