Package simple-guess
Description
One should normally import a single symbol from this package, inquire
.
Any other symbols from this package should normally be explicitly qualified, such as simple-guess:eager-advisor
.
Don't (:use)
!
simple-guess
defines a simple extensible protocol for computing a guess using advisors.
I'm using this in an upcoming library to automatically determine the correct metaclass to use by analyzing the defclass form (after a trivial bit of package-local configuration).
One should normally import a single symbol from this package, inquire
.
Any other symbols from this package should normally be explicitly qualified, such as simple-guess:eager-advisor
.
Don't (:use)
!
The manager basically represents the type of inquiry, and is normally passed directly as the manager to any subinquiries.
The manager is usually stateless, in which case it can be reused across top-level inquiries.
Alternatively, the manager could manage some global state for the top-level inquiry.
An advisor is an object that returns advice (an object) given a query (a plist), or nil
if the advisor has no particular opinion.
manager advisor &rest query &key &allow-other-keys => advice
The advisor ponders query and returns advice to the best of its knowledge, or nil
if it doesn't have a particular opinion. (Use fakenil if you need to represent nil
as advice.)
The advisor is free to compute its advice any way it likes, including querying subadvisors (using the same query, an amended query, or an unrelated query) and combining their results in some way.
(manager simple-guess:manager
) (advisor simple-guess:constant-advisor
) &rest query => advice
Returns the advisor's simple-guess:advice
.
(manager simple-guess:manager
) (advisor simple-guess:eager-advisor
) &rest query => advice
Queries each of the advisor's simple-guess:advisors
in turn, returning the first non-nil advice encountered.
(manager simple-guess:manager
) (advisor simple-guess:query-variant-advisor
) &rest query => advice
Calls (apply #'
.inquire
manager (simple-guess:advisor
advisor) (funcall (simple-guess:query-transformer
advisor) query))
(manager simple-guess:manager
) (advisor simple-guess:macro-advisor
) &rest query => advice
Calls (apply #'
.inquire
manager (simple-guess:expansion
advisor) query)
Slots:
((advisor :initarg :advisor
:reader simple-guess:advisor
:type simple-guess:advisor
:documentation ":advisor is required."))
object => advisor
Returns the advisor associated with the object, which is usually an "inner" advisor that is being consulted by the object, the "outer" advisor. A method is defined for simple-guess:advisor-mixin
.
Slots:
((advisors :initarg :advisors
:reader simple-guess:advisors
:type list
:documentation ":advisors is required."))
object => advisor
Returns the advisors associated with the object, which are usually "inner" advisors that are being consulted by the object, the "outer" advisor. A method is defined for simple-guess:advisors-mixin
.
A function designator. The initial value is the function make-instance.
As an example, you could bind this variable to a function that forwards to make-instance, but returns the simple-guess:expansion
directly if the result was an instance of simple-guess:macro-variant
. This would result in slightly increased query performance, at the cost of somewhat decreased debuggability.
Another use-case would be implementing various memoizing schemes, notably for simple-guess:constant-advisor
s.
advisor-class &rest initargs => advisor
simple-guess:advisor
.Forwards all arguments to simple-guess:*make-advisor-function*
.
Slots:
((advice :initarg :advice
:reader simple-guess:advice
:initform nil))
advice => advisor
simple-guess:advisor
.Calls (
.simple-guess:make-advisor
'simple-guess:constant-advisor
:advice advice)
advisor => advice
Returns the advisor's advice. A method is defined for simple-guess:constant-advisor
.
simple-guess:advisors-mixin
, simple-guess:advisor
Analogous to or.
&rest advisors => advisor
simple-guess:advisor
objects.simple-guess:advisor
.If there are no advisors, then return the result of (
.simple-guess:constant-advisor
nil)
If there is only one advisor in advisors, then return advisor after checking that it is indeed an simple-guess:advisor
.
Else, call (
.simple-guess:make-advisor
'simple-guess:eager-advisor
:advisors advisors)
simple-guess:advisors-mixin
, simple-guess:advisor
Slots:
((query-transformer :initarg :query-transformer
:reader simple-guess:query-transformer
:documentation ":query-transformer is required."))
inner-advisor query-transformer => advisor
simple-guess:advisor
.simple-guess:advisor
.Calls (
.simple-guess:make-advisor
'simple-guess:query-variant-advisor
:advisor inner-advisor :query-transformer query-transformer)
advisor => query-transformer
Returns the query-transformer that the advisor will funcall with the query before passing it to the inner advisor. A method is defined for simple-guess:query-variant-advisor
.
A higher-level simple-guess:advisor
whose semantics are implemented as a lower-level simple-guess:advisor
, its expansion.
macro-advisor => expansion
Returns the expansion, which is an simple-guess:advisor
that implements the semantics of the macro. Substituting the expansion for the macro-advisor must have equivalent semantics, else the consequences are undefined.
Slots:
((expansion :reader simple-guess:expansion
:type simple-guess:advisor
)
:documentation "Initialized by a shared-initialize :after method that assigns the result of calling simple-guess:compute-expansion
on the macro to the slot.")
macro-advisor => expansion
simple-guess:macro-advisor
.advisor
.Computes the expansion that will subsequently be returned when calling simple-guess:expansion
on macro-advisor.
(advisor simple-guess:query-variants-advisor
) => expansion
Let inner-advisor be the simple-guess:advisor
of advisor.
For each query-transformer in the simple-guess:query-transformers
of advisor, call (
.simple-guess:query-variant-advisor
inner-advisor query-transformer)
Return the result of applying the simple-guess:grouping-function
of advisor to the list produced in the previous step.
simple-guess:advisor-mixin
, simple-guess:standard-macro-advisor
Slots:
((query-transformers :initarg :query-transformers
:reader simple-guess:query-transformers
:documentation ":query-transformers is required.")
(grouping-function :initarg :grouping-function
:reader simple-guess:grouping-function
:type (or function symbol)
:initform #'simple-guess:eager-advisor
))
inner-advisor query-transformers &key (group simple-guess:eager-advisor
) => advisor
simple-guess:advisor
.simple-guess:query-variants-advisor
.Calls (
.simple-guess:make-advisor
'simple-guess:query-variants-advisor
:advisor inner-advisor :query-transformers query-transformers :grouping-function group)
advisor => query-transformers
Returns the list of query-transformers that will be used to initialize as many inner simple-guess:query-variant-advisor
. A method is defined for simple-guess:query-variants-advisor
.
Returns the function designator that will be applied to the simple-guess:query-transformers
to group them. A method is defined for simple-guess:query-variants-advisor
.