Previous week Up Next week

Hello

Here is the latest OCaml Weekly News, for the week of February 10 to 17, 2015.

  1. Ocveralls 0.1 release
  2. First public release of the OCaml Memory Profiler
  3. Core Suite 112.17.00
  4. Other OCaml News

Ocveralls 0.1 release

Archive: https://sympa.inria.fr/sympa/arc/caml-list/2015-02/msg00076.html

Julien Sagot announced:
Some of you may already know the "patched-bisect" and
the ocveralls.sh script, that allowed you to send
coverage informations to http://coveralls.io service.

Inspired by this patched bisect and the script,
ocveralls is now available as a standalone
program, so you do not need to patch bisect
anymore.

Use bisect as you used to, and run ocveralls on coverage
data (the same way you would use bisect-report) in order
to generate the json file to be sent via coveralls API.
(Example in README.MD file)

ocveralls 0.1 is already available via opam.

Sources: https://github.com/sagotch/ocveralls
Bug report and suggestions are welcome:
https://github.com/sagotch/ocveralls/issues

Hope you will like it!

PS: If you want to test ocveralls locally, set the --repo_token option
to whatever you want or ocveralls will fail trying to determine on
what CI plateform it is running.
      

First public release of the OCaml Memory Profiler

Archive: https://sympa.inria.fr/sympa/arc/caml-list/2015-02/msg00079.html

Çagdas Bozman announced:
  On behalf of the OCamlPro team, I am pleased to announce the public
release of the OCaml Memory Profiler. This tool suite inspects the
memory of OCaml applications at run-time to produce various offline
reports on its usage.

Homepage: http://memprof.typerex.org/
Usage: http://memprof.typerex.org/free-version.php
Support: http://memprof.typerex.org/report-a-bug.php
Gallery of examples: http://memprof.typerex.org/gallery.php
Commercial: http://memprof.typerex.org/commercial-version.php

  The OCaml Memory Profiler contains an enhanced OCaml distribution
(based on 4.01.0) that is used to build an instrumented version or your
OCaml applications. Instrumented programs can inspect their memory
on-demand to output memory dumps. These dumps contain the static
type and allocation site of all allocated values (among other information).
They are analyzed offline (outside of the application process) to produce
reports that are displayed in your browser (see the gallery of examples).

  The OCaml Memory Profiler comes in two different forms: an Online
Version and a Commercial Version.

The Online Version can be used by everyone, it provides an OPAM switch
and a tool, ocp-memprof. Once an application has been compiled in the
switch, ocp-memprof can be used to trigger the output of memory
snapshots, that are locally analyzed to generate a summary. The
summary is sent to our online servers to be displayed in the gallery
of examples.

The Commercial Version improves on the Online Version by removing the
need for the online servers: summaries can be displayed locally, to
provide complete development privacy. It also comes with support, to
install and execute the tool (Basic Support option), to help
understanding the results and fix applications (Advanced Support option)
and with access to the sources (Extended Support option). Other
additional features are available in the Commercial Version, such as
more precise root descriptions and more frequent updates.
      

Core Suite 112.17.00

Archive: https://sympa.inria.fr/sympa/arc/caml-list/2015-02/msg00102.html

Jeremie Dimino announced:
I am pleased to announce the 112.17.00 release of the Core suite.

The following packages were upgraded:

- async
- async_extended
- async_extra
- async_kernel
- async_parallel
- async_smtp
- async_ssl
- async_unix
- bignum
- bin_prot
- core
- core_bench
- core_extended
- core_kernel
- custom_printf
- email_message
- jenga
- ocaml_plugin
- pa_ounit
- patdiff
- rpc_parallel
- sexplib
- textutils
- typerep
- typerep_extended

Files for this release are available on our website and all packages
are in opam:

  https://ocaml.janestreet.com/ocaml-core/112.17/files

We also have generated API documentation for this release. The result
is not perfect as the tools are still in development. You can find it
here:

  https://ocaml.janestreet.com/ocaml-core/112.17/doc/

Here is list of changes for this version:

# 112.17.00

## async

Added tests and updated examples

## async_extended

- Added `Interactive` module for terminal interaction with users by
  command-line executables.

  `Interactive` was previously in `Iron_common`.
