On this page:
7.1 Package Query Syntax
7.2 Package Query Omissions
7.3 Package Query Classifications
7.4 Parsing a Package Query
7.5 Examples
7.5.1 Specifying an Edition
7.5.2 Specifying Accepted Revisions
7.5.3 Marking Inclusive and Exclusive Endpoints
7.5.4 Omitting Information
7.6 Primitive Package Query Operations
parsed-package-query
well-formed-package-query?
malformed-package-query?
resolved-package-query?
exact-package-query?
package-query?
package-query-variant?
boundary-flags-string?
coerce-parsed-package-query
format-parsed-package-query
make-exact-package-query
resolve-minimum-revision
resolve-maximum-revision
abbreviate-exact-package-query
parse-package-query
7.7 Autocompleting Package Queries
gen:  package-query-defaults
package-query-defaults?
package-query-defaults-implementation/  c
default-package-query-defaults
autocomplete-parsed-package-query
get-default-provider
get-default-package
get-default-edition
get-default-min-revision
get-default-max-revision
get-default-interval-bounds
7.8 Creating Canonical Package Queries
gen:  package-query-canon
package-query-canon?
package-query-canon-implementation/  c
make-canonical-package-query
$package-query-canon
$package-query-canon:  backwards
$package-query-canon:  no-minimum
$package-query-canon:  no-maximum
$package-query-canon:  no-selection
$package-query-canon:  oob
find-revision-number
select-revision-number
8.12

7 Package Queries🔗ℹ

 (require denxi/query) package: denxi

A package query is a colon-separated string used to find package definitions.

7.1 Package Query Syntax🔗ℹ

With no omissions, a query follows this form:

    <provider>:<package>:<edition>:<revision-min>:<revision-max>:<interval-bounds>

e.g. "example.com:htdp:teachers:8:201:ii"

<provider> is, as expected, the name of the package’s provider. This may or may not be the author of the package. A domain name for a provider name is not required, but using one is helpful if your package appears across multiple services.

<package> is the name of the package.

<revision-min> and <revision-max> can each be a revision number or a revision name.

Finally, <interval-bounds> can be "ee", "ie", "ei", or "ii". These characters control if <revision-min> or <revision-max> are interpreted as inclusive or exclusive interval boundaries. The first character controls <revision-min>. The second character controls <revision-max>. If the character is "i", then the boundary is inclusive of the defined revision. If "e", exclusive.

7.2 Package Query Omissions🔗ℹ

To omit a field, use consecutive colons, or leave fields off the end of the string. An omitted field is set to the empty string.

e.g. "example.com:htdp::8::ie", or "example.com:htdp".

When a field is set to the empty string, a fallback value may be used instead. See Autocompleting Package Queries for more information.

The empty string is equivalent to using only default values.

7.3 Package Query Classifications🔗ℹ

A parsed package query is an instance of parsed-package-query.

A well-formed package query is a parsed package query that uses strings for all fields.

A malformed package query is a parsed package query that is not a well-formed package query.

A resolved package query is a well-formed package query where the minimum and maximum revisions are digit strings that can be trivially converted to revision numbers.

An exact package query is a resolved package query where the minimum and maximum revisions form an inclusive interval that matches exactly one version.

7.4 Parsing a Package Query🔗ℹ

Assume that a query Q is bound to a well-formed package query with no omissions. In that case you can construct an instance of parsed-package-query using (apply parsed-package-query (string-split Q ":")).

In the general case where fields may be omitted, any missing fields should be set to the empty string like so:

(define (parse-package-query s)
  (define user-defined (string-split s ":"))
  (define num-fields (length user-defined))
  (apply parsed-package-query
         (build-list (procedure-arity parsed-package-query)
                     (λ (i)
                       (if (< i num-fields)
                           (list-ref user-defined i)
                           "")))))

7.5 Examples🔗ℹ

Field positions are important. You can still create a query for just calculator, but calculator would be intepreted as the provider, and not the package name.

7.5.1 Specifying an Edition🔗ℹ

