Giter Site home page Giter Site logo

jmbr / incf-cl Goto Github PK

View Code? Open in Web Editor NEW
23.0 4.0 4.0 135 KB

A collection of convenience functions and macros for Common Lisp. Moved to https://git.sr.ht/~jmbr/incf-cl

Home Page: https://git.sr.ht/~jmbr/incf-cl

License: MIT License

Common Lisp 100.00%
common-lisp utility-library

incf-cl's Introduction

(INCF CL)

Overview

The library (INCF CL) is a collection of convenience functions and macros for Common Lisp. The features it provides are:

  • List comprehensions.
  • Doctest suite for automatic verification of examples in docstrings.
  • List manipulation functions similar to those in Haskell’s prelude.
  • Nesting functions akin to those available in Mathematica.

This library is released under the X11 license and it has been tested with the following Common Lisp implementations:

Usage

Installation

The easiest way to install (INCF CL) is to use Quicklisp:

(ql:quickload "incf-cl")

You may alternatively clone the source code repository by issuing the following command:

$ git clone https://github.com/jmbr/incf-cl.git

and then follow the ASDF installation procedure for your CL implementation.

Loading the library

To begin using the library, write:

(use-package :incf-cl)

Features

Ranges

The function RANGE is similar to MATLAB’s vector notation. Some use cases are:

CL-USER> (range 1 10)
(1 2 3 4 5 6 7 8 9 10)

CL-USER> (range 0 1/4 1)
(0 1/4 1/2 3/4 1)

List comprehensions

List comprehensions are a programming language construct that closely mimics the way you declare a set in mathematics and are sometimes more succinct and readable than a composition of MAPCAR and DELETE-IF or a loop.

Here are two examples of how to use the LC (short for List Comprehension) macro:

CL-USER> (lc (sin x) (<- x (range 0 .25 (/ pi 2))))
(0.0 0.24740396 0.47942555 0.6816388 0.84147096 0.9489846 0.997495)
CL-USER> (lc (cons x y) (<- x (range 0 2)) (<- y (range 0 2))
             (= (+ x y) 2))
((0 . 2) (1 . 1) (2 . 0))

Doctests

DOCTEST checks documentation strings for correctness. For every exported function in the package name passed to DOCTEST,

  1. each docstring is scanned for pieces of text resembling interactive sessions,
  2. then those snippets are evaluated,
  3. and the resulting values are checked against the expected ones.

For example, consider the package TEST:

(defpackage :test
  (:use :common-lisp :incf-cl)
  (:export :factorial))

(in-package :test)