- In `Process`, added an `?env` argument to some functions.
- Allowed `Command_rpc` implementations to access the
  `Rpc.Connection.t` used to invoke them.

  There is an option to invoke `Command_rpc` implementations via sexp
  communication instead of `Rpc`, so implementations are given a value
  of a variant type `Sexp | Bin_io of Rpc.Connection.t`.
- Added `Resource` module, which abstracts the idea of acquiring and
  releasing a handle to a resource.

## async_extra

- Modernized code style in `Async_extra`.

  This was mostly whitespace changes, plus deletions of unneeded
  module paths.
- Added `with sexp_of` to `Tcp.Where_to_listen` for debugging.
- In `Versioned_typed_tcp`, check that the writer on the other side is
  not closed in the `Pass_on` case.
- Added a new way to implement an RPC, where the implementation
  doesn't return a deferred.

  This "blocking" rpc implementation guarantees that the rpc will in
  fact be fully dispatched by the time the implementation returns.

  This can be used to skip the deserialization of the query, and
  instead operate directly in the message contents as received.

  Also, fixed a bug in which the query handler (and therefore the
  connection state) was being called before the internal async rpc
  handshake was finished.
- Added an optional `job_tag` argument to `Sequencer_table.enqueue`,
  to display for debugging.
- Added an optional argument to TCP-connection functions to control
  the local interface used to connect.

  To implement this this, extended `Tcp.connect` to work on a bound socket.
- Added `with compare` to `Process.Output.t`.
- Added `Process.Output.Stable` module.
- Exposed concrete rpc in `Versioned_rpc.Both_convert`.
- Changed `Cpu_usage` to take its first sample after waiting, rather
  than immediately.

  This fixes a problem where the first sample could be `NAN` or `Inf`.
- Made `Log` buffer-age be unlimited, to avoid exceptions when log
  writes are blocked for long periods.
- Improved `Log.t_of_sexp`'s error message.
- Changed `Rpc.Connection.client` and `with_client` to raise some
  errors which had been dropped during RPC dispatch.

  Previously, errors dispatching `Rpc.Rpc.t`'s were handled correctly
  and returned or raised by the relevant dispatch functions.  However,
  errors that occurred in the middle of handling a `Rpc.Pipe_rpc.t` or
  `Rpc.State_rpc.t` were swallowed.  This is because they happen after
  the dispatch functions have returned, and the dispatch interface
  doesn't allow for errors to occur in the middle of the pipe -- they
  must be raised to the monitor in effect when the `Rpc.Connection.t`
  is created.  Errors could be raised to the effective monitor at the
  dispatch call, but the failure causes the entire connection to go
  into error, so the connection's monitor seems more appropriate.
  These errors weren't propagated to the caller because `client` and
  `with_client` both used `Monitor.try_with` without `rest` handling,
  causing /any/ errors caused while handling the connection (after the
  `Connection.t` has been returned to the user) to be dropped.
- In `Rpc`, exposed some optional parameters from the `Tcp` module:
  `?max_pending_connections` and `?buffer_age_limit`.

## async_kernel

- Fixed a space leak in `Clock.Event.abort`, making it free the job
  that was created and stored in the timing wheel.
- Moved `Scheduler.yield` from `Async_unix`.
- Fixed a bug in `Scheduler.yield_every`, so that it doesn't
  initialize the scheduler until the staged function is called.
- Added `concat_map` function to `Monad_sequence` interface.
- Added `Shutdown.shutdown_on_unhandled_exn`.
- Added some functions to `Deferred.Or_error` to parallel
  `Core.Or_error`: `errorf`, `tag`, `tag_arg`.

  ```ocaml
  val errorf : ('a, unit, string, _ t) format4 -> 'a
  val tag : 'a t -> string -> 'a t
  val tag_arg : 'a t -> string -> 'b -> ('b -> Sexp.t) -> 'a t
  ```
- Added `Gc.Alarm`, an Async-friendly wrapper around
  `Core.Gc.Expert.Alarm`.
- Removed `Gc.Expert`, whose functions are superseded by
  Async-friendly functions in `Gc` proper.
- Added `Pipe.read_now_at_most`.
- Changed `Pipe.merge` to check whether its output is closed, and if
  so, stop rather than write to it (which raised).

  Also, made `Pipe.merge` close its inputs whenever its output is
  closed.