If you prefer a scientific calculator, the package author can provide that design under a different edition. Specify an edition using the next field.

example.com:calculator:scientific

7.5.2 Specifying Accepted Revisions🔗ℹ

The next field is for requesting a specific revision of a package.

example.com:calculator:scientific:288

example.com:calculator:scientific:open-beta

A revision can be an exact nonnegative integer or a name. Names are aliases for numbers.

What about version ranges? Just add another revision to act as the maximum accepted revision.

example.com:calculator:scientific:288:288

From here we can change the endpoints of the interval to accept alternative packages. This is useful if some implementations are not available.

example.com:calculator:scientific:102:288

7.5.3 Marking Inclusive and Exclusive Endpoints🔗ℹ

By default, revision intervals are inclusive of their endpoints. You can add flags to mark the interval as inclusive or exclusive of each endpoint. Use the letter i for inclusive, and e for exclusive. In the below form, revision 288 will not match this query because of the e on the right side of the two flags.

example.com:calculator:scientific:102:288:ie

Using integer interval notation:

Marking exclusive bounds are useful with revision names. The below query requests a scientific calculator’s closed beta implementation, up to but not including the production-ready revision.

example.com:calculator:scientific:closed-beta:production:ie

If the author did not define a revision name marking the end of a beta, then you would have to know the revision number in advance of writing the query. With the interval flags, you do not have to know any revision numbers.

When resolving revision names, Denxi will raise an error for queries like these because they each resolve to a backwards interval:

example.com:calculator:scientific:production:closed-beta

example.com:calculator:scientific:9:0

example.com:calculator:scientific:3:3:ee

7.5.4 Omitting Information🔗ℹ

You may omit fields in package queries. Two contiguous colons will set the associated field to the empty string. Any contiguous colon sequence at the end of a query is implied and does not need to be typed.

example.com:calculator::production

Even the empty string is a valid package query. In fact, "" and ":::" parse the same way.

7.6 Primitive Package Query Operations🔗ℹ

struct

(struct parsed-package-query (provider-name
    package-name
    edition-name
    revision-min
    revision-max
    interval-bounds))
  provider-name : string?
  package-name : string?
  edition-name : string?
  revision-min : string?
  revision-max : string?
  interval-bounds : string?
A parsed form of a package query.

procedure

(well-formed-package-query? v)  boolean?

  v : any/c

procedure

(malformed-package-query? v)  boolean?

  v : any/c

procedure

(resolved-package-query? v)  boolean?

  v : any/c

procedure

(exact-package-query? v)  boolean?

  v : any/c
Each procedure returns #t if v matches the respective rule in Package Query Classifications.

Returns #t if the input value is suitable for use as an argument to parse-package-query.

Returns #t if the input value is suitable for use as an argument to coerce-parsed-package-query. Specifically, the input can be a string, or an instance of parsed-package-query.

Returns #t if the argument is a suitable value for package-query-interval-bounds.

Returns a parsed-package-query from a variant value type.

Converts a parsed-package-query to a string, with no validation performed on the fields in advance. The fields set in query are joined into the string as-is.

procedure

(make-exact-package-query provider 
  name 
  revision-number) 
  exact-package-query?
  provider : string?
  name : string?
  revision-number : revision-number?
Returns an exact package query built from the arguments.

procedure

(resolve-minimum-revision query    
  find-revision-number)  any/c
  query : parsed-package-query?
  find-revision-number : (-> string? any/c)
Returns (parsed-package-query-revision-min query) as a revision number, taking boundary flags into account.

Pass the implementation for translating revision names to revision numbers as find-revision-number. When necessary, resolve-minimum-revision will apply find-revision-number to a revision name to resolve.

find-revision-number may return something other than a revision number. resolve-minimum-revision will return that value as-is. find-revision-number may also raise an error, which will be caught and returned only if it’s not an instance of exn:break. Leverage these rules to understand why a particular resolution failed (e.g. a web service 404s for a minimum revision name, but not the maximum).

