So long, and thanks for all the functional fish! (30 Mar 2008)

1982. I'm not even sure if I already had my first computer back then - but that's the year when Peter Henderson published an article about Functional Geometry, in which he describes how to build images from equations, and how to create big images from smaller ones using functional composition.

The original implementation was in UCSD Pascal. A while ago, part-time Lisp hacker Frank Buß ported it to Lisp and added Postscript output, and he also posted a very nice description of his approach, illustrating how this example helped him understand how valuable support for higher-order functions in a language can be.

Frank's code is clear and compact, and the platform dependencies are all in one function, which made it easy to adapt to CoCreate Modeling's dialect of Common Lisp. In fact, all that's needed to run the code is the following loader code:

;; -*-Lisp-*-
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Description:  Wrapper to run Frank Buss' functional geometry code
;;               in CoCreate Modeling
;; Author:       Claus Brod  
;; Language:     Lisp
;;
;; (C) Copyright 2008 Claus Brod, all rights reserved
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;

(in-package :clausbrod.de)
(use-package :oli)
(export '(plot-escher))

;; Allow using lambda without quoting it via #' first
;; (No longer required in CoCreate Modeling 2008 and later.)
(defmacro lambda (&rest body)
  `(function (lambda ,@body)))

(defparameter *our-loadpath* *load-truename*)
(load (format nil "~A/functional.lsp"
              (directory-namestring *our-loadpath*)))

;; Modeling-specific plotter function
(defun plot-annotation (p)
  (let ((tempfile (format nil "~A/test.mac" (oli:sd-inq-temp-dir)))
        (scale 500.0))
    (startup::activate-annotation)

    (with-open-file (s tempfile
                       :direction :output :if-exists :supersede)
      (format s "line~%")

      (dolist (line (funcall p '(0 0) '(1 0) '(0 1)))
        (destructuring-bind ((x0 y0) (x1 y1)) line
          (format s "  ~D,~D ~D,~D~%"
                  (* scale (float x0))
                  (* scale (float y0))
                  (* scale (float x1))
                  (* scale (float y1)))))

      (format s "end"))

    (oli:sd-execute-annotator-command
     :cmd (format nil "input '~A'" tempfile))
    (docu::docu_vp :fit_vp)
    (delete-file tempfile)))

;; Shortcut for the Escher fish drawing
(defun plot-escher()
  (plot-annotation *fishes*))

The loader code adds the definition for the lambda macro which is missing so far in CoCreate Modeling, loads Frank's code, and then adds a plotter function which creates output in a 2D Annotation window.

Usage instructions:

  • Download Frank's code from his site and save it as functional.lsp.
  • Download the loader code and save it into the same directory.
  • Load the loader Lisp code into CoCreate Modeling 2007 or higher.
  • In the user input line, enter (clausbrod.de:plot-escher)

Thanks to Frank for this cute demo code!



When asked for a TWiki account, use your own or the default TWikiGuest account.


Revision: r1.1 - 31 Mar 2008 - 18:03 - ClausBrod
Blog > DefinePrivatePublic20080330FunctionalFish
Copyright © 1999-2024 by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding TWiki? Send feedback