{"id":16661178,"url":"https://github.com/sellout/quid-pro-quo","last_synced_at":"2026-04-03T10:36:41.209Z","repository":{"id":41348168,"uuid":"1656483","full_name":"sellout/quid-pro-quo","owner":"sellout","description":"A contract programming library for Common Lisp in the style of Eiffel’s Design by Contract ™.","archived":false,"fork":false,"pushed_at":"2018-06-26T08:59:06.000Z","size":433,"stargazers_count":95,"open_issues_count":7,"forks_count":9,"subscribers_count":8,"default_branch":"master","last_synced_at":"2025-01-19T13:44:23.026Z","etag":null,"topics":["common-lisp","design-by-contract","eiffel","postcondition","preconditions"],"latest_commit_sha":null,"homepage":"","language":"Common Lisp","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/sellout.png","metadata":{"files":{"readme":"README.md","changelog":"ChangeLog","contributing":null,"funding":null,"license":"COPYING","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2011-04-24T12:31:44.000Z","updated_at":"2024-11-12T02:50:51.000Z","dependencies_parsed_at":"2022-08-25T08:00:50.499Z","dependency_job_id":null,"html_url":"https://github.com/sellout/quid-pro-quo","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sellout%2Fquid-pro-quo","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sellout%2Fquid-pro-quo/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sellout%2Fquid-pro-quo/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sellout%2Fquid-pro-quo/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sellout","download_url":"https://codeload.github.com/sellout/quid-pro-quo/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243293794,"owners_count":20268142,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["common-lisp","design-by-contract","eiffel","postcondition","preconditions"],"created_at":"2024-10-12T10:34:03.583Z","updated_at":"2025-12-26T10:45:14.452Z","avatar_url":"https://github.com/sellout.png","language":"Common Lisp","funding_links":[],"categories":["Miscellaneous ##"],"sub_categories":[],"readme":"# Quid Pro Quo\n\nA contract programming library for Common Lisp in the style of Eiffel’s Design by Contract ™.\n\n## What is it all about?\n\nOne main goals of every program is reliability, that is, correctness and robustness. A program is correct if it performs according to its specification, it is robust if it handles situations that were not covered in the specification in a graceful manner. One way to prove the correctness of a program with respect to a (formal) specification is the Hoare calculus. Based on this formal method Bertrand Meyer developed a method of software engineering called Design by Contract ™.\n\nThe principal idea of contract programming is that a class and its clients have a contract with each other: The client must guarantee certain conditions before calling a method specialized on the class (the preconditions), the class guarantees certain properties after the call (the postconditions).  If the pre- and postconditions are included in a form that the compiler can check, then any violation of the contract between caller and class can be detected immediately.\n\n## Support for Contract Programming in Programming Languages\n\nThe language that offers the best support for contract programming is [Eiffel](http://www.eiffel.com), designed by Bertrand Meyer. It is rather difficult to add support for contract programming to most other languages, but not so for Common Lisp: I [Matthias Hölzl] have written a package for Common Lisp that provides support for contract programming. It is still very new and not too well tested so you should expect some rough edges and changes in its future design. There is no larger program depending on this package available, only some silly test cases. Since I intend to use the Quid Pro Quo package for my own programs this should change in the not so distant future.\n\n## Contract Programming in Common Lisp.\n\nOne of the outstanding features of the Eiffel language is that it supports a concept called contract programming. A comprehensive description is given in the following books\n\n\u003e Object Oriented Software Construction, 2nd ed.\n\u003e Bertrand Meyer\n\u003e Prentice Hall PTR, 1997\n\u003e ISBN 0-13-629155-4\n\n\u003e Eiffel: The Language, 2nd ed.\n\u003e Bertrand Meyer\n\u003e Prentice Hall PTR, 1992\n\u003e ISBN ???\n\nbut the key point of contract programming is that the relationship between a class and its clients is specified by a contract: There are certain conditions that the caller of a method specialized on a class has to fulfill so that the method can do its job (the preconditions) and the method guarantees certain things after its completion (the postconditions). Furthermore a class may have certain properties that are always true about that class; these properties are called invariants.\n\nThis file contains an implementation of contract programming for CLOS. Pre- and postconditions as well as invariants are specified by qualified methods of type `contract`; the usual before, after and around method combinations are available for these methods as well.\n\n## Implementation Support\n\n* ABCL – **YES** as of 1.1.1\n* Allegro – **YES** (both ANSI \u0026 modern)\n* CLISP – **YES** but creation invariants are ignored (33 pass, 4 fail)\n* Clozure – **YES**\n* CMUCL – **YES**\n* Corman – NO, it’s not supported by [Closer-MOP][]\n* ECL – NO, `DEFINE-METHOD-COMBINATION` is broken\n* LispWorks – currently fails tests (10 pass, 25 fail)\n* SBCL – **YES**\n* Scineer – ? (would be happy to find someone to test it)\n\n[Closer-MOP]: http://common-lisp.net/project/closer/closer-mop.html\n\n## Usage\n\nPreconditions (`defrequirement`) and postconditions (`defguarantee`) are added to functions. This works for both generic and non-generic functions (but contracts on non-generic functions may do nothing on certain lisp implementations).\n\n```common-lisp\n(defrequirement put (item (stack stack))\n  \"the stack is not full\"\n  (declare (ignore item))\n  (not (full stack)))\n\n(defguarantee put (item (stack stack))\n  (and (not (empty stack))\n       (eq (top-item stack) item)\n       (= (count stack) (1+ (old (count stack))))))\n\n(defguarantee pop-stack ((stack stack))\n  (and (not (full stack))\n       (eq (results) (old (top-item stack)))\n       (= (count stack) (1- (old (count stack)))))\n```\n\nThis simple example illustrates a few things:\n\n* the docstring is included in any contract failure messages,\n* the macro `old` is available in postconditions so that state from before the call can be compared to the state after the call, and\n* the function `results` is available in postconditions which returns the same values returned by the primary method.\n\nThese contracts can also be created similarly to `:before` and `:after` methods, primarily for `defgeneric` convenience. In this case, the optional description of what is being required or guaranteed can be included between the method qualifier and the lambda list (this is because the docstring is not necessarily accessible).\n\n```common-lisp\n(defgeneric put (item stack)\n  (:method :require \"the stack is not full\" (item (stack stack))\n    (declare (ignore item))\n    (not (full stack)))\n  (:method :guarantee (item (stack stack))\n    (and (not (empty stack))\n         (eq (top-item stack) item)\n         (= (count stack) (1+ (old (count stack))))))\n\n(defmethod pop-stack :guarantee ((stack stack))\n  (and (not (full stack))\n       (eq (results) (old (top-item stack)))\n       (= (count stack) (1- (old (count stack)))))\n```\n\nInvariants can be placed on classes.\n\n```common-lisp\n(defclass stack ()\n  ((capacity :initarg :capacity :reader capacity :type integer)\n   (count :initform 0 :reader count :type integer)\n   (top-item :reader top-item))\n  (:metaclass contracted-class)\n  (:invariants (lambda (instance)\n                 \"the count must be between 0 and the capacity\"\n                 (\u003c= 0 (count instance) (capacity instance)))\n               (lambda (instance)\n                 \"there is no top-item if the stack is empty\"\n                 (implies (empty instance)\n                          (not (slot-boundp instance 'top-item))))))\n```\n\nIn order to have invariants on a class, the metaclass must be specified as `contracted-class`.\n\nInvariants are added to classes explicitly with the `:invariants` option, which allows you to specify any number of predicates that take the instance as their only argument. When available (depending on the Lisp implementation), the documentation string for the function is used. If no documentation is available, we fall back to the body (in the case of a lambda) or the function name and its documentation as the description.\n\nThis also illustrates another macro that is useful in contracts – `implies`. With `implies`, the second argument is only tested if the first argument is true.\n\nTypes are also checked as invariants. Most implementations check slot types little enough that it's possible for a bad value to end up there in some cases.\n\nThe description is included in the report if a `contract-violation-error` is raised. The description is also added to the documentation for the class, function, or primary method as appropriate. Slot type declarations are also added to the class documentation.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsellout%2Fquid-pro-quo","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsellout%2Fquid-pro-quo","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsellout%2Fquid-pro-quo/lists"}