[Caml-list] Attn: Development Editor, Latest OCaml Weekly News

Alan Schmitt
2020-09-01T07:55:54Z

[-- Attachment #1: Type: text/plain, Size: 15200 bytes --]

Hello

Here is the latest OCaml Weekly News, for the week of August 25 to
September 01, 2020.

Table of Contents
─────────────────

Writing bindings for Google Apps Script (GAS)
What the Jane Street interns have wrought
a small library for shell/AWK/Perl-like scripting
letters 0.2.0
raylib-ocaml 0.1.0
OCaml Workshop 2020 Online Conference is live now
Other OCaml News
Old CWN

Writing bindings for Google Apps Script (GAS)
═════════════════════════════════════════════

Archive:
<https://discuss.ocaml.org/t/writing-bindings-for-google-apps-script-gas/6293/1>

Danielo Rodríguez announced
───────────────────────────

Thanks to the help of this community I successfully completed a crazy
idea: To write some ocaml functions to use inside [Google Apps Script]
for a small stupid spreadsheet that I had.

The way it works now is by having a main index.js file that calls the
Ocaml functions that are available under a global Lib
namespace. Everything is bundled using parcel and the Idea was to use
as few JS code as possible. Because it was easier than I expected I
decided to go one step further and write some bindings for the GAS
functions I was using and reduce the glue JS code even more.

This are the bindings that I wrote so far. They work, but are not
usable inside Ocaml yet.

┌────
│ type spreadsheet
│ type sheet
│ type range
│ external getActiveSpreadsheet : unit -> spreadsheet = "getActiveSpreadsheet" [@@bs.val][@@bs.scope
│ "SpreadsheetApp"]
│ external getSheets : spreadsheet -> sheet array = "getSheets" [@@bs.send]
│ external getSheetByName : spreadsheet -> string -> sheet = "getSheetByName" [@@bs.send]
│ external getDataRange : sheet -> range = "getDataRange" [@@bs.send]
│ external getValues : range -> 'a array array = "getValues" [@@bs.send]
└────

My doubt are on the edges. When it is just obscure GAS stuff I have no
doubt, abstract types and functions to interact with them. Is when a
GAS function returns data where I have doubts. Usually they are just
arrays of arrays of Numbers or Strings. In the example above, the last
definition says that you will get an array of arrays of `'a', but that
is not true because it will be an array of "stuff" (strings, numbers,
floats). How should I type it in a way that it's flexible but not
cumbersome? For example, I don't think using a functor will help
because you will need to create a functor for every possible return
type, in my case if you have 3 sheets with 3 different shapes, you
will need 3 functors. An alternative that I have used was to provide
some helper functions to convert from JS to Ocaml types and then
unwrap the Ocaml types, like the example I'm doing with
Number_or_string. This is nothing serious and I will just add the
bindings that I may need for now, but I want to hear what the
community (and potential users) thinks.

If anyone is interested in taking a look on the project, it is here:
<https://github.com/danielo515/ElectronicProjectsSpreadsheet>

[Google Apps Script] <https://developers.google.com/apps-script>

Matthieu Dubuget said
─────────────────────

Not answering directly to your question, sorry.

But here is a binding I have been using for around 4 years:
<https://dubuget.fr/gitea/matthieu/ocaml-google-app.git>.

Hongbo Zhang also replied
─────────────────────────

For return type polymorphism, you can use GADT with bs.ignore, the
rough idea:

┌────
│ type 'a t = Int : int t | String : string t
│ external f : ('a t [@bs.ignore]) -> ... -> 'a = "xx"
└────
I read discuss.ocaml.org from time to time, but checks
<https://forum.rescript-lang.org/> daily where you can get a quick
answer

What the Jane Street interns have wrought
═════════════════════════════════════════

Archive:
<https://discuss.ocaml.org/t/what-the-jane-street-interns-have-wrought/6294/1>

Yaron Minsky announced
──────────────────────

I thought folks here might find this interesting:

<https://blog.janestreet.com/what-the-interns-have-wrought-2020/>

The post summarizes three of the intern projects that happened this
summer at Jane Street. It might be interesting if you're looking for
an internship (or know someone who is), or if you're interested in any
of the underlying tech. For example, if there's significant interest
in a library for writing OCaml, we'd be more likely to open-source it.

a small library for shell/AWK/Perl-like scripting
═════════════════════════════════════════════════

Archive:
<https://sympa.inria.fr/sympa/arc/caml-list/2020-08/msg00021.html>

Oleg announced
──────────────

Some time ago Chet Murthy asked about writing shell-like scripts in
OCaml. Prompted by it, I also want to report on my experience and
announce a small library that made it pleasant to do
shell/AWK/Perl-like scripting in OCaml.

The library is available at
<http://okmij.org/ftp/ML/myawk/0README.dr>
and consists of two small ML files, myawk.ml and strings.ml. The
latter collects general-purpose string operations, more convenient
than those in Stdlib.String. The rest of that web directory contains
half a dozen sample scripts with comments.

Here is the first example: a typical AWK script, but written in OCaml:

┌────
│ #!/bin/env -S ocaml
│
│ #load "myawk.cma"
│ open Myawk open Strings
│ let hash = string_of_int <|> Hashtbl.hash
│ ;;
│ (* Sanitize the files originally used by join1.ml and join2.ml
│ The files are made of space-separated fields; the first field is the
│ key. It is sensitive; but because it is a key it can't be replaced with
│ meaningless garbage. We obfuscate it beyond recognition. The third field
│ is obfuscated as well. The second and fourth can be left as they are,
│ and the fifth, if present, is replaced with XXX
│
│ The script is a proper filter: reads from stdin, writes to stdout
│ *)
│
│ for_each_line @@ map words @@ function (f1::f2::f3::f4::rest) ->
│ print [hash f1; f2; hash f3; f4; if rest = [] then "" else "XXX"]
│ ;;
└────

Here <|> is a function composition. I wish it were in Stdlib. The real
example, used in real life, was performing a database join

┌────
│ SELECT T2.* from Table1 as T1, Table2 as T2 where T1.f1 = T2.f1
└────

where Table1 and Table2 are text files with space-separated column
values. Table1 is supposed to be fed to stdin:

┌────
│ let () =
│ for_each_line @@ map words @@
│ map_option (function (x::_) -> Some x | _ -> None) @@
│ (ignore <|> shell "grep %s table1.txt")
└────

It is a typical rough-and-dirty script. Alas, it was too rough: I was
so excited that it typechecked and worked the first time, that I
didn't look carefully at the output and overlooked what I was looking
for (resulting in an unneeded hassle and apology). I should have
queried exactly for what I wanted:
┌────
│ SELECT T1.f1, T1.f4 FROM Table1 as T1, Table2 as T2
│ WHERE T1.f1 = T2.f1 AND T1.f3 <> "3"
└────

which is actually easy to write in myawk (probably not so in AWK
though)

┌────
│ let () =
│ for_each_line ~fname:"table2.txt" @@ map words @@
│ map_option (function (w::_) -> Some w | _ -> None) @@
│ fun w ->
│ for_each_line ~fname:"table1.txt" @@ map words @@
│ map_option (function
│ (x::f2::f3::f4::_) when x = w && f4 <> "3" -> Some [x;f4] | _ -> None) @@
│ print
└────

This is the classical nested loop join. Chet Murthy might be pleased
to see the extensive use of the continuation-passing style. I was
apprehensive at first, but it turned out not to be a hassle.

The library has a few other examples, including case-branching and
rewriting a real AWK script from the OCaml distribution.

Finally, let's compare with shell scripts. The example below doesn't
show off the library, but it does show the benefits of OCaml for
scripting. The original shell script is a sample GIT commit hook,
quoted in the comments:

┌────
│ (*
│ From GIT's sample hooks:
│ ANY-GIT-REPO/.git/hooks/commit-msg.sample
│
│ # Called by "git commit" with one argument, the name of the file
│ # that has the commit message. The hook should exit with non-zero
│ # status after issuing an appropriate message if it wants to stop the
│ # commit. The hook is allowed to edit the commit message file.
│
│ # This example catches duplicate Signed-off-by lines.
│
│ test "" = "$(grep '^Signed-off-by: ' "$1" |
│ sort | uniq -c | sed -e '/^[ ]*1[ ]/d')" || {
│ echo >&2 Duplicate Signed-off-by lines.
│ exit 1
│ }
│
│ *)
│ module H = Hashtbl
│
│ let commit_msg = Sys.argv.(1)
│ let ht = H.create 5
│ let () =
│ for_each_line ~fname:commit_msg @@ fun l ->
│ if is_prefix "Signed-off-by: " l <> None then begin
│ if H.find_opt ht l <> None then begin
│ prerr_endline "Duplicate Signed-off-by lines.";
│ exit 1
│ end else
│ H.add ht l ()
│ end
└────

Although the OCaml script seems to have more characters, one doesn't
need to type them all. Scripts like that are meant to be entered in an
editor; even ancient editors have completion facilities.

Looking at the original shell script brings despair, and drives me
right towards Unix Haters. Not only the script is algorithmically
ugly: if a duplicate signed-off line occurs near the beginning, we can
report it right away and stop. We don't need to read the rest of the
commit message, filter it, sort it, precisely count all duplicates and
filter again. Not only the script gratuitously wastes system resources
(read: the laptop battery) by launching many processes and allocating
communication buffers. Mainly, the script isn't good at its primary
purpose: it isn't easy to write and read. Pipeline composition of
small stream processors is generally a good thing – but not when each
stream processor is written in its own idiosyncratic
language. Incidentally, I have doubts about the script: I think that
quotes around $1 are meant to be embedded; but why they are not
escaped then? Probably it is some edge case of bash, out of several
0thousands.

In contrast, OCaml script does exactly what is required, with no extra
work. Everything is written in only one language.

letters 0.2.0
═════════════

Archive: <https://discuss.ocaml.org/t/ann-letters-0-2-0/6307/1>

Miko announced
──────────────

Getting this release done took a bit longer than expected due to some
real life factors, but finally here it is.

This one mainly focuses on the most requested features and
improvements like simplifying configuration around CA certificates,
provides some basic documentation and additionally adds support for
`multipart/alternative' emails with combined HTML and plain text
content.

jerben then added
─────────────────

Link to Github: <https://github.com/oxidizing/letters>

raylib-ocaml 0.1.0
══════════════════

Archive: <https://discuss.ocaml.org/t/ann-raylib-ocaml-0-1-0/6313/1>

Tobias Mock announced
─────────────────────

I'd like to announce the first version of [raylib-ocaml], a binding to
the awesome [raylib] game development library. The release can be
found on opam as ["raylib"].

The bindings are nearly complete, as far as functions and types go,
but only a subset was tested so far. I will work on bringing more of
the numerous examples of the C version to OCaml in the future.

Currently, raylib-ocaml only works on Linux, but I plan to support
Windows (and possibly other targets) in the future.

Feel free to give it a spin and please report any issues you run into.

[raylib-ocaml] <https://github.com/tjammer/raylib-ocaml>

[raylib] <https://www.raylib.com/>

["raylib"] <https://opam.ocaml.org/packages/raylib/>

OCaml Workshop 2020 Online Conference is live now
═════════════════════════════════════════════════

Archive:
<https://discuss.ocaml.org/t/ocaml-workshop-2020-online-conference-is-live-now/6287/30>

Deep in this thread, Didier Wenzek announced
────────────────────────────────────────────

[OCaml 2020 All Videos]

[OCaml 2020 All Videos]
<https://www.youtube.com/playlist?list=PLKO_ZowsIOu5fHjRj0ua7_QWE_L789K_f>

Other OCaml News
════════════════

>From the ocamlcore planet blog
──────────────────────────────

Here are links from many OCaml blogs aggregated at [OCaml Planet].

• [BuckleScript Good and Bad News]
• [What the interns have wrought, 2020 edition]
• [Coq 8.12.0 is out]

[OCaml Planet] <http://ocaml.org/community/planet/>

[BuckleScript Good and Bad News]
<http://psellos.com/2020/08/2020.08.east-van-girls.html>

[What the interns have wrought, 2020 edition]
<https://blog.janestreet.com/what-the-interns-have-wrought-2020/>

[Coq 8.12.0 is out] <https://coq.inria.fr/news/coq-8-12-0-is-out.html>

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@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/>

[-- Attachment #2: Type: text/html, Size: 34062 bytes --]