If find-revision-number returns a revision number, it is adjusted according to (parsed-package-query-interval-bounds query) using make-minimum-revision-number.

procedure

(resolve-maximum-revision query    
  find-revision-number)  any/c
  query : parsed-package-query?
  find-revision-number : (-> string? any/c)

procedure

(abbreviate-exact-package-query query)  string?

  query : exact-package-query?
Like format-parsed-package-query, except the resulting string omits more fields. Since query is exact, this does not result in lost information.

procedure

(parse-package-query str)  parsed-package-query?

  str : string?
Converts a string to an instance of parsed-package-query.

7.7 Autocompleting Package Queries🔗ℹ

This section covers autocompleting package queries, which entails replacing empty strings and non-string elements of parsed-package-query instances with well-formed values.

A generic interface for a structure type that predicts missing fields for package queries. The available method definitions are documented in this section.

Returns #t if the sole argument is an instance of a structure that implements at least zero methods of gen:package-query-defaults.

A contract for structure instances that implement at least zero methods of gen:package-query-defaults. The contracts for existing methods match their documented contracts. Such a structure can autocomplete parsed package queries using autocomplete-parsed-package-query.

A default implementation for gen:package-query-defaults.

It implements every method using the same code as the fallbacks for the generic interface.

procedure

(autocomplete-parsed-package-query autocomplete 
  query) 
  well-formed-package-query?
  autocomplete : package-query-defaults-implementation/c
  query : parsed-package-query?
Replaces all empty strings and non-strings in query with suitable values. autocomplete may opt to preserve empty strings.

procedure

(get-default-provider defaults)  string?

  defaults : package-query-defaults?
A method of gen:package-query-defaults that returns a default value for parsed-package-query-provider-name.

The fallback implementation for this method always returns DEFAULT_STRING.

procedure

(get-default-package defaults provider)  string?

  defaults : package-query-defaults?
  provider : string?
A method of gen:package-query-defaults that returns a default value for parsed-package-query-package-name, in terms of a provider name.

The fallback implementation for this method always returns DEFAULT_STRING.

procedure

(get-default-edition defaults    
  provider    
  package-name)  string?
  defaults : package-query-defaults?
  provider : string?
  package-name : string?
A method of gen:package-query-defaults that returns a default value for parsed-package-query-edition-name, in terms of a provider name and package name.

The fallback implementation for this method always returns DEFAULT_STRING.

procedure

(get-default-min-revision defaults    
  provider    
  package-name    
  edition)  string?
  defaults : package-query-defaults?
  provider : string?
  package-name : string?
  edition : string?
A method of gen:package-query-defaults that returns a default value for parsed-package-query-revision-min, in terms of a provider name, package name, and edition name.

The fallback implementation for this method always returns "0".

procedure

(get-default-max-revision defaults    
  provider    
  package-name    
  edition    
  min-revision)  string?
  defaults : package-query-defaults?
  provider : string?
  package-name : string?
  edition : string?
  min-revision : string?
A method of gen:package-query-defaults that returns a default value for parsed-package-query-revision-max, in terms of a provider name, package name, and edition name.

The fallback implementation for this method always returns DEFAULT_STRING.

A method of gen:package-query-defaults that returns a default value for parsed-package-query-interval-bounds.

The fallback implementation for this method always returns "ii".

7.8 Creating Canonical Package Queries🔗ℹ

Package queries may or may not refer to existing data at some location. They require an authority to state that not only is a package query meaningful, but the authority can direct a program to the data using an exact variant of the query that it will provide.

A package query canon (or just “canon” in the context of this section) is an implementation of gen:package-query-canon that represents the authority. A package query produced using make-canonical-package-query is said to be in canonical form with respect to a canon. We can also call the result a canonical package query.

A canonical package query is an exact package query. There is no predicate for canonical package queries, so the only meaningful difference is that canonical package queries are expected to work with the canon that defines them.

Therefore, make-canonical-package-query represents a social contract for a package query canon to only make valid queries. If it is not able to do this, it should not return a query at all.

A generic interface for a structure type that creates canonical package queries. The available method definitions are documented in this section.

