Books / Constructions / Chapter 16

Part V · Chapter 16

Reusing a Package

7 min read

Contents of Constructions

In the previous chapter the work rule used the newton, the metre, and the joule. Their definitions lived in a separate package. The acid chapter split things the same way: one package set the chemical vocabulary, another built definitions on it. Time to work out how these parts join.

Start by identifying what the package provides: its public names, the inputs it requires, and the result it promises. A package used by another package is a dependency; the package that uses it is the consumer. We will use chemistry to examine the names, then mechanics to check a pinned dependency and repeat the familiar calculation.

The package name and the names inside it

The chemical vocabulary opens with three lines:

language "law.core" version "0.2";
package openstax.chemistry_acids version "0.1.0";
namespace "urn:openstax:clir:chemistry-acids";

The first line names the language and its version; the second, the package and its version. The third sets the namespace, the shared beginning from which the declarations’ addresses are built.

In an explanation a rule’s address may look like this: urn:openstax:clir:chemistry-acids#AmphiproticDonatesAndAccepts. In this address the namespace comes before # and the rule’s name after it. A label helps us recognize the rule; the full address identifies the declaration that took part, without guessing from a similar name.

We have often met pub before declarations. It marks a name as available to other packages. A declaration without pub may take part in the work of its own package, but other packages cannot refer to it as a public name[^chapter-16-public].

A public name does not establish that its definition is sound or fits the case at hand. pub is about availability. We still need to read the declaration’s meaning and constraints.

What an import means

The acid-definitions package connects the vocabulary with the line:

import openstax.chemistry_acids version "0.1.0";

After that it may refer to the vocabulary’s public declarations. For example, the general question about acids uses the type Species from the connected package:

pub relation is_acid(s: openstax.chemistry_acids::Species) kind institutional {
    label ru unofficial "частица признаётся кислотой по выбранному прочтению";
    label en unofficial "the species is an acid under the selected reading";
}

In the name openstax.chemistry_acids::Species, the package stands to the left of the double colon, the declaration to the right. The consumer refers to the vocabulary’s own Species type; it does not declare a second type with a similar name and assume the two will be treated as one.

But an import line by itself runs nothing. To read the consumer’s declarations, names must be resolved against the dependency’s public declarations. To compute with them, its definitions and rules must also be present in the assembled program. The law test command prepares both when it builds the pinned world. Recognizing names and computing with their definitions are separate steps, even when one command handles them.

Mechanics has a similar line connecting units.si. Here the dependency provides the unit definitions the calculation’s operations use. Recognizing the symbol N and computing a quantity with a known dimension are two different requirements on the assembled set.

What the package provides—and assumes

Take the work calculation from the last chapter. Before use, it helps to write down its conditions in a few lines:

What to establish For this calculation
Which inputs are needed Force and displacement for one calculation
Which units are admissible Units of force and length convertible to N and m
Which answer results Work, written in J
What is assumed Constant force, displacement in its direction
What the calculation does not check Whether these conditions hold; measurement errors

This table summarizes the package’s contract with its user in ordinary language; it is not part of the program. The relation’s signature gives the inputs’ types and order, and the conversion operations check their dimensions. Neither establishes that the force in the real experiment was constant or directed along the displacement. The person applying the model must check that.

Try writing the same summary for the chemical vocabulary: what comes in, what follows, and what remains unchecked? A donates_proton message counts as input information. The definitions package builds its conclusion on that message but does not investigate the substance on its own. A dependency carries these applicability conditions together with its capabilities.

Why a fingerprint is needed next to the version

An import names a version, but repeatability requires pinning the dependency’s exact contents. The law.lock file does this job.

It records the chosen packages, their versions, and content fingerprints. The version names the intended release; artifactHash identifies the compiled dependency, while sourceHash identifies its source snapshot. Both belong to the current lock format. resolutionHash fingerprints the outcome of resolving the dependencies together, rather than one package alone[^chapter-16-lock].

These values follow the package format’s rules. Do not replace them with an arbitrary hash of the printed text or a hand-shortened string. An explanation may show the fingerprint’s start; checking needs the full fingerprint in the file.