- Changed `Clock.at` to return `Deferred.unit` if it is supplied a
  time in the past.

  Previously, it would create an empty ivar and a job to fill it that
  would run in the next cycle.
- Changed `Clock.Event.status` to return ````Will_happen_at of
  Time.t``` rather than ````Waiting```, if applicable.
- Added `Ivar.create_full`.
- Moved the use of `Linux_ext` to `Async_unix`.

  This is one of the necessary steps in making `Async_kernel` depend
  on `Core_kernel` rather than `Core`.

## async_parallel

- Modernize the code

## async_smtp

Moved from janestreet-alpha

## async_ssl

- moved ffi_bindings and ffi_stubgen in separate libraries

## async_unix

- Moved `Scheduler.yield` to `Async_kernel`.
- Added `Reader.load_annotated_sexp*` functions.

  These are like the existing `Reader.load_sexp*` functions, except
  they return annotated sexps rather than sexps.  Having annotated
  sexps is useful so that one can report error positions to the user
  when processing values built by the `t_of_sexp_` functions /after/
  they return.  I.e. when there aren't syntax errors in the sexps, but
  rather semantic errors detected later.
- Removed noise and redundancy from `Reader.load_sexp` error messages.
- Added `Writer.save_sexps`, analogous to `Reader.load_sexps`.
- Made `Writer` errors raised by the background flush job include the
  entire `Writer.t`, rather than just the `Fd.t`.
- Added to `Writer.transfer` an optional argument to limit the number
  of values read at once from the pipe.

  The old behavior is to have no limit and remains the default.
- Added to `Writer` some missing checks for functions that should
  ensure the input writer isn't closed.
- Changed `Scheduler.run_cycles_until_no_jobs_remain` to pause so that
  alarms scheduled to fire in the past actually fire.

  This is necessary because of the timing-wheel, which doesn't
  guarantee to fire an event until alarm-precision after it was
  scheduled.

  Without this change, some tests unexpectedly fail, due to jobs not
  running that should have.

## bignum

- Added `Bigint.random` function, which produces a uniformly
  distributed value.

## bin_prot

- Added `Bin_prot.Blob`, formerly known as `Core_extended.Wrapped`,
  which has efficient handling of size-prefixed bin-io values in cases
  where serialization can be bypassed.

## core

- Deprecated the single-line files that simply `include` the
  corresponding Core_kernel module.  Those are unnecessary, because
  people should use `Core.Std`.

  We will keep these aliases around for a version before deleted them
  entirely.
- Changed finalizers and signal handlers to, upon an unhandled
  exception, exit nonzero rather than asynchronously raise.
- Removed `Time.Zone.find_office`.

  Replaced uses with the still-blocking `Time.Zone.find_exn`
- Made many changes to `Time` to make the time zone explicit instead
  of implicitly using the local timezone.

  Added `zone:Time.Zone.t` parameters to many functions.  In almost
  all cases, used `~zone:Time.Zone.local` where previously it was
  implicit.

  Removed `of_local_ofday` and `to_local_ofday` in favor of the
  explicit versions (with `Time.Zone.local`).

  Removed `Time.Zone.machine_zone ()` in favor of `local`.
- Exported `Core.Std.With_return`.
- Exposed `Core.Std.with_return_option`.
- Fixed `Time_ns.Ofday.of_span_since_start_of_day` to check its input.
- Changed `Time_ns.to_span` and `of_span` to round to microseconds,
  for round trippability.
- Added `Unix.Error` module, for the `Unix.error` type.
- Added `Unix.Syscall_result`, a new abstract type representing the
  result of a Unix system call as an `int`, to avoid allocation.

  A lot of Unix system calls return an integer on success, so for ones
  that are called a lot, we can encode errors as `-errno`.  This
  module abstracts this concept.
- Changed `Iobuf.recvmmsg` functions to return the new
  `Unix.Syscall_result`.
- Changed `Unix.exec`'s `?env` argument to support extending the
  environment in addition to replacing it.
- Added `with compare` to `Unix.Exit.t` and `Unix.Exit_or_signal.t`.
- Moved `Backtrace` to `Core_kernel`.

  Deleted `backtrace_stubs.c`, now that we have `Printexc.get_callstack`.