Returns #t if the sole argument is an instance of a structure that implements at least zero methods of gen:package-query-canon.

A contract for structure instances that implement all methods of gen:package-query-canon. The contracts for existing methods match their documented contracts. Such a structure is suitable for use with make-canonical-package-query.

procedure

(make-canonical-package-query 
  [#:force-complete-interval? force-complete-interval?] 
  canon 
  defaults 
  query) 
  (subprogram/c exact-package-query?)
  force-complete-interval? : any/c = #f
  canon : package-query-canon-implementation/c
  defaults : package-query-defaults-implementation/c
  query : package-query-variant?
Returns a subprogram that computes an exact package query in canonical form with respect to canon. In the event of an error, the subprogram log gains at least one $package-query-canon instance.

  1. Autocomplete query using (autocomplete-parsed-package-query defaults query).

  2. Convert all revision names in the output of Step 1 to a revision number interval.

  3. Select exactly one revision number from the interval defined in Step 2 that points to an available package definition.

  4. Return an exact package query using the output of Step 3.

In the event only one of the two revision interval endpoints is resolved, the return value depends on force-complete-interval?. If force-complete-interval? is a true value, the process will skip Step 3 and use the only available revision number to perform Step 4. Be careful with this option, because it discards the error information for the unresolved boundary.

struct

(struct $package-query-canon $message (user-query
    autocompleted-query)
    #:prefab)
  user-query : package-query?
  autocompleted-query : package-query?
A message about a failure to convert a package query to canonical form.

user-query reflects what was passed to make-canonical-package-query. autocompleted-query is the result of applying autocomplete-parsed-package-query to user-query in advance of the attempted conversion.

struct

(struct $package-query-canon:backwards $package-query-canon
  (alleged-minimum
   alleged-maximum))
  alleged-minimum : revision-number?
  alleged-maximum : revision-number?
A package query canon successfully converted revision names in a query to revision numbers, but the numbers form the backwards interval {alleged-minimum .. alleged-maximum}.

A package query canon could not resolve the revision name for the minimum revision of a package query.

hint is the value—or a derived serializeable value—created by applying resolve-minimum-revision to the autocompleted query. It may clarify why the revision name did not resolve.

struct

(struct $package-query-canon:no-selection $package-query-canon
  (minimum
   maximum
   hint))
  minimum : revision-number?
  maximum : revision-number?
  hint : any/c
A package query canon resolved all revision names to revision numbers, but could not select the best fit among them.

hint is an implementation-specific value meant to explain why this is the case.

struct

(struct $package-query-canon:oob $package-query-canon (minimum
    maximum
    selection))
  minimum : revision-number?
  maximum : revision-number?
  selection : revision-number?
A package query canon resolved all revision names to revision numbers, but selected a revision number outside of the user’s {minimum ... maximum} interval.

procedure

(find-revision-number canon    
  provider    
  package    
  edition    
  revision-name)  any/c
  canon : package-query-canon-implementation/c
  provider : string?
  package : string?
  edition : string?
  revision-name : string?
A method of gen:package-query-canon that returns either the revision number named by revision-name, or an implementation-defined value representing why a revision number cannot be returned.

procedure

(select-revision-number canon    
  provider    
  package    
  edition    
  revision-min    
  revision-max)  any/c
  canon : package-query-canon-implementation/c
  provider : string?
  package : string?
  edition : string?
  revision-min : revision-number?
  revision-max : revision-number?
A method of gen:package-query-canon used by make-canonical-package-query, after find-revision-number. It returns either a revision number or an implementation-defined value representing why a revision number cannot be returned.

revision-min and revision-max are boundaries to an inclusive integer interval. The revisions they represent may not exist where definitions would be stored. If select-revision-number returns a revision number, it will be constrained to {revision-min ... revision-max} to represent the best available revision (Typically this is the revision number closest to revision-max).

Warning: Only return a revision number from your implementation if the caller may assume that the package definition it references actually exists. Failure to do so will cause a runtime error.