(defun factorial (n &optional (acc 1))
  "Returns the factorial of N, where N is an integer >= 0.

  Examples:

  TEST> (lc (factorial n) (<- n (range 1 5)))
  (1 2 6 24 120)

  TEST> (factorial 450/15)
  265252859812191058636308480000000

  TEST> (signals-p arithmetic-error (factorial -1))
  T

  TEST> (signals-p type-error (factorial 30.1))
  T

  TEST> (factorial 0)
  1"
  (declare (type integer n))

  (cond
    ((minusp n) (error 'arithmetic-error))
    ((/= n (floor n)) (error 'type-error)))

  (if (= n 0)
      acc
      (factorial (1- n) (* n acc))))

You can use DOCTEST to make sure the examples given in FACTORIAL’s documentation string work as expected by writing

CL-USER> (doctest :test)
.....
T

Or, equivalently,

CL-USER> (doctest 'test::factorial)
.....
T

Prelude

Some list manipulation functions patterned after Haskell’s prelude are available. Namely,

  • BREAK*
  • CYCLE (and its destructive version NCYCLE).
  • DROP
  • DROP-WHILE
  • FLIP
  • GROUP
  • INSERT
  • INTERSPERSE (and its destructive version NINTERSPERSE).
  • PARTITION
  • REPLICATE
  • SCAN* (using the key parameters :INITIAL-VALUE and :FROM-END it works as scanl, scanl1, scanr, or scanr1)
  • SPAN
  • SPLIT-AT
  • TAKE
  • TAKE-WHILE
  • UNZIP

The on-line documentation for each of them can be read using DESCRIBE (or M-x slime-describe-symbol in SLIME). See also A Tour of the Haskell Prelude by Bernie Pope for more information.

Since Common Lisp doesn’t guarantee tail call elimination, these functions are written iteratively to avoid stack overflows.

Nesting

The function NEST-LIST applies a function to an initial value, then applies the same function to the previous result, and so on. This stops after a specified number of evaluations or when a given predicate is true and a list containing all the results is returned.

NEST works as NEST-LIST but it only returns the last result, not the whole list.

Some examples:

CL-USER> (setf *print-circle* nil)
NIL
CL-USER> (nest-list (lambda (x) `(sin ,x)) 'z :max 3)
(Z (SIN Z) (SIN (SIN Z)) (SIN (SIN (SIN Z))))

CL-USER> (nest-list #'+ '(1 1) :max 10)
(1 1 2 3 5 8 13 21 34 55 89 144)

CL-USER> (nest #'+ '(1 1) :max 10)
144

CL-USER> (nest-list (lambda (x) (mod (* 2 x) 19))
                    2
                    :test (lambda (x) (/= x 1)))
(2 4 8 16 13 7 14 9 18 17 15 11 3 6 12 5 10 1)

The closely related function FIXED-POINT returns the fixed point of a function starting from an initial value. Whether a fixed point has been reached or not is determined by a test function (EQL by default).

For example, the square root of 2 using Newton’s method can be computed as:

CL-USER> (fixed-point (lambda (x)
                        (float (- x (/ (- (expt x 2) 2) (* 2 x)))))
                      1)
1.4142135

Unfolds

There’s an implementation of UNFOLD and UNFOLD-RIGHT as specified in SRFI 1: List library. Here’s an example of UNFOLD:

(defun euler (f x0 y0 interval h)
  "Computes an approximate solution of the initial value problem:

    y'(x) = f(x, y), x in interval;  y(x0) = y0

  using Euler's explicit method.  Interval is a list of two elements
  representing a closed interval.  The function returns a list of
  points and the values of the approximate solution at those points.

  For example,

  EULER> (euler (lambda (x y)
                  (declare (ignore y))
                  (- (sin x)))
                0 1 (list 0 (/ pi 2)) 0.5)
  ((0 1) (0.5 1.0) (1.0 0.7602872) (1.5 0.33955175))"
  (assert (<= (first interval) (second interval)))
  (unfold (lambda (x) (> (first x) (second interval)))
          #'identity
          (lambda (pair)
            (destructuring-bind (x y) pair
              (list (+ x h) (+ y (* h (funcall f x y))))))
          (list x0 y0)))

Functions

The function $ returns the composition of several functions. The following example illustrates its use:

CL-USER> (funcall ($ (lambda (x) (* x x))
                     (lambda (x) (+ x 2)))
                  2)
16

Hash table utilities

DOHASH iterates over a hash table with semantics similar to those of DOLIST:

CL-USER> (defparameter *hash-table* (make-hash-table))
*HASH-TABLE*
CL-USER> (setf (gethash "one" *hash-table*) 1)
1
CL-USER> (setf (gethash "two" *hash-table*) 2)
2
CL-USER> (setf (gethash "three" *hash-table*) 3)
3
CL-USER> (dohash (key value *hash-table*)
           (format t "~a => ~d~%" key value))
three => 3
two => 2
one => 1
NIL
CL-USER> (let ((product 1))
           (dohash (key value *hash-table* product)
             (setf product (* product value))))
6

Strings

STRING-JOIN glues together a list of strings placing a given separator between each string. By default, the separator is a space.

CL-USER> (string-join '("Hello" "world"))
"Hello world"
CL-USER> (string-join '("Hello" "world") ", ")
"Hello, world"

Feedback

Please use Github to send patches and bug reports.

incf-cl's People

Contributors

jmbr avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

incf-cl's Issues

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.