;;; -*- Mode:LISP; Package:PUSER; Base:10 -*- ;;; (C) Copyright 1983,1984,1985, Uppsala University ;;; Peter Henderson's examples of "delayed evaluation". ;;; "Functional Programming" pp. 214--241. ;;; The general programming style is: ;;; Whenever a structure is "generated", delay the computation of some part of it, ;;; typically its rest. ;;; In all these examples, one could use a sort of :ARGUMENT-LIST declaration ;;; instead of PROLOG:CONSTRAIN. (define-predicate sum-ints ((sum-ints ?n ?sum) (prolog:constrain ?ints (integers-beginning ?n ?ints)) (sum-all ?ints 0 ?sum))) (define-predicate sum-all ((sum-all () ?s ?s)) ((sum-all (?i . ?j) ?s ?u) (sum ?t ?s ?i) (sum-all ?j ?t ?u))) (define-predicate first-k ((first-k 0 ? ()) (cut)) ((first-k ?k (?x . ?rest) (?x . ?rest-k)) (sum ?k-1 ?k -1) (first-k ?k-1 ?rest ?rest-k))) ;;; The SAME-FRINGE problem. (define-predicate same-fringe ((same-fringe ?tree1 ?tree2) (prolog:constrain ?tree1 (flatten ?tree1 ?flat ())) (prolog:constrain ?tree2 (flatten ?tree2 ?flat ())))) ;If there are two FLATTEN producers, then run one of them. (define-predicate prolog:*combine-constraints* (:options (:if-old-definition :keep)) (flatten (prolog:*combine-constraints* :invoke (flatten . ?) (flatten . ?)))) (define-predicate flatten ((flatten () ?f ?f) (cut)) ((flatten (?x . ?rest) ?f0 ?f) (cut) (flatten ?x ?f0 ?f1) (prolog:constrain ?f1 (flatten ?rest ?f1 ?f))) ((flatten ?x (?x . ?f) ?f))) ;;A Fibonacci series. (define-predicate fibonaccis ((fibonaccis (1 1 . ?series)) (prolog:constrain ?series (stream-sum ?series (1 . ?series) (1 1 . ?series))))) (define-predicate stream-sum ((stream-sum (?a . ?as) (?b . ?bs) (?c . ?cs)) (sum ?a ?b ?c) (prolog:constrain ?as (stream-sum ?as ?bs ?cs)))) ;;A Hamming series. (define-predicate hamming ((hamming ?x) (= ?x (1 . ?x235)) (prolog:constrain ?x235 (merge ?x235 ?x23 ?x5)) (prolog:constrain ?x23 (merge ?x23 ?x2 ?x3)) (prolog:constrain ?x2 (mul ?x2 ?x 2)) (prolog:constrain ?x3 (mul ?x3 ?x 3)) (prolog:constrain ?x5 (mul ?x5 ?x 5)))) (define-predicate merge ((merge ?merged (?u . ?rest1) (?u . ?rest2)) (merge ?merged ?rest1 (?u . ?rest2))) ((merge (?x . ?merged) (?x . ?rest1) (?y . ?rest2)) (< ?x ?y) (prolog:constrain ?merged (merge ?merged ?rest1 (?y . ?rest2)))) ((merge (?y . ?merged) (?x . ?rest1) (?y . ?rest2)) (> ?x ?y) (prolog:constrain ?merged (merge ?merged (?x . ?rest1) ?rest2)))) (define-predicate mul ((mul () () ?)) ((mul (?x*y . ?rest*y) (?x . ?rest) ?y) (product ?x*y ?x ?y) (prolog:constrain ?rest*y (mul ?rest*y ?rest ?y)))) ;;A Sieve of Eratosthenes using integer streams. (define-predicate integers-beginning ((integers-beginning ?n (?n . ?rest)) (sum ?n+1 ?n 1) (prolog:constrain ?rest (integers-beginning ?n+1 ?rest)))) (define-predicate primes ((primes ?primes) (integers-beginning 2 ?integers) (sift ?primes ?integers))) (define-predicate sift ((sift (?first . ?rest-sifted) (?first . ?rest-integers)) (no-multiples ?rest-left ?first ?rest-integers) (prolog:constrain ?rest-sifted (sift ?rest-sifted ?rest-left)))) ;;Write this with one clause to avoid repeated unifications with third arg ;;which is a constrained variable. ;;Having two clauses slows down this particular program tremendously. (define-predicate no-multiples ((no-multiples ?filtered ?n (?int0 . ?int)) (cases ((lisp-predicate (zerop (\ '?int0 '?n)) :dont-invoke) (no-multiples ?filtered ?n ?int)) ((= ?filtered (?int0 . ?rest-filtered)) (prolog:constrain ?rest-filtered (no-multiples ?rest-filtered ?n ?int)))))) (define-predicate print-primes ((print-primes) (primes ?primes) (map print ?primes)))