- Changed `Bigstring.read_assume_fd_is_nonblocking` and
  `send_nonblocking_no_sigpipe` to return `Unix.Syscall_result.t`, to
  reduce allocation.
- Changed `Iobuf.send_nonblocking_no_sigpipe` to handle `EINTR` like
  `EAGAIN`, instead of raising.
- Added `Command.Spec.char`.
- Changed `Process_env.parse_ssh_client` to accept an `SSH_CLIENT`
  that is just IP address without ports.

## core_bench

- Updated code to follow some core changes

## core_extended

- Added functions to `Low_level_debug` to get a sexp or string
  representation of any type.

  This could  be handy when debugging polymorphic code.
- Renamed `String.is_substring` to `is_substring_deprecated`.  Use
  `Core.String.is_substring` instead.
- Fixed a bug in `Bin_io_utils.save`.
- Made `Unix.Mac_address` match `Hashable.S`.

## core_kernel

- Added `List.is_prefix`.

  ```ocaml
  val List.is_prefix : 'a t -> prefix:'a t -> equal:('a -> 'a -> bool) -> bool
  ```
- Made `String_id.Make` functor generative, which exposes that the
  result has `type t = private string`.

  Previously the result of `String_id.Make` didn't expose `type t =
  private string` due to a type-checker bug:

  * http://caml.inria.fr/mantis/view.php?id=6485
  * http://caml.inria.fr/mantis/view.php?id=6011

- Used generative functors, e.g. for `Unique_id`.

  Used generative functors (new feature in 4.02) where previously we
  used dummy `M : sig end` arguments in the signature and `(struct
  end)` when applying the functor.

  Just to note the difference between applicative and generative
  functors.  Suppose we have:

  ```ocaml
  module F (M : sig end) : sig type t end
  ```

  and we apply it several times

  ```ocaml
  module A = F (struct end)
  module B = F (struct end)
  module C = F (String)
  module D = F (String)
  ```

  Then we have that `A.t <> B.t` but `C.t = D.t`.  This can lead to
  subtle bugs, e.g. `Unique_id.Int (Unit)`.  Note that it is perfectly
  valid to apply any module to `F`, even though that is certainly not
  what we want.

  In 4.02, we can explicitly say that functor generates new types,
  i.e. it is generative. For this we use argument `()`.  So `F`
  becomes

  ```ocaml
  module F () : sig type t end
  ```

  You can only apply `F` to `()` or `(struct end)` but each
  application yields a new type `t`.

  ```ocaml
  module A = F ()
  module B = F ()
  module C = F (struct end)
  module D = F (String) (* illegal *)
  ```

  and now `A.t`, `B.t` and `C.t` are all different.

  Note that `F (struct end)` is still allowed but was converted to to
  `F ()` for consistency with signatures.

  Propagated generativity where necessary.  If inside a functor we use
  generative functor that creates new types, then we also need to make
  the enclosing functor generative.

  For functors that don't create types (like `Async.Log.Make_global`),
  generative or applicative functors are the same, but the syntax of
  generative functors is lighter.
- Exported `Core_kernel.Std.With_return`.
- Exposed the record type of `Source_code_position.t`.
- In `Weak_hashtbl.create`, exposed the `?growth_allowed` and `?size`
  arguments of the underlying `Hashtbl.create`.
- Added `with compare` to `Array`.
- Sped up `Int.pow`.

  Benchmarks before:

  | Name                                          |     Time/Run | mWd/Run | Percentage |
  |-----------------------------------------------|--------------|---------|------------|
  | [int_math.ml:int_math_pow] random[ 5] x 10000 | 140_546.89ns |         |     53.98% |
  | [int_math.ml:int_math_pow] random[10] x 10000 | 173_853.08ns |         |     66.77% |
  | [int_math.ml:int_math_pow] random[30] x 10000 | 219_948.85ns |         |     84.47% |
  | [int_math.ml:int_math_pow] random[60] x 10000 | 260_387.26ns |         |    100.00% |
  | [int_math.ml:int_math_pow] 2 ^ 30             |      11.34ns |         |            |
  | [int_math.ml:int_math_pow] 2L ^ 30L           |      21.69ns |   3.00w |            |
  | [int_math.ml:int_math_pow] 2L ^ 60L           |      22.95ns |   3.00w |            |

  and after:

  | Name                                          |     Time/Run | mWd/Run | Percentage |
  |-----------------------------------------------|--------------|---------|------------|
  | [int_math.ml:int_math_pow] random[ 5] x 10000 | 105_200.94ns |         |     80.78% |
  | [int_math.ml:int_math_pow] random[10] x 10000 | 117_365.82ns |         |     90.12% |
  | [int_math.ml:int_math_pow] random[30] x 10000 | 130_234.51ns |         |    100.00% |
  | [int_math.ml:int_math_pow] random[60] x 10000 | 123_621.45ns |         |     94.92% |
  | [int_math.ml:int_math_pow] 2 ^ 30             |       8.55ns |         |            |
  | [int_math.ml:int_math_pow] 2L ^ 30L           |      22.17ns |   3.00w |      0.02% |
  | [int_math.ml:int_math_pow] 2L ^ 60L           |      22.49ns |   3.00w |      0.02% |
- Removed the old, deprecated permission phantom types (`read_only`,
  etc.) and replaced them with the new =Perms= types.

  The old types had subtyping based on covariance and `private` types.
  The new types have subtyping based on contravariance and dropping
  capabilities.

  Renamed `read_only` as `read`, since `Perms` doesn't distinguish
  between them.

  The idiom for the type of a function that only needs read access
  changed from:

  ```ocaml
  val f : _ t -> ...
  ```

  to

  ```ocaml
  val f : [> read ] t -> ...
  ```

  This mostly hit `Iobuf` and its users.
- Added `String.is_substring`.
- Added `With_return.prepend`, and exposed `With_return.t` as
  contravariant.

  ```ocaml
  (** [prepend a ~f] returns a value [x] such that each call to
[x.return] first applies [f]
      before applying [a.return].  The call to [f] is "prepended" to
the call to the
      original [a.return].  A possible use case is to hand [x] over to
an other function
      which returns ['b] a subtype of ['a], or to capture a common
transformation [f]
      applied to returned values at several call sites. *)
  val prepend : 'a return -> f:('b -> 'a) -> 'b return
  ```
- Moved the `Gc` module's alarm functionality into a new
  `Gc.Expert.Alarm` module.

  The was done because the Gc alarms introduce threading semantics.
- Exposed modules in `Core_kernel.Std`: `Int_conversions`,
  `Ordered_collection_common`
- Removed `Pooled_hashtbl` from `Hashable.S`, to eliminate a
  dependency cycle between `Int63` and `Pool`.

  This was needed to use `Int63` in `Pool`.  Previously, `Int63 <- Int
  <- Hashable <- Pool`, which made it impossible to use `Int63` in
  `Pool`.

  So, we are removing the dependency `Hashable <- Pool`, simplifying
  `Hashable` to not include `Pooled_hashtbl`, and letting users call
  the `Pooled_hashtbl` functor directly when necessary.
- Added to `Pool.Pointer.Id` conversions to and from `Int63`.
- Made `Pooled_hashtbl.resize` allocate less.
- Removed `Pool.pointer_of_id_exn_is_supported`, which was always
  `true`.
- Added `with compare` to `Info`, `Error`, `Or_error`.
- Moved `Backtrace` from `Core`
- In C stubs, replaced `intxx` types by `intxx_t`.

  Following this: http://caml.inria.fr/mantis/view.php?id=6517

  Fixes #23
- Removed `Backtrace.get_opt`, which is no longer necessary now that
  `Backtrace.get` is available on all platforms.
- Added module types: `Stable`, `Stable1`, `Stable2`.
- Exposed `Core_kernel.Std.Avltree`.
- Removed from `Binary_packing` a duplicated exception,
  `Pack_signed_32_argument_out_of_range`.

  Closes #26
- Made `Info`, `Error`, and `Or_error` stable.

  The new stable serialization format is distinct from the existing
  unstable serialization format in the respective modules, which wasn't
  changed.
- Add `Sequence.Step.sexp_of_t`.

## core_profiler

Initial release

## custom_printf

- Changed `%{M.x}` to call `M.x` instead of `M.Format.x`.

  This is more natural and makes it easy to call arbitrary other
  functions.
- Added syntax `%{M#x}`, which calls `M.to_string_x`.

  This makes it easy to use existing modules, since calling functions
  `to_string` or `to_string_x` is already the convention.

## email_message

Moved from janestreet-alpha

## jenga

- Fixed byte-compile targets to avoid stale artifact deletion of
  `.for-byte-compile.cmt` file when compilation fails.

  This avoids polling jenga trigger loop.
- Show `Removed stale build artifact` messages only when `-act` flag is given.
- Extended Jenga API with `val file_existence : Path.t -> unit t`.

  `file-existence` has same relationship to `file-exists` as
  `glob_change` has to `glob_listing`.
- Fixed memory leak in tenacious hearts by using weak references and
  finalizers.

  * Strip code for obsolete versions of hearts.
  * Strip code for `OLD_TENACIOUS=true`.
  * Ensure `Ring` support preemptive calls to `detach`.  Add ring tests.
  * Keep message showing `Live(Kb-delta)`.
- Fixed curly braces in globs.
- Throttled calls to `Writer.save`, to fix the `too many open files`
  bug.

  Throttled calls to `Writer.save` from `save_description.run` sharing
  the same throttle used for all FD access, with
  `~max_concurrent_jobs:500`
- Added to `jenga -progress` `~save=XXX`, the number of calls to
  `Writer.save` in `Progress.saves_run`.

## ocaml_plugin

- Fixed spurious `interface mismatch` error when a plugin cache is
  shared by incompatible compilers.

  When a plugin cache directory is used by several executables with
  incompatible cmis/compilers, and the cache config option
  `try_old_cache_with_new_exec` is set to true, this could lead to the
  following error:

  ```ocaml
  Plugin failed: (ocaml_dynloader.ml.Dynlink_error "interface mismatch")
  ```

  This feature fixes this.

  Since it modifies some record, for later changes it seems easier and
  more conservative to allow field additions without breaking older
  version.  Thus we allow extra fields in persisted records.

  ```ocaml
  let t_of_sexp = Sexp.of_sexp_allow_extra_fields t_of_sexp
  ```

  New executables can read both old and new caches, but old
  executables will either blow away new caches, or if the config says
  the cache is read-only, fail.

  Take the chance to modernize part of the code.
- Switched tests to unified tests.
- Fixed bugs dealing with paths with spaces in them.
- Check that plugins have the expected type before running them rather
  than after, which is what one would expect.

  Also check that runtime and compile types match in
  `check_ocaml_src_files` and
  `compile_ocaml_src_files_into_cmxs_file`.

## pa_ounit

- only spend time to format test description when tests are run

## patdiff

- The call to Pcre.full_split in patdiff_core.ml rely on a bug of
  pcre-ocaml <= 7.1.2.

  To get the same behavior with pcre-ocaml >= 7.1.3 we need to pass
  ~max:(-1).

  See this bug for more details:

     https://github.com/mmottl/pcre-ocaml/issues/1

## rpc_parallel

- Follow changes in Async RPC

## sexplib

- Added `sexp_of_` support for GADTs, and remove the not-quite-working
  support for `of_sexp`.

## textutils

- Added a `~narrow` argument to `Text_graph.render`

## typerep

- Split out typerep_extended which is now using core_kernel

## typerep_extended

- typerep_extended now use core_kernel
      

Other OCaml News

From the ocamlcore planet blog:
Thanks to Alp Mestan, we now include in the OCaml Weekly News the links to the
recent posts from the ocamlcore planet blog at http://planet.ocaml.org/.

Fold left via fold right:
  http://shayne-fletcher.blogspot.com/2015/02/fold-left-via-fold-right.html

Installing OCaml for MacOS Noobie!:
  http://yansnotes.blogspot.com/2015/01/ocaml-for-macos-noobie.html

Senior Development Engineer at Lookingglass Cyber Solutions (Full-time):
  http://functionaljobs.com/jobs/8782-senior-development-engineer-at-lookingglass-cyber-solutions

Full Time: Software Developer (Functional Programming) at Jane Street in New York, NY; London, UK; Hong Kong:
  http://jobs.github.com/positions/0a9333c4-71da-11e0-9ac7-692793c00b45

Smash the Bitcoin Pinata for fun and profit!:
  http://openmirage.org/blog/announcing-bitcoin-pinata

The Bitcoin Piñata!:
  http://amirchaudhry.com/bitcoin-pinata
      

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