added documentation about dynamic functions

parent 4946be63
......@@ -31,6 +31,7 @@ Documentation for the Guile-Log Logic Programming Environment for Guile 2.0 v0.4
* acumulators/generators:: Hot to collect and generate sequences of solutions.
* postpone:: To postpone a search.
* dynamics:: catch prompt abort
* dynamic-functions:: Dynamicaly add, remove and execute clauses
* database:: Prolog like Database, the guile-log kind.
* parsing:: A parsing framework. Enabling to use guile-log's parser
* sed/grep:: Sed and grep functionalities for scheme
......@@ -39,6 +40,49 @@ Documentation for the Guile-Log Logic Programming Environment for Guile 2.0 v0.4
* Index:: Complete index.
@end menu
@node dynamic-functions
@chapter Overview
An interesting category of functionality in prolog is their dynamic function framework. They are a generalization of databases and allow to do matching in a scalable manner through indexing. Guile log also support a full indexer for a simplified matcher. And for all matched clauses they will be executed in order acording to how the database is setuped. One can add clauses to the head or to the end, remove clauses according to a pattern and also store states for later rewinding. The state guarding mechanism is either cheap (weak) e.g. it will not remember states as long as the action is above in the stack, else if it backtracks below the stack, state will be stored and restored at reentrence. We also support strong state storage at e.g. postpone support.
To use the api use @code{(use-modules (logic guile-log functional-database))}.
@chapter Api
@findex define-dynamic
@findex <push-dynamic>
@findex <lambda-dyn>
@findex <append-dynamic>
@findex <remove-dynamic>
@code{SCM (define-dynamic f)}, this will make a dynamic function object and bind it to @code{f}
@code{G.L. (<push-dynamic> f lambda-dyn)}, push a match onto the head of dynamic function @code{f}. @code{lambda-dyn} is a special lambda typically created through,
@code{SCM (<lambda-dyn> pat ... code)}, here @code{pat ...} will be simplified patterns only supporting @code{quote,unquote} all else directive is not allowed. @code{code} is evaluated in guile-log mode.
Similarly we can add code to the end of the dynamic function, e.g.
@code{G.L. (<append-dynamic> f lambda-dyn)}.
Also to remove elements one can use,
@code{G.L. (<remove-dynamic> (f a ...))}, where @code{f} is the dynamic function and @code{a ...} the patterns for the arguments that, which matches will be retracted.
@findex <with-dynamic-functions>
@findex <guard-dynamic-functions>
The previous set of API is typically what you get to use in prolog. The
downside is that they posses problem w.r.t. leaking data and therefor the next ideom is preferable to use in order to make sure both that one undo any changes to the dynamic variable, but also at reinstation of a state inside the form, it will resore to the same state as when control left the inner of the ideom e.g.
@code{G.L. (<with-dynamic-functions> (f ...) code ...)}, for this form @code{f ...}, will be weakly guarded throughout the form e.g. if control leaves the form then the state is stored if needed and at reinstation of state inside @code{code ...}, the old state of the dynamic variable will be reinstated. But inside the form state of the dynamic functions is not saved or restored.
A stronger form of guard can be used in case one would like to make sure that the dynamic functions state can be reinstated in case of e.g. postpone is used, then use,
@code{G.L. (<guard-dynamic-functions> (f ...) code ...)},
Finally the last section conserns the ability to compile the dynamic function for as fast lookup as possible, use
@findex <dynamic-compile>
@code{G.L. (<dynamic-compile> f ...)}, comiles the dynamic functions @code{f ...} for fast lookup. This ideom takes time and if used freely can cause a high memory consumption.
@node umatch
......@@ -61,7 +61,7 @@
block-growth-factor init-block-size
get-index-set get-index-test
......@@ -11,7 +11,11 @@
#:export (define-dynamic dynamic-push dynamic-prepend dynamic-compile
dynamic-remove dynamic-env-ref dynamic-env-set!
dynamic-compile-index <with-dynamic>))
Action dynlist array indexed
......@@ -484,12 +488,27 @@ add/run * vlist *
(error "not a dynamic variable"))))
(<define-guile-log-rule> (<dynamic-add> head vs lam)
(<let> ((head.v (<cp> (cons head vs))
(vh (find-vars tail)))
(define-syntax <lambda-dyn>
(syntax-rules ()
((_ (pat ...) code)
(list (mk-varpat pat)
(lambda (a b c x)
(apply (<<lambda>> (pat ... code))
a b c x))
((_ (pat ...) code y)
(list (mk-varpat pat)
(lambda (a b c x)
(apply (<<lambda>> (pat ... code))
a b c x))
(lambda (a b c x)
(apply (<<lambda>> (pat ... y))
a b c x))))))
(<define-guile-log-rule> (<push-dynamic> f dyn-lambda)
(<code> (apply dynamic-push S f dyn-lambda)))
(<define-guile-log-rule> (<append-dynamic> f dyn-lambda)
(<code> (apply dynamic-append S f dyn-lambda)))
(<define-guile-log-rule> (<weak-with-dynamic> f code ...)
(<let> ((state (dynamic-env-ref f)))
(define-module (logic guile-log indexer)
#:use-module (logic guile-log code-load)
#:re-export (get-index-set))
\ No newline at end of file
#:re-export (get-index-set get-index-test))
\ No newline at end of file
......@@ -332,4 +332,15 @@ SCM_DEFINE(scm_get_index_set, "get-index-set", 3, 0, 0,
#undef FUNC_NAME
SCM_DEFINE(scm_get_index_test, "get-index-test", 4, 0, 0,
(SCM s, SCM e, SCM db, SCM n_), "")
#define FUNC_NAME s_scm_get_index_test
int n = scm_to_int(n_);
get_index_set(s, e, db);
return get_index_set(s, e, db);
#undef FUNC_NAME
SCM_API SCM scm_get_index_set(SCM s, SCM e, SCM db);
SCM_API SCM scm_get_index_test(SCM s, SCM e, SCM db, SCM n_);
(use-modules (logic guile-log functional-database))
(use-modules (logic guile-log indexer))
(use-modules (logic guile-log umatch))
(define-dynamic f)
(define (add x)
......@@ -9,7 +10,7 @@
(define (comp)
(dynamic-compile-index *current-stack* f))
(define n 100)
(define n 33)
(lambda (x)
......@@ -27,10 +28,10 @@
(define (finde a e)
(let* ((db (vector-ref e 3)))
(get-index-set *current-stack* a db)))
(get-index-test *current-stack* a db 1000)))
(define (try n)
(let ((v `(,(gp-var! *current-stack*) 4))
(let ((v '(5 5) #;`(,(gp-var! *current-stack*) 4))
(e (car (get))))
(let loop ((n n))
(if (= n 0)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment