{"id":22318672,"url":"https://github.com/scymtym/computation.environment","last_synced_at":"2026-01-06T16:14:56.754Z","repository":{"id":136535521,"uuid":"439278509","full_name":"scymtym/computation.environment","owner":"scymtym","description":"Overly general (and slow) environment library","archived":false,"fork":false,"pushed_at":"2023-03-03T13:53:09.000Z","size":138,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"future","last_synced_at":"2025-01-31T05:47:25.240Z","etag":null,"topics":["environments","namespace","visualization"],"latest_commit_sha":null,"homepage":"","language":"Common Lisp","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/scymtym.png","metadata":{"files":{"readme":"README.org","changelog":null,"contributing":null,"funding":null,"license":"COPYING","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-12-17T09:29:51.000Z","updated_at":"2024-10-29T17:34:14.000Z","dependencies_parsed_at":null,"dependency_job_id":"d689b1eb-f937-4d03-a12c-bc94fcd93669","html_url":"https://github.com/scymtym/computation.environment","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/scymtym%2Fcomputation.environment","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/scymtym%2Fcomputation.environment/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/scymtym%2Fcomputation.environment/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/scymtym%2Fcomputation.environment/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/scymtym","download_url":"https://codeload.github.com/scymtym/computation.environment/tar.gz/refs/heads/future","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245585811,"owners_count":20639671,"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":["environments","namespace","visualization"],"created_at":"2024-12-03T23:42:09.863Z","updated_at":"2026-01-06T16:14:56.722Z","avatar_url":"https://github.com/scymtym.png","language":"Common Lisp","funding_links":[],"categories":[],"sub_categories":[],"readme":"#+TITLE:    computation.environment README\n#+AUTHOR:   Jan Moringen\n#+EMAIL:    jmoringe@techfak.uni-bielefeld.de\n#+LANGUAGE: en\n\n#+SEQ_TODO: TODO STARTED | DONE\n#+OPTIONS: num:nil\n\n* STARTED Introduction\n\n  The ~compoutation.environment~ library provides protocols and\n  implementations for environments (not necessarily Common Lisp\n  environments or Lisp environments), that is data structures which\n  manage bindings of names to values. Different kinds of environments\n  are available:\n\n  + Global environments\n  + Lexical environments\n\n  Lexical environments can be organized in a hierarchy such that child\n  environments inherit entries from their ancestors.\n\n  Another feature are first-class namespaces: environments contain\n  namespaces which in turn control how names are organized and\n  processed within the environment.\n\n* STARTED Concepts\n\n  This section introduces the terminology used in the remainder of\n  this document.\n\n  + \u003c\u003cglossary:name\u003e\u003e Name :: In this context, a name is an object the\n       purpose of which is referring to another object. Their are\n       different kinds of names with different associated rules\n       regarding which objects are legal name of that kind and the\n       comparison of names. All names of one particular kind form a\n       [[glossary:namespace][namespace]].\n\n  + \u003c\u003cglossary:namespace\u003e\u003e Namespace :: A namespace defines a\n       particular kind of [[glossary:name][name]] for which it controls\n\n    + \u003c\u003cglossary:name-syntax\u003e\u003e Name syntax :: Which objects are valid\n         names in the namespace?\n\n         For example, legal variable names are typically symbols\n         (excluding constants such as ~cl:nil~, ~cl:t~ and\n         ~cl:pi~). Function names, on the other hand, can also be of\n         the form ~(cl:setf NAME)~.\n\n    + \u003c\u003cglossary:name-comparison\u003e\u003e Name comparison :: Given two\n         objects which are valid names, how to decide whether they\n         designate the same name?\n\n         For example, ~name1~ and ~name2~ must be ~eq~ in order to\n         designate the same [[glossary:name][variable name]]. However, ~name1~ and\n         ~name2~ in ~(let ((name1 (list 'setf foo)) (name2 (list 'setf\n         foo))))~ are not ~eq~ yet still designate the same /function\n         name/.\n\n    + Entry isolation :: Not sure\n\n    For example, legal variable names are typically symbols (excluding\n    constants such as ~cl:nil~, ~cl:t~ and ~cl:pi~) and can be\n    compared using ~cl:eq~. Function names, on the other hand, can\n    also be of the form ~(cl:setf NAME)~ and must be compared using\n    ~cl:equal~ or a specialized function. In a non-Lisp use-case,\n    names could be non-empty strings and ~string=~ or\n    ~string-equal~ could be appropriate comparison functions.\n\n  + \u003c\u003cglossary:environment\u003e\u003e Environment :: At the minimum, a\n       collection of [[glossary:namespace][namespaces]] and associated [[glossary:binding][binding]] collections. An\n       environment may have other parts such as a reference to a\n       parent environment.\n\n  + \u003c\u003cglossary:binding\u003e\u003e Binding :: An association of a [[glossary:name][name]] in a\n       [[glossary:namespace][namespace]] and a value.\n\n  + \u003c\u003cglossary:scope\u003e\u003e Scope :: A scopes controls the way in which a\n       value is looked up for a given name, [[glossary:namespace][namespace]] and [[glossary:environment][environment]].\n\n       As a concrete example, the /direct/ scope constrains the lookup\n       to the specified environment, that is ancestors of the\n       environment are not considered.\n\n  #+BEGIN_SRC plantuml :exports results :file static-view.png\n    hide members\n\n    class environment\n    class namespace\n    class bindings\n\n    class eq-namespace extends namespace {\n    }\n    class equal-namespace extends namespace {\n    }\n\n    environment -\u003e namespace\n    namespace -\u003e bindings\n  #+END_SRC\n\n  #+RESULTS:\n  [[file:static-view.png]]\n\n  Object diagram without hierarchy\n\n  #+BEGIN_SRC plantuml :exports results :file objects-without-hierarchy.png\n    object \"environment : lexical-environment\" as environment\n    object \"function-namespace ; function-name-namespace\" as function_namespace\n    note bottom of function_namespace {\n      Legal names are of type \"\"(or symbol (cons (eql setf) (cons symbol null)))\"\"\n    }\n    map \"function-bindings : equal-hash-table-bindings\" as function_bindings {\n      function-name₁ =\u003e function₁\n      function-name₂ =\u003e function₂\n      …              =\u003e …\n    }\n    object \"variable-namespace : eq-namespace\" as variable_namespace\n    map \"variable-bindings : eq-hash-table-bindings\" as variable_bindings {\n      variable-name₁ =\u003e variable₁\n      variable-name₂ =\u003e variable₂\n      …              =\u003e …\n    }\n    object \"namespace-namespace : eq-namespace\" as namespace_namespace\n    map \"namespace-bindings : eq-hash-table-bindings\" as namespace_bindings {\n      namespace *---\u003e namespace_namespace\n      function  *---\u003e function_namespace\n      variable  *---\u003e variable_namespace\n    }\n\n    environment *-- namespace_bindings\n    environment *-- function_bindings\n    environment *-- variable_bindings\n  #+END_SRC\n\n  #+RESULTS:\n  [[file:objects-without-hierarchy.png]]\n\n  Object diagram with hierarchy\n\n  #+BEGIN_SRC plantuml :exports results :file objects-with-hierarchy.png\n    object \"global-environment\" as global_environment\n    object \"namespace-namespace : eq-namespace\" as namespace_namespace\n    object \"variable-namespace : eq-namespace\" as variable_namespace\n    object \"function-namespace ; function-name-namespace\" as function_namespace\n    map \"namespace-bindings : eq-hash-table-bindings\" as namespace_bindings {\n      namespace *--\u003e namespace_namespace\n      function  *--\u003e function_namespace\n      variable  *--\u003e variable_namespace\n    }\n\n    object \"environment : lexical-environment\" as environment\n    map \"function-bindings : equal-hash-table-bindings\" as function_bindings {\n      function-name₁ =\u003e function₁\n      function-name₂ =\u003e function₂\n      …              =\u003e …\n    }\n    map \"variable-bindings : eq-hash-table-bindings\" as variable_bindings {\n      variable-name₁ =\u003e variable₁\n      variable-name₂ =\u003e variable₂\n      …              =\u003e …\n    }\n\n    global_environment *-right- namespace_bindings\n\n    environment -up-\u003e global_environment : \"parent\"\n    environment *-- function_bindings\n    environment *-- variable_bindings\n  #+END_SRC\n\n  #+RESULTS:\n  [[file:objects-with-hierarchy.png]]\n\n* STARTED Tutorial\n\n  #+BEGIN_SRC lisp :exports results :results silent\n    (ql:quickload :computation.environment)\n  #+END_SRC\n\n** STARTED Making environments\n\n   This library provides different kinds of environments such as\n   ~global-environment~. Clients create instances of theses\n   environment classes using ~make-instance~. In order to hold any\n   [[glossary:binding][bindings]], an environment must contain at least one\n   [[glossary:namespace][namespace]]. Namespaces are stored as bindings in a special\n   namespace, but the details of that mechanism are not important at\n   this point. The following code creates a global environment that\n   contains a single namespace, called ~function~, but no \"ordinary\"\n   bindings:\n\n   #+BEGIN_SRC lisp :exports both :results output\n     (defvar *environment* (make-instance 'computation.environment:global-environment))\n\n     (setf (computation.environment:lookup 'function 'computation.environment:namespace *environment*)\n           (make-instance 'computation.environment::eq-namespace))\n\n     (describe *environment*)\n   #+END_SRC\n\n   #+RESULTS:\n   : #\u003cGLOBAL-ENVIRONMENT 1 namespace {100A817B03}\u003e\n   :\n   :   EQ-NAMESPACE COMMON-LISP:FUNCTION 0 entries\n   :\n\n** STARTED Looking up bindings\n\n   As mentioned above, the new environment does not yet contain any\n   bindings in its ~function~ namespace, so an attempt to look up a\n   function in that environment must result in an error:\n\n   #+BEGIN_SRC lisp :exports both\n     (handler-case\n         (computation.environment:lookup 'foo 'function *environment*)\n       (error (condition)\n         (princ-to-string condition)))\n   #+END_SRC\n\n   #+RESULTS:\n   : An entry for name FOO does not exist in namespace #\u003cEQ-NAMESPACE {100BDBF7B3}\u003e\n   : in environment #\u003cGLOBAL-ENVIRONMENT 1 namespace {100A817B03}\u003e\n\n   Correspondingly, listing all entries contained in the ~function~\n   namespace in the environment results in the empty list:\n\n   #+BEGIN_SRC lisp :exports both\n     (computation.environment:entries 'function *environment*)\n   #+END_SRC\n\n   #+RESULTS:\n   : NIL\n\n** STARTED Adding bindings\n\n   New bindings can be created in two ways\n\n   1. Destructively modifying a given environment by adding the new\n      binding to it\n\n   2. Creating a new environment object that contains the new binding\n      and is linked to the existing environment object\n\n   The first way can be achieved using the ~(setf\n   computation.environment:lookup)~ generic function:\n\n   #+BEGIN_SRC lisp :exports both\n     (setf (computation.environment:lookup 'foo 'function *environment*) :foo)\n     (computation.environment:lookup 'foo 'function *environment*)\n   #+END_SRC\n\n   #+RESULTS:\n   : :FOO\n\n   The functions ~computation.environment:augmented-environment~ and\n   ~computation.environment:augmented-namespace~ implement the second\n   way:\n\n   #+BEGIN_SRC lisp :exports both :results output\n     (let ((augmented (computation.environment:augmented-namespace\n                       *environment* 'function '(bar) '(:bar)\n                       :class 'computation.environment::lexical-environment)))\n       (describe augmented)\n       (format t \"~\u0026----------------\")\n       (handler-case\n           (print (computation.environment:lookup 'bar 'function augmented))\n         (error (condition)\n           (princ-to-string condition))))\n   #+END_SRC\n\n   #+RESULTS:\n   : #\u003cLEXICAL-ENVIRONMENT 1 namespace @1 {1011E28F13}\u003e\n   :\n   :   EQ-NAMESPACE COMMON-LISP:FUNCTION 2 entries\n   :     BAR → :BAR\n   :     FOO → :FOO [inherited from #\u003cGLOBAL-ENVIRONMENT 2 namespaces {10028B3063}\u003e]\n   : ----------------\n   : :BAR\n\n   but the original environment is not affected:\n\n   #+BEGIN_SRC lisp :exports both :results output\n     (describe *environment*)\n   #+END_SRC\n\n   #+RESULTS:\n   : #\u003cGLOBAL-ENVIRONMENT 2 namespaces {10028B3063}\u003e\n   :\n   :   EQ-NAMESPACE COMMON-LISP:FUNCTION 1 entry\n   :     FOO → :FOO\n\n** STARTED Shadowing\n\n   #+BEGIN_SRC lisp :exports both :results output\n     (let ((augmented (computation.environment:augmented-namespace\n                       *environment* 'function '(foo) '(:bar)\n                       :class 'computation.environment::lexical-environment)))\n       (describe *environment*)\n       (terpri) (terpri)\n       (describe augmented))\n   #+END_SRC\n\n   #+RESULTS:\n   #+begin_example\n   #\u003cGLOBAL-ENVIRONMENT 2 namespaces {10028B3063}\u003e\n\n     EQ-NAMESPACE COMMON-LISP:FUNCTION 1 entry\n       FOO → :FOO\n\n   #\u003cLEXICAL-ENVIRONMENT 1 namespace @1 {1005097E73}\u003e\n\n     EQ-NAMESPACE COMMON-LISP:FUNCTION 2 entries\n       FOO → :BAR\n       FOO → :FOO [inherited from #\u003cGLOBAL-ENVIRONMENT 2 namespaces {10028B3063}\u003e]\n   #+end_example\n\n* STARTED Dictionary\n\n  #+BEGIN_SRC lisp :results none :exports none :session \"doc\"\n    #.(progn\n        #1=(ql:quickload '(:computation.environment :alexandria :split-sequence :text.documentation-string))\n        '#1#)\n    ,#+no (defun doc (symbol kind)\n      (let* ((lambda-list (sb-introspect:function-lambda-list symbol))\n             (string      (documentation symbol kind))\n             (lines       (split-sequence:split-sequence #\\Newline string))\n             (trimmed     (mapcar (alexandria:curry #'string-left-trim '(#\\Space)) lines)))\n        (format t \"~~~(~A~)~~ src_lisp[:exports code]{~\u003c~{~A~^ ~}~:@\u003e}~2%~{~A~^~%~}\"\n                symbol (list lambda-list) trimmed)))\n    (in-package #:cl-user)\n\n    (defun doc (symbol kind)\n      (let* ((lambda-list (sb-introspect:function-lambda-list symbol))\n             (string      (documentation symbol kind))\n             (trimmed     (when string\n                            (text.documentation-string.parser::remove-common-leading-whitespace string))))\n        (format t \"#+begin_quote~%\")\n        (format t \"*~~~(~A~)~~* src_lisp[:exports code]{~\u003c~{~(~A~)~^ ~}~:@\u003e}~2%\"\n                symbol (list lambda-list))\n        ,#+no (format t \"~(~A~) ~\u003c~{~A~^ ~}~:@\u003e~2%\"\n                     symbol (list lambda-list))\n        (if trimmed\n            (text.documentation-string.unparser::render-org\n             'list\n             (text.documentation-string.parser::decide-meta-variables\n              (text.documentation-string.parser:parse trimmed 'list) 'list\n              :initial-entries (map 'list #'symbol-name lambda-list))\n             ,*standard-output*)\n            (format t \"/not documented/~%\"))\n        (format t \"#+end_quote~%\")))\n  #+END_SRC\n\n** STARTED The bindings protocol\n\n   This low-level protocol is responsible for creating and accessing\n   [[glossary:binding][bindings]] in a given [[glossary:namespace][namespace]] in one particular\n   [[glossary:environment][environment]]. Clients should usually use the higher-level\n   [[#sec:dictionary-environment-protocol][environment protocol]].\n\n   \u003c\u003cgeneric-function:make-bindings\u003e\u003e\n   #+BEGIN_SRC lisp :results output raw :exports results :session \"doc\"\n     (doc 'computation.environment:make-bindings 'function)\n   #+END_SRC\n\n   #+RESULTS:\n   #+begin_quote\n   *~make-bindings~* src_lisp[:exports code]{namespace environment}\n\n   Return a bindings object for /namespace/ in /environment/.\n\n   The returned object must be usable with /namespace/ and /environment/\n   in the bindings protocol.\n   #+end_quote\n\n   \u003c\u003cgeneric-function:entry-count-in-bindings\u003e\u003e\n   #+BEGIN_SRC lisp :results output raw :exports results :session \"doc\"\n     (doc 'computation.environment:entry-count-in-bindings 'function)\n   #+END_SRC\n\n   #+RESULTS:\n   #+begin_quote\n   *~entry-count-in-bindings~* src_lisp[:exports code]{bindings namespace\n                                                       environment}\n\n   Return the number of entries in /bindings/ in /namespace/, /environment/.\n   #+end_quote\n\n   \u003c\u003cgeneric-function:map-entries-in-bindings\u003e\u003e\n   #+BEGIN_SRC lisp :results output raw :exports results :session \"doc\"\n     (doc 'computation.environment:map-entries-in-bindings 'function)\n   #+END_SRC\n\n   #+RESULTS:\n   #+begin_quote\n   *~map-entries-in-bindings~* src_lisp[:exports code]{function bindings namespace\n                                                       environment}\n\n   Call /function/ with each entry in /bindings/ in /namespace/, /environment/.\n\n   The lambda list of /function/ must be compatible with\n\n   #+BEGIN_EXAMPLE\n   (name value)\n   #+END_EXAMPLE\n   where /name/ is the name of the entry and /value/ is the associated\n   value. Any value returned by /function/ is discarded.\n   #+end_quote\n\n   \u003c\u003cgeneric-function:lookup-in-bindings\u003e\u003e\n   #+BEGIN_SRC lisp :results output raw :exports results :session \"doc\"\n     (doc 'computation.environment:lookup-in-bindings 'function)\n   #+END_SRC\n\n   #+RESULTS:\n   #+begin_quote\n   *~lookup-in-bindings~* src_lisp[:exports code]{name bindings namespace environment}\n\n   Lookup and return the value for /name/ in /bindings/ in /namespace/, /environment/.\n\n   Return two values: 1) the found value or ~nil~ 2) a Boolean\n   indicating whether a value exists\n   #+end_quote\n\n   \u003c\u003cgeneric-function:setf-lookup-in-bindings\u003e\u003e\n   #+BEGIN_SRC lisp :results output raw :exports results :session \"doc\"\n     (doc '(setf computation.environment:lookup-in-bindings) 'function)\n   #+END_SRC\n\n   #+RESULTS:\n   #+begin_quote\n   *~(setf lookup-in-bindings)~* src_lisp[:exports code]{new-value name bindings namespace environment}\n\n   Set the value of /name/ in /bindings/ in /namespace/, /environment/ to /new-value/.\n\n   Return /new-value/ as the primary return value.\n   #+end_quote\n\n** STARTED The environment protocol\n   :PROPERTIES:\n   :CUSTOM_ID: sec:dictionary-environment-protocol\n   :END:\n\n   This protocol allows accessing the [[glossary:binding][bindings]] in all [[glossary:namespace][namespaces]] in a\n   given [[glossary:scope][scope]] starting at a particular [[glossary:environment][environment]]. The scope\n   controls, for example, whether bindings inherited from parent\n   environments should be considered.\n\n   \u003c\u003cgeneric-function:entry-count\u003e\u003e\n   #+BEGIN_SRC lisp :results output raw :exports results :session \"doc\"\n     (doc 'computation.environment:entry-count 'function)\n   #+END_SRC\n\n   #+RESULTS:\n   #+begin_quote\n   *~entry-count~* src_lisp[:exports code]{namespace environment \u0026key scope}\n\n   Return the number of entries in /namespace/ in /environment/ for /scope/.\n   #+end_quote\n\n   \u003c\u003cgeneric-function:map-entries\u003e\u003e\n   #+BEGIN_SRC lisp :results output raw :exports results :session \"doc\"\n     (doc 'computation.environment:map-entries 'function)\n   #+END_SRC\n\n   #+RESULTS:\n   #+begin_quote\n   *~map-entries~* src_lisp[:exports code]{function namespace environment \u0026key\n                                           scope}\n\n   Call /function/ for each entry in /namespace/ in /environment/ for /scope/.\n\n   The lambda list of /function/ must be compatible with\n\n   #+BEGIN_EXAMPLE\n   (name value container)\n   #+END_EXAMPLE\n   Any value returned by /function/ is discarded.\n   #+end_quote\n\n   \u003c\u003cgeneric-function:entries\u003e\u003e\n   #+BEGIN_SRC lisp :results output raw :exports results :session \"doc\"\n     (doc 'computation.environment:entries 'function)\n   #+END_SRC\n\n   #+RESULTS:\n   #+begin_quote\n   *~entries~* src_lisp[:exports code]{namespace environment \u0026key scope}\n\n   Return entries in /namespace/ in /environment/ for /scope/ as an alist.\n   #+end_quote\n\n   \u003c\u003cgeneric-function:lookup\u003e\u003e\n   #+BEGIN_SRC lisp :results output raw :exports results :session \"doc\"\n     (doc 'computation.environment:lookup 'function)\n   #+END_SRC\n\n   #+RESULTS:\n   #+begin_quote\n   *~lookup~* src_lisp[:exports code]{name namespace environment \u0026key\n                                      if-does-not-exist scope}\n\n   Lookup and return the value for /name/ in /namespace/ in /environment/ for /scope/.\n\n   Return three values:\n   1) the found value (subject to /if-does-not-exist/)\n   2) a Boolean indicating whether a value exists\n   3) the environment in which the value was found.\n\n   /scope/ controls which bindings are considered. Examples of scopes\n   include binding directly contained in /environment/ and bindings\n   contained in /environment/ or any of its ancestor environments.\n\n   /if-does-not-exist/ controls the behavior in case such a value does\n   not exist.\n   #+end_quote\n\n   \u003c\u003cgeneric-function:setf-lookup\u003e\u003e\n   #+BEGIN_SRC lisp :results output raw :exports results :session \"doc\"\n     (doc '(setf computation.environment:lookup) 'function)\n   #+END_SRC\n\n   #+RESULTS:\n   #+begin_quote\n   *~(setf lookup)~* src_lisp[:exports code]{new-value name namespace environment \u0026key if-does-not-exist}\n\n   Set the value of /name/ in /namespace/ in /environment/ to /new-value/.\n\n   Return /new-value/ as the primary return value.\n\n   /if-does-not-exist/ is accepted for parity with ~lookup~.\n   #+end_quote\n\n   \u003c\u003cgeneric-function:make-or-update\u003e\u003e\n   #+BEGIN_SRC lisp :results output raw :exports results :session \"doc\"\n     (doc 'computation.environment:make-or-update 'function)\n   #+END_SRC\n\n   #+RESULTS:\n   #+begin_quote\n   *~make-or-update~* src_lisp[:exports code]{name namespace environment make-cont\n                                              update-cont \u0026key scope}\n\n   Use /make-cont/ or /update-cont/ to set /name/ in /namespace/ in /environment/ for /scope/.\n\n   Return four values:\n   1) the new value of /name/ in /namespace/ in /environment/\n   2) a Boolean indicating whether the value of /name/ in\n      /namespace/ in /environment/ has been updated\n   3) the previous value of /name/ in /namespace/ in /environment/\n   4) the container in which the previous value was found.\n\n   If no value exists for /name/ in /namespace/ in /environment/, /make-cont/\n   is called to make a value which is then set as the value of /name/\n   in /namespace/ in /environment/.\n\n   If a value exists for /name/ in /namespace/ in /environment/,\n   /update-cont/ is called with the existing value and the container of\n   that existing value to potentially compute a new value. If a new\n   value is computed, that value is set as the value of /name/ in\n   /namespace/ in /environment/.\n\n   /make-cont/ has to be a function with a lambda list compatible with\n\n   #+BEGIN_EXAMPLE\n   ()\n   #+END_EXAMPLE\n   and has to return the new value as its primary return value.\n\n   /update-cont/ has to be a function with a lambda list compatible\n   with\n\n   #+BEGIN_EXAMPLE\n   (old-value old-container)\n   #+END_EXAMPLE\n   and must return between two values and three values when called:\n   1) a new value based on OLD-VALUE\n   2) a Boolean indicating whether the first return value is different\n      from /OLD-VALUE/\n   3) optionally a container in which the returned new value should be\n      set.\n   #+end_quote\n\n   \u003c\u003cgeneric-function:ensure\u003e\u003e\n   #+BEGIN_SRC lisp :results output raw :exports results :session \"doc\"\n     (doc 'computation.environment:ensure 'function)\n   #+END_SRC\n\n   #+RESULTS:\n   #+begin_quote\n   *~ensure~* src_lisp[:exports code]{name namespace environment make-cont \u0026key\n                                      scope}\n\n   Maybe use /make-cont/ to set /name/ in /namespace/ in /environment/ for /scope/.\n\n   Return four values:\n   1) the new value of /name/ in /namespace/ in /environment/\n   2) a Boolean indicating whether the value of /name/ in\n      /namespace/ in /environment/ has been updated\n   3) the container in which the previous value was found.\n\n   If no value exists for /name/ in /namespace/ in /environment/, /make-cont/\n   is called to make a value which is then set as the value of /name/\n   in /namespace/ in /environment/.\n\n   /make-cont/ has to be a function with a lambda list compatible with\n\n   #+BEGIN_EXAMPLE\n   ()\n   #+END_EXAMPLE\n   and has to return the new value as its primary return value.\n   #+end_quote\n\n** STARTED The hierarchical environment protocol\n\n   \u003c\u003cgeneric-function:parent\u003e\u003e\n   #+BEGIN_SRC lisp :results output raw :exports results :session \"doc\"\n     (in-package #:cl-user)\n     (doc 'computation.environment:parent 'function)\n   #+END_SRC\n\n   #+RESULTS:\n   #+begin_quote\n   *~parent~* src_lisp[:exports code]{environment}\n\n   Return the parent of /environment/ or ~nil~.\n\n   #+end_quote\n\n   \u003c\u003cgeneric-function:root\u003e\u003e\n   #+BEGIN_SRC lisp :results output raw :exports results :session \"doc\"\n     (doc 'computation.environment:root 'function)\n   #+END_SRC\n\n   #+RESULTS:\n   #+begin_quote\n   *~root~* src_lisp[:exports code]{environment}\n\n   Return the ancestor of /environment/ that has no parent.\n\n   In particular, if /environment/ does not have a parent, return\n   /environment/.\n   #+end_quote\n\n   \u003c\u003cgeneric-function:depth\u003e\u003e\n   #+BEGIN_SRC lisp :results output raw :exports results :session \"doc\"\n     (doc 'computation.environment:depth 'function)\n   #+END_SRC\n\n   #+RESULTS:\n   #+begin_quote\n   *~depth~* src_lisp[:exports code]{environment}\n\n   Return the number of ancestors /environment/ has.\n\n   In particular, return /0/ if /environment/ does not have a parent.\n\n   #+end_quote\n\n# Local Variables:\n# eval: (mapcar 'require '(ob-lisp ob-plantuml))\n# End:\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fscymtym%2Fcomputation.environment","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fscymtym%2Fcomputation.environment","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fscymtym%2Fcomputation.environment/lists"}