UNPKG

@ciao-lang/ts-ciao-interface

Version:

Simple Ciao interface for node.

47 lines (36 loc) 9.98 kB
<!DOCTYPE HTML><html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"/><meta name="viewport" content="width=device-width, initial-scale=1"/><meta name="theme-color" content="#273f79"/><link rel="stylesheet" href="lpdoc.css" type="text/css"/><script type="text/javascript" src="lpdoc.js"></script><title>Lazy evaluation &mdash; The Ciao System v1.22</title></head><body><div class="lpdoc-page fixleftbar"><a href="#" id="sidebar-toggle-button" class="lpdoc-navbutton"><span id="sidebar-button-arrow">&#9776;</span></a><div id="sidebar" class="lpdoc-sidebar"><div style="height: 40px; margin-left: auto; margin-right: auto"><img src="ciao-logo_autofig.png" width=auto height=100%></div><div class="lpdoc-nav"><span class="lpdoc-on-right"><a class="lpdoc-navbutton" href="ExtendLang.html">&#x2191;</a><a class="lpdoc-navbutton" href="det_hook_rt.html">&#x2190;</a><a class="lpdoc-navbutton" href="lazy_lib.html">&#x2192;</a><a class="lpdoc-navbutton" href="ciaosearch.html">&#x1F50D;</a></span><span><a href="ciaofulltoc.html">TOC</a></span></div><hr></hr><ul class="lpdoc-itemize-sectpath"><li><a href="ciao.html">The Ciao System</a> &raquo;<br/> </li><li><a href="ExtendLang.html">PART IV - Language extensions</a> &raquo;<br/> </li><li><a href=""><strong>Lazy evaluation</strong></a> &#9662;<ul><li><a href="lazy_lib.html">Lazy evaluation library</a></li></ul></li></ul><hr></hr><em>ON THIS PAGE</em><ul><li><a href="#Usage and interface">Usage and interface</a></li><li><a href="#Other information">Other information</a></li></ul></div><div class="lpdoc-main"><div id=""><h1>Lazy evaluation</h1><a class="lpdoc-idx-anchor" href="ciaosearch.html#lazy"></a> <strong>Author(s):</strong> <a class="lpdoc-idx-anchor" id="Amadeo Casas" href="ciaosearch.html#Amadeo Casas">Amadeo Casas</a>, <a class="lpdoc-idx-anchor" id="Jose F. Morales" href="ciaosearch.html#Jose F. Morales">Jose F. Morales (minor modifications)</a>.<p> This library package allows the use of lazy evaluation in a Ciao module/program.<p>Lazy Evaluation is a program evaluation technique used particularly in functional languages. When using lazy evaluation, an expression is not evaluated as soon as it is assigned, but rather when the evaluator is forced to produce the value of the expression. Although the <tt>when</tt> or <tt>freeze</tt> control primitives present in many modern logic programming systems are more powerful than lazy evaluation, they lack the simplicity of use and cleaner semantics of functional lazy evaluation.<p>The objective of this package is to allow evaluating the functions lazily. Functions are the subset of relations (predicates) which have a designated argument through which a single output is obtained for any set of inputs (the other arguments). In logic programming systems which have syntactic support for functions (including Ciao), functions are typically translated to predicates whose <tt>last</tt> argument is designated as a (single value) output and the rest as inputs.<p>In our proposal, a function can be declared as lazy via the following declaration:<p> <pre class="lpdoc-codeblock">:- lazy fun_eval f/N. </pre> <p> This function could be represented as:<p><pre class="lpdoc-codeblock">:- lazy fun_eval f(~_,_,_,_). </pre> <p>where ~ indicates the argument through which the single output will be obtained. Another possible representation may be:<p><pre class="lpdoc-codeblock">:- lazy fun_return f(~_,_,_,_). </pre> <p> In order to achieve the intended behavior, the execution of each function declared as lazy is suspended until the return value of the function is needed.<p>A simple example of the use of lazy evaluation would be the definition of a function which returns the (potentially) infinite list of integers starting with a given one:<p><pre class="lpdoc-codeblock">:- lazy fun_eval nums_from/1. nums_from(X) := [X | nums_from(X+1)]. </pre> <p> While lazy functions certainly increase the overhead in the execution, they also allow the user to develop in an easy way predicates which can handle infinite terms, and this is the main advantage of the proposed functionality.<p>Lazy evaluation can be also a better option than eager evaluation when a function in a different module is used and it returns a big amount of data. As an example, we have the following module <tt>module1</tt>:<p><pre class="lpdoc-codeblock">:- module(module1, [test/1], [fsyntax, lazy, hiord]). :- use_module(library(lazy/lazy_lib), [nums_from/2, takeWhile/3]). :- use_module(module2, [squares/2]). :- use_module(library(arithpreds)). :- fun_eval test/0. test := ~takeWhile((&apos;&apos;(X) :- X &lt; 10000), ~squares(~nums_from(1))). </pre> <p> and another module <tt>module2</tt>:<p> <pre class="lpdoc-codeblock">:- module(module1, [test/1], [fsyntax, lazy, hiord]). :- use_module(library(lazy/lazy_lib), [nums_from/2, takeWhile/3]). :- use_module(module2, [squares/2]). :- use_module(library(arithpreds)). :- fun_eval test/0. test := ~takeWhile((&apos;&apos;(X) :- X &lt; 10000), ~squares(~nums_from(1))). </pre> <p> Function <tt>test/0</tt> in module <tt>m1</tt> needs to execute function <tt>squares/1</tt>, in module <tt>m2</tt>, which will return a very long list (in the case of this example this list will be infinite, but the conclusions also apply with finite but long lists). If <tt>squares/1</tt> were executed eagerly then the entire list would be returned, to immediately execute the <tt>take/2</tt> function with the entire list, but creating this intermediate result is wasteful in terms of memory requirements. In order to solve this problem, the <tt>squares/1</tt> function could be moved to module <tt>m1</tt> and merged with <tt>take/2</tt> (or, also, they could exchange a size parameter). But rearranging the program is not always possible and may perhaps complicate other aspects of the overall program design.<p>If instead the <tt>squares/1</tt> function is evaluated lazily, it is possible to keep the definitions unchanged and in different modules and there will be a smaller memory penalty for storing the intermediate result. As more values are needed by the <tt>take/2</tt> function, more values in the list returned by <tt>squares/1</tt> are built (in this example, only 10 values). These values that have been consumed and passed over will be recovered by the garbage collector and the corresponding memory freed. The query:<p> <pre class="lpdoc-codeblock">?- test(X). </pre> <p> will compute <span class="lpdoc-var">X</span> = [1,4,9,16,25,36,49,64,81,100].<p>Some common lazy predicates are provided in <a class="lpdoc-idx-anchor" id="0" href="lazy_lib.html"><tt>lazy_lib</tt></a>. <br/><div id="Usage and interface"><h2>Usage and interface</h2><div class="lpdoc-cartouche"><ul><li><strong>Library usage:</strong><br/><tt>:- use_package(lazy).</tt> or <tt>:- module(...,...,[lazy]).</tt><li><strong>New operators defined:</strong><br/><a class="lpdoc-idx-anchor" id="1" href="ciaosearch.html#lazy/1"><tt>lazy/1</tt></a> [1170,fx]. <li><strong>Implicit imports:</strong><br/><ul class="lpdoc-itemize-minus"><li><em>System library modules:</em><br/><a class="lpdoc-idx-anchor" id="2" href="freeze.html"><tt>freeze</tt></a>. <li><em>Packages:</em><br/><a class="lpdoc-idx-anchor" id="3" href="ciaosearch.html#prelude"><tt>prelude</tt></a>, <a class="lpdoc-idx-anchor" id="4" href="ciaosearch.html#initial"><tt>initial</tt></a>, <a class="lpdoc-idx-anchor" id="5" href="condcomp_doc.html"><tt>condcomp</tt></a>, <a class="lpdoc-idx-anchor" id="6" href="assertions_doc.html"><tt>assertions</tt></a>, <a class="lpdoc-idx-anchor" id="7" href="ciaosearch.html#assertions/assertions_basic"><tt>assertions/assertions_basic</tt></a>. </ul></ul></div></div><div id="Other information"><h2>Other information</h2> The translation of the code in order to execute it lazily is explained below.<p>A sentence translation is provided to handle the <tt>lazy</tt> directives. The translation of a lazy function into a predicate is done in two steps. First, the function is converted into a predicate (using the fsyntax package). Then, the resulting predicate is transformed to suspend its execution until the value of the last variable (i.e., the output variable) is needed. This suspension is achieved by the use of the <tt>freeze/1</tt> control primitive that many modern logic programming systems implement quite efficiently (<tt>block</tt> or <tt>when</tt> declarations can obviously also be used, but we explain the transformation in terms of <tt>freeze</tt> because it is more widespread). The translation will rename the original predicate to an internal name and add a bridge predicate with the original name which invokes the internal predicate through a call to <tt>freeze/1</tt>. This will delay the execution of the internal predicate until its result is required, which will be detected as a binding (i.e., demand) of its output variable.<p>We show now an example of the use of lazy evaluation, and how a lazy function is translated by this package. The following code returns an (infinite) list of fibonacci numbers:<p> <pre class="lpdoc-codeblock">:- lazy fun_eval fiblist/0. fiblist := [0, 1 | ~zipWith(add, FibL, ~tail(FibL))] :- FibL = fiblist. </pre> <p> which is translated into:<p> <pre class="lpdoc-codeblock">fiblist(X) :- freeze(X, &apos;fiblist_$$lazy$$&apos;(X)). &apos;fiblist_$$lazy$$&apos;([0, 1 | Rest]) :- fiblist(FibL), tail(FibL, T), zipWith(add, FibL, T, Rest). </pre> <p> In the <tt>fiblist</tt> function defined, any element in the resulting infinite list of fibonacci numbers can be referenced, as for example, <tt>nth(X, ~fiblist, Value).</tt>. The other functions used in the definition are <tt>tail/2</tt> and <tt>zipWith/3</tt>. These two functions can be found in the <strong>lazy_lib.pl</strong> runtime file.<p><br/></div></div><div class="lpdoc-footer">Generated with LPdoc using Ciao</div></div><div class="lpdoc-clearer"></div></div></body></html>