[cwn] Attn: Development Editor, Latest OCaml Weekly News
Alan Schmitt
alan.schmitt at polytechnique.org
Tue Jul 2 02:02:15 PDT 2019
Hello
Here is the latest OCaml Weekly News, for the week of June 25 to
July
02, 2019.
Table of Contents
─────────────────
Learn Ocsigen: Graffiti tutorial updated
Release of OCamlFormat 0.10
Ocaml 4.09.0+beta1
Parallel and distributed execution of command lines, pardi!
Other OCaml News
Old CWN
Learn Ocsigen: Graffiti tutorial updated
════════════════════════════════════════
Archive:
<https://discuss.ocaml.org/t/learn-ocsigen-graffiti-tutorial-updated/3983/1>
Vincent Balat announced
───────────────────────
[Graffiti tutorial] explains step by step how to write a
[multi-user
client-server drawing application] in OCaml.
It is the best starting point for beginners with Ocsigen.
An updated version of this tutorial is now online, thanks to
[corentinjuvigny] and [chrismamo1].
Please report any problem (mistakes etc.) [here].
[Graffiti tutorial]
<http://ocsigen.org/tuto/latest/manual/application>
[multi-user client-server drawing application]
<http://ocsigen.org/graffiti>
[corentinjuvigny] <https://github.com/corentinjuvigny>
[chrismamo1] <https://github.com/chrismamo1>
[here] <https://github.com/ocsigen/tuto/issues>
Release of OCamlFormat 0.10
═══════════════════════════
Archive:
<https://discuss.ocaml.org/t/ann-release-of-ocamlformat-0-10/3988/1>
Guillaume Petiot announced
──────────────────────────
*Release of OCamlFormat 0.10*
We are pleased to announce the release of OCamlFormat 0.10
(available
on opam).
There have been numerous changes since the last release, so here
is a
comprehensive list of the new features and breaking changes to
help
the transition from OCamlFormat 0.9.
`ocamlformat-0.10' now works on the 4.08 AST, although the
formatting
should not differ greatly from the one of `ocamlformat-0.9' in
this
regard. Please note that it is necessary to build `ocamlformat'
with
4.08 to be able to parse new features like `let*'.
Upgrading from `ocamlformat-0.9' requires to install the
following
dependencies:
• ocaml-migrate-parsetree >= 1.3.1 (upgrade)
• uuseg >= 10.0.0 (new)
• uutf >= 1.0.1 (upgrade)
This release focuses on preserving the style of the original
source
and on handling more `ocp-indent' options.
Style preservation
╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌
◊ Expression grouping
The new option `exp-grouping' has been added to preserve the
keywords
`begin~/~end' that are used to delimit expressions instead of
parentheses. `exp-grouping=parens' always uses parentheses to
delimit
expressions. `exp-grouping=preserve' preserves the original
grouping
syntax (parentheses or `begin~/~end').
◊ Horizontal alignment
Horizontal alignment is something that users often use to make
pattern-matching or type declarations easier to read, and it is
a
feature that has been requested many times. Three new options
have
been added to horizontally align the lines.
`align-cases' horizontally aligns the match/try cases:
┌────
│ let fooooooooooo =
│ match foooooooooooooooooooooooo with
│ | Bfooooooooooooooooo -> foooooooooooo
│ | C (a, b, c, d) -> fooooooooooooooooooo
│ | _ -> fooooooooooooooooooo
└────
`align-constructors-decl' horizontally aligns type declarations:
┌────
│ type t =
│ | ( :: ) of a * b
│ | [] of looooooooooooooooooooooooooooooooooooooong_break
└────
`align-variants-decl' horizontally aligns variants type
declarations:
┌────
│ type x =
│ [ ~Foooooooo of int
│ | ~Fooooooooooooo of int ]
└────
◊ Preserve blank lines in sequences
The new option `sequence-blank-line' decides whether a blank
line is
preserved between expressions of a
sequence. `sequence-blank-line=compact' will not keep any blank
line
between expressions of a sequence, this is still the default
behavior. `sequence-blank-line=preserve' will keep a blank line
between two expressions of a sequence if the input contains at
least
one.
This option can help preserving the readability of the code in
this
situation:
┌────
│ let foo x y =
│ do_some_setup y ;
│
│ important_function x
└────
Supporting more `ocp-indent' options
╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌
The long term goal of `ocamlformat' is to handle every
`ocp-indent'
option, this release got closer to this goal as the following
`ocp-indent' options are now supported by `ocamlformat':
• max_indent
• with
• strict_with
• ppx_stritem_ext
• base
• in
• type
◊ Offset added to a new line
The new option `max-indent' sets the maximum offset (number of
columns) added to a new line in addition to the offset of the
previous
line. If this offset is set to 2 columns, then each new line can
only
be indented by 2 columns more in addition to the previous line,
for
example:
┌────
│ let () =
│ fooooo
│ |> List.iter (fun x ->
│ let x = x $ y in
│ fooooooooooo x)
└────
This option is equivalent to the `max_indent' option of
`ocp-indent',
and it will be set if `max_indent' is set in an `.ocp-indent'
configuration file.
◊ Indentation of pattern matching cases
The new options `funtion-indent' and `match-indent' respectively
decide the indentation of function cases and the indentation of
match/try cases. These options are equivalent to the `with'
option of
`ocp-indent', and they will be set if `with' is set in an
`ocp-indent'
configuration file. If the indentation is set to 4 columns,
cases are
formatted like this:
┌────
│ let foooooooo = function
│ | fooooooooooooooooooooooo -> foooooooooooooooooooooooooo
│
│ let foooooooo =
│ match fooooooooooooooooooooooo with
│ | fooooooooooooooooooooooo ->
foooooooooooooooooooooooooo
└────
The new options `function-indent-nested' and
`match-indent-nested'
respectively decide whether the `function-indent' and the
`match-indent' parameters should be applied even when in a
sub-block. If these options are set to `never', it only applies
`function-indent' or `match-indent' if the function or match
block
starts a line. If these options are set to `always', then the
indent
parameters are always applied. The `auto' value applies the
indentation parameter when seen fit.
These options are equivalent to the `strict_with' option of
`ocp-indent', and they will be set if `strict_with' is set in an
`ocp-indent' configuration file.
◊ Indentation inside extension nodes
The new option `extension-indent' sets the indentation of items
(that
are not at structure level) inside extension nodes. The new
option
`stritem-extension-indent' sets the indentation of structure
items
inside extension nodes. This option is equivalent to the
`ppx_stritem_ext' option of `ocp-indent', and it will be set if
`ppx_stritem_ext' is set in an `.ocp-indent' configuration file.
For example if `extension-indent' is set to 5 and
`stritem-extension-indent' is set to 3:
┌────
│ let foo =
│ [%foooooooooo
│ fooooooooooooooooooooooooooo
foooooooooooooooooooooooooooooooooo
│ foooooooooooooooooooooooooooo]
│ [@@foooooooooo
│ fooooooooooooooooooooooooooo
foooooooooooooooooooooooooooooooooo
│ foooooooooooooooooooooooooooo]
│
│ [@@@foooooooooo
│ fooooooooooooooooooooooooooo
foooooooooooooooooooooooooooooooooo
│ foooooooooooooooooooooooooooo]
└────
◊ Let-binding indentation
The new option `let-binding-indent' sets the indentation of let
binding expressions if they do not fit on a single line. This
option
is equivalent to the `base' option of `ocp-indent'. The new
option
`indent-after-in' sets the indentation after `let ... in',
unless
followed by another `let'. This option is equivalent to the `in'
option of `ocp-indent'. The new option `type-decl-indent' sets
the
indentation of type declarations if they do not fit on a single
line. This option is equivalent to the `type' option of
`ocp-indent'.
These options will be set if their `ocp-indent' counterparts are
set
in an `.ocp-indent' configuration file.
Miscellaneous features
╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌
This release also brings some new options, new values for
existing
features, or corrects erroneous behaviours.
◊ Indicate multiline delimiters
The former `indicate-multiline-delimiters' boolean option is now
a
3-valued option:
• `indicate-multiline-delimiters=space' (was equivalent to
`true')
prints a space inside the delimiter to indicate the matching
one is
on a different line.
• `indicate-multiline-delimiters=no' (was equivalent to `false')
doesn't do anything special to indicate the closing delimiter.
• `indicate-multiline-delimiters=closing-on-separate-line' is
the new
feature of this option, it makes sure that the closing
delimiter is
on its own line.
On this example we can see the closing parenthesis delimiting
the
nested pattern-matchings are on their own line and are aligned
with
the matching opening parenthesis:
┌────
│ let () =
│ match v with
│ | None -> None
│ | Some x ->
│ ( match x with
│ | None -> None
│ | Some x ->
│ ( match x with
│ | None -> None
│ | Some x -> x
│ )
│ )
└────
◊ Formatting of literal strings
`break-string-literals=newlines' now takes into account
pretty-printing commands like `@,', `@;' and `@\n' to produce
more
readable strings. A new value for this option has been added,
`break-string-literals=newlines-and-wrap', to break lines at
newlines
delimiters (including pretty-printing commands) and also wrap
the
string literals at the margin.
Here is how `break-string-literals=newlines-and-wrap' formats a
string:
┌────
│ let fooooooooooo =
│ "Lorem ipsum dolor sit amet, consectetur adipiscing elit,
sed do eiusmod \
│ tempor incididunt ut labore et dolore magna aliqua.@;\
│ Ut enim ad minim veniam, quis nostrud exercitation ullamco
laboris nisi \
│ ut aliquip ex ea commodo consequat.@;\
│ Duis aute irure dolor in reprehenderit in voluptate velit
esse cillum \
│ dolore eu fugiat nulla pariatur.@;\
│ Excepteur sint occaecat cupidatat non proident, sunt in
culpa qui \
│ officia deserunt mollit anim id est laborum."
└────
*Warning:* the `break-string-literals' will likely be removed in
the
next release and the default behavior would be
`newlines-and-wrap'.
◊ Break before the `in' keyword
The new option `break-before-in' has been added to decide
whether the
line should break before the `in' keyword of a `let'
binding. `break-before-in=fit-or-vertical' will always break the
line
before the `in' keyword if the whole `let' binding does not fit
on a
single line, it is still the default behavior.
`break-before-in=auto'
will only break the line if the `in' keyword does not fit on the
previous line.
For example:
┌────
│ let _ =
│ let short = this is short in
│ let fooo =
│ (this is very long) but (the in keyword can fit) on the
same line in
│ foooooo
└────
◊ Indentation of nested pattern-matching
The new option `nested-match' defines the style of
pattern-matchings
nested in the last case of another
pattern-matching. `nested-match=wrap' wraps the nested
pattern-matching with parentheses and adds indentation, this is
still
the default behavior. `nested-match=align' vertically aligns the
nested pattern-matching under the encompassing pattern-matching,
for
example:
┌────
│ let () =
│ match v with
│ | None -> None
│ | Some x ->
│ match x with
│ | None -> None
│ | Some x -> x
└────
The new option `cases-matching-exp-indent' decides the
indentation of
cases right-hand sides which are `match' or `try'
expressions. `cases-matching-exp-indent=compact' forces an
indentation
of 2, unless `nested-match' is set to `align' and this is the
last
case of the pattern matching. `compact' is the default
behavior. `cases-matching-exp-indent=normal' indents as it would
any
other expression.
◊ Whitelist of files to format
A new kind of configuration files is now handled by
`ocamlformat':
`.ocamlformat-enable' files. If the `disable' option is set, an
`.ocamlformat-enable' file can list the files that `ocamlformat'
should format even when the `disable' option is set. Each line
in an
`.ocamlformat-enable' file specifies a filename relative to the
directory containing the `.ocamlformat-enable' file.
The `.ocamlformat-enable' files are using the same syntax as the
`.ocamlformat-ignore' files: lines starting with `#' are ignored
and
can be used as comments.
These new configuration files do not contradict the existing
`.ocamlformat-ignore' files, as `.ocamlformat-enable' are only
considered when `disable' is set, and `.ocamlformat-ignore' are
only
considered when `disable' is not set.
◊ Disable outside detected project
The `disable-outside-detected-project' option is now set by
default.
When the option `--enable-outside-detected-project' is not set,
`.ocamlformat' files outside of the project (including the one
in
`XDG_CONFIG_HOME') are not read. The project root of an input
file is
taken to be the nearest ancestor directory that contains a .git
or .hg
or dune-project file. If no config file is found, formatting is
disabled.
◊ Space around collection-expressions
The former option `space-around-collection-expressions' that was
deciding whether a space should be added inside the delimiters
of
collection expressions (lists, arrays, records, variants) has
been
replaced by 4 new options: `space-around-arrays',
`space-around-lists', `space-around-records' and
`space-around-variants', to allow a finer grain customization.
◊ Fit-or-vertical mode for pattern matching
The `break-cases' option that decides the shape of pattern
matching
has a new value `fit-or-vertical'. `break-cases=fit-or-vertical'
tries
to fit all or-patterns on the same line, otherwise breaks each
or-pattern (they are wrapped in other modes). For example if
this set
of or-patterns does not fit on a single line, we get the
following
output:
┌────
│ let ffffff =
│ match foooooooooooo with
│ | Aaaaaaaaaaaaaaaaa
│ | Bbbbbbbbbbbbbbbbb
│ | Ccccccccccccccccc
│ | Ddddddddddddddddd
│ | Eeeeeeeeeeeeeeeee -> foooooooooooooooooooo
│ | Fffffffffffffffff -> fooooooooooooooooo
└────
◊ K&R style for if-then-else
The `if-then-else' option now has a new value `k-r' that uses
parentheses (when necessary) to reproduce a formatting close to
the
K&R style. For example:
┌────
│ let _ =
│ if b then (
│ something loooooooooooooooooooooooooooooooong enough
to_trigger a break ;
│ this is more
│ ) else if b1 then (
│ something loooooooooooooooooooooooooooooooong enough
to_trigger a break ;
│ this is more
│ ) else
│ e
└────
Breaking changes
╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌
• the `indicate-multiline-delimiters' option is no longer a
boolean
option but now has 3 values: `space', `no' and
`closing-on-separate-line' that are detailed in this patch
note.
• the `disable-outside-detected-project' option is now set by
default.
• the `default' preset profile has been removed (it was
equivalent to
the `ocamlformat' profile with `break-cases=fit').
• the `space-around-collection-expressions' option has been
replaced
by 4 new options: `space-around-arrays', `space-around-lists',
`space-around-records' and `space-around-variants'.
What's next?
╌╌╌╌╌╌╌╌╌╌╌╌
We strongly encourage our users to try out the `conventional'
preset
profile, as we plan to make it the default profile in a future
release. This profile's purpose is to reproduce the most
commonly
encountered styles, and it may be more pleasing to the eye than
the
current default options.
As stated previously, the `break-string-literals' will likely be
removed in the next release and the default behavior would be
`newlines-and-wrap'.
Credits
╌╌╌╌╌╌╌
This release also contains many other changes and bug fixes that
we
cannot detail here.
We would like to thank our maintainers and contributors for this
release: Jules Aguillon, Josh Berdine, Hugo Heuzard, Guillaume
Petiot
and Thomas Refis, and especially our industrial users Jane
Street,
Ahrefs and Nomadic Labs that made this work possible by funding
this
project and providing helpful contributions and feedback.
We would be happy to provide support for more customers, please
contact us at contact at tarides.com
If you wish to get involved with OCamlFormat development or file
an
issue, please read the [contributing guide], any contribution is
welcomed.
[contributing guide]
<https://github.com/ocaml-ppx/ocamlformat/blob/master/CONTRIBUTING.md>
Ocaml 4.09.0+beta1
══════════════════
Archive:
<https://sympa.inria.fr/sympa/arc/caml-list/2019-06/msg00054.html>
Damien Doligez announced
────────────────────────
The release of OCaml 4.09.0 is approaching. We have created a
beta
version to help you prepare for the release.
The source code is available at these addresses:
<https://github.com/ocaml/ocaml/archive/4.09.0+beta1.tar.gz>
<https://caml.inria.fr/pub/distrib/ocaml-4.09/ocaml-4.09.0+beta1.tar.gz>
The compiler can also be installed as an OPAM switch with one of
the
following commands.
┌────
│ opam switch create ocaml-variants.4.09.0+beta1
--repositories=default,beta=git+https://github.com/ocaml/ocaml-beta-repository.git
└────
or
┌────
│ opam switch create ocaml-variants.4.09.0+beta1+<VARIANT>
--repositories=default,beta=git+https://github.com/ocaml/ocaml-beta-repository.git
└────
where you replace <VARIANT> with one of these:
• afl
• default_unsafe_string
• flambda
• fp
• fp+flambda
We want to know about all bugs. Please report them here:
<https://github.com/ocaml/ocaml/issues>
Parallel and distributed execution of command lines, pardi!
═══════════════════════════════════════════════════════════
Archive:
<https://discuss.ocaml.org/t/ann-parallel-and-distributed-execution-of-command-lines-pardi/4015/1>
UnixJunkie announced
────────────────────
I am pleased to announce the first release of pardi (which the
community recently helped to debug):
<https://github.com/UnixJunkie/pardi>
Pardi is a command line tool to parallelize programs which are
not
parallel; provided that you can cut an input file into
independent
chunks.
For example, to compress a file in parallel using 1MB chunks:
┌────
│ pardi -d b:1048576 -m s -i <YOUR_BIG_FILE> -o
<YOUR_BIG_FILE>.gz \
│ -w 'xz -c -9 %IN > %OUT'
└────
Using the right option, you can cut an input file by lines (e.g.
SMI
files), by number of bytes (for binary files), by separating
lines
verifying a regexp (quite generic) or by a block separating line
(e.g. MOL2/SDF/PDB file formats).
If processing a single record of your input file is too fine
grained,
you can play with the -c option to reach better parallelization
(try
10,20,50,100,200,500,etc).
┌────
│ usage:
│ pardi ...
│ {-i|--input} <file>: where to read from (default=stdin)
│ {-o|--output} <file>: where to write to (default=stdout)
│ {-n|--nprocs} <int>: max jobs in parallel (default=all
cores)
│ {-c|--chunks} <int>: how many chunks per job (default=1)
│ {-d|--demux} {l|b:<int>|r:<regexp>|s:<string>}: how to cut
input
│ file into chunks (line/bytes/regexp/sep_line; default=line)
│ {-w|--work} <string>: command to execute on each chunk
│ {-m|--mux} {c|s|n}: how to mux job results in output file
│ (cat/sorted_cat/null; default=cat)
└────
Other OCaml News
════════════════
From the ocamlcore planet blog
──────────────────────────────
Here are links from many OCaml blogs aggregated at [OCaml
Planet].
• [Compiler Engineer at Axoni (Full-time)]
• [Learn Eliom - Graffiti tutorial updated]
[OCaml Planet] <http://ocaml.org/community/planet/>
[Compiler Engineer at Axoni (Full-time)]
<https://functionaljobs.com/jobs/9171-compiler-engineer-at-axoni>
[Learn Eliom - Graffiti tutorial updated]
<https://ocsigen.github.io/blog/2019/06/25/graffiti/>
Old CWN
═══════
If you happen to miss a CWN, you can [send me a message] and
I'll mail
it to you, or go take a look at [the archive] or the [RSS feed
of the
archives].
If you also wish to receive it every week by mail, you may
subscribe
[online].
[Alan Schmitt]
[send me a message] <mailto:alan.schmitt at polytechnique.org>
[the archive] <http://alan.petitepomme.net/cwn/>
[RSS feed of the archives]
<http://alan.petitepomme.net/cwn/cwn.rss>
[online] <http://lists.idyll.org/listinfo/caml-news-weekly/>
[Alan Schmitt] <http://alan.petitepomme.net/>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.idyll.org/pipermail/caml-news-weekly/attachments/20190702/096e3c3b/attachment-0001.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 487 bytes
Desc: not available
URL: <http://lists.idyll.org/pipermail/caml-news-weekly/attachments/20190702/096e3c3b/attachment-0001.pgp>
More information about the caml-news-weekly
mailing list