The recipient must receive both the pinning and the dependencies themselves. The law.lock file tells what to look for but does not contain the dependency’s program itself. Given the dependency files, the recipient can prepare the calculation without asking the author for the right version.

When a dependency file and its recorded fingerprint disagree, first investigate the cause. Overwriting law.lock to fit whatever is at hand means accepting a new set, not restoring the earlier calculation.

Run the calculation with its dependency

The companion already contains mechanics, its unit definitions, and the lock that pins their contents. First make a working copy. Start in reader/ and choose a directory name that does not already exist:

mkdir mechanics-study
cp -R packs/primitives/natural-sciences/mechanics/. mechanics-study

mechanics-study is now your copy of the package. It contains the rule files, scenarios, law.lock, and deps/. Check that its dependency files agree with the received lock:

law install --project mechanics-study --offline

--project names the package. --offline uses the files already received. A successful check confirms that the pinned dependencies are available; it does not run the work calculation or choose a newer version.

Now run the scenarios:

law test mechanics-study

The ten scenarios should pass, including the 300-joule work calculation. law test reads the package’s manifest, builds the program with its pinned dependencies, and compares each answer with the scenario’s expectations.

For tasks 1 and 2 from Chapter 15, edit the work scenario in mechanics-study/tests/calc-mechanics.lawtest, then run law test mechanics-study again. Begin each exercise with an unchanged copy of that file. Replacing 50 m with 5000 cm keeps the result. After replacing 6 N with 6 J, use the dimension-error expectations specified in Chapter 15, including removal of the rule-application expectation.

Check the pinning separately

Make a second copy for the deliberate error:

cp -R mechanics-study mechanics-bad-pin

In mechanics-bad-pin/law.lock, find the dependency record named units.si. Change only its artifactHash to sha256: followed by 64 zeros. The dependency files themselves stay unchanged. Try the same installation check:

law install --project mechanics-bad-pin --offline

The command refuses the altered lock. The recorded fingerprint no longer agrees with the received set. Read the refusal before changing anything else. Restore the lock from the untouched copy and check again:

cp mechanics-study/law.lock mechanics-bad-pin/law.lock
law install --project mechanics-bad-pin --offline
law test mechanics-bad-pin

The installation check should succeed and the ten scenarios should pass again. The mechanics rules needed no repair: the deliberate error was in the pinning[^chapter-16-restore].

The chemical vocabulary allows the same check. The refusal reason stays the same: the pinned fingerprint and the dependency copy in hand disagree.

What to hand over together

This is the dependency part of the handover; Chapter 18 returns to the full transfer. With the rule files, enclose the manifest law.toml, which names the package and declares its dependencies, the dependency pinning, the dependencies themselves, and sample questions. If the model rests on a text, the saved source materials and their bindings will be needed too.

A stork in flying goggles carries on a rope a little tree with a nest and packed roots.

Equally important are brief instructions: which file to run, which question is asked, what is expected, and which conditions the user must check before calculating. The prepared set must let anyone repeat the answer without remembering how the author assembled it on their own machine.

Now we can connect a package, check its pinned copy, and examine its role in the computation. The fingerprint check establishes agreement with the pinning; the scenarios check particular answers. Neither establishes that every rule is right. A wrong rule can pass tests that never expose its difference from the intended rule. The next chapter builds checks that do.

[^chapter-16-public]: §§23–24 of the Arxo specification tell apart import, declaration visibility, and a dependency’s participation in execution. A name’s publicness does not replace connecting the needed program contents. [^chapter-16-lock]: §11: law.lock sets the pinned information and separates updating dependencies from execution. The mechanics manifest declares the units.si dependency. [^chapter-16-restore]: This edition’s experiment changes only the dependency’s artifactHash in a copied lock; the dependency files stay unchanged. The npm CLI refuses the altered lock. Returning the saved lock restores installation and all ten mechanics scenarios. The historical specification link above describes the earlier contentHash format; the companion’s migration note records the current sourceHash/artifactHash format.

Contents · PDF · EPUB · Original text under CC BY 4.0 · Source-material terms

Constructions

Contents

You’re reading · Part V

Assemble and Hand Over

Reading settings

Text size
Appearance

Preferences and your reading place are saved only in this browser.