GithubHelp home page GithubHelp logo

optima's Introduction

optima - Optimized Pattern Matching Library

optima is a fast pattern matching library which uses optimizing techniques widely used in the functional programming world. See the following references for more details:

Pattern Language

A pattern specifier, or a pattern for short ambiguous, is an expression that describes how a value matches some specification. Pattern specifiers are defined as follows:

pattern-specifier ::= constant-pattern
                    | variable-pattern
                    | place-pattern
                    | guard-pattern
                    | not-pattern
                    | or-pattern
                    | and-pattern
                    | constructor-pattern
                    | derived-pattern
constant-pattern ::= t | nil
                   | keyword
                   | atom-except-symbol
                   | (quote VALUE)
variable-pattern ::= SYMBOL | (variable SYMBOL)
place-pattern ::= (place SYMBOL)
guard-pattern ::= (guard PATTERN TEST-FORM)
not-pattern ::= (not PATTERN)
or-pattern ::= (or PATTERN*)
and-pattern ::= (and PATTERN*)
constructor-pattern ::= (NAME ARG*)
derived-pattern ::= (NAME PATTERN*)

Constant-Pattern

A constant-pattern matches the constant itself.

Examples:

(match 1 (1 2)) => 2
(match "foo" ("foo" "bar")) => "bar"
(match '(1) ('(1) 2)) => 2

Variable-Pattern

A variable-pattern matches any value and binds the value to the variable. "_" and "otherwise" are special variable-patterns (a.k.a wildcard-pattern) which match any value but don't bind.

Examples:

(match 1 (x x)) => 1
(match 1 (_ 2)) => 2
(match 1
  (2 2)
  (otherwise 'otherwise))
=> OTHERWISE

Place-Pattern

A place-pattern matches any value, in the same way as variable-patterns do, but binds the value by using SYMBOL-MACROLET.

Examples:

(defvar c (cons 1 2))
(match c ((cons (place x) y) (incf x) (incf y)))
c
 => (2 . 2)

Guard-Pattern

A guard-pattern is a special pattern that tests whether TEST-FORM is satisfied in the current matching context.

Examples:

(match 1 ((guard x (eql x 2)) t))
=> NIL
(match 1 ((guard x (eql x 1)) t))
=> T

Not-Pattern

A not-pattern matches a value that is not matched with sub-PATTERN.

Examples:

(match 1 ((not 2) 3)) => 3
(match 1 ((not (not 1)) 1)) => 1

Or-Pattern

An or-pattern matches a value that is matched with one of sub-PATTERNs.

Examples:

(match '(2 . 1) ((or (cons 1 x) (cons 2 x)) x))
=> 1

And-Pattern

An and-pattern matches a value that is matched with all of its sub-PATTERNs. The most common use case is to match a value and bind the value to a variable.

Examples:

(match 1 ((and 1 x) x))
=> 1

Constructor-Pattern

A constructor-pattern matches the sub-components of a value based on its structure. The following constructors are available:

CONS

Syntax:

cons-constructor-pattern ::= (cons CAR-PATTERN CDR-PATTERN)

Examples:

(match '(1 . 2)
  ((cons a b) (+ a b)))
 => 3

ASSOC

Syntax:

assoc-constructor-pattern ::= (assoc ITEM PATTERN &key key test)

Examples:

(match '((1 . :one))
  ((assoc 1 x) x))
=> :ONE
(match '((1 . :one) (2 . :two))
  ((assoc 2 x) x))
=> :TWO
(match '(1 (2 . 3))
  ((assoc 2 x) x))
=> 3
(match '(("a" . 123))
  ((assoc "A" 123 :test #'string-equal) t))
=> T

PROPERTY

Syntax:

property-constructor-pattern ::= (property KEY PATTERN)

Examples:

(match '(:a 1)
  ((property :a x) x))
=> 1
(match '(:a 1 :b 2)
  ((property :b x) x))
=> 2
(match '(:a 1 2)
  ((property :a x) x))
=> 1

VECTOR

Syntax:

vector-constructor-pattern ::= (vector PATTERN*)

Examples:

(match #(1 2)
  ((vector a b) (+ a b)))
=> 3

SIMPLE-VECTOR

Syntax:

simple-vector-constructor-pattern ::= (simple-vector PATTERN*)

Examples:

(match #(1 2)
  ((simple-vector a b) (+ a b)))
=> 3

CLASS

Matches an instance of a given subclass of standard-class, as well as the instance's slots.

Syntax:

class-constructor-pattern ::= (class NAME slot*)
                            | (NAME slot*)
slot ::= SLOT-NAME
       | (SLOT-NAME PATTERN*)

CLASS can be omitted. If slot is a symbol, then it will be regarded as (slot slot). If more than one PATTERN is given, then they will be wrapped by and-pattern like (and PATTERN*).

Examples:

(defclass point ()
  ((x :initarg :x)
   (y :initarg :y)))
(defvar p (make-instance 'point :x 1 :y 2))
(match p
  ((point x y) (list x y)))
=> (1 2)
(match p
  ((point (x 1 x)) x))
=> 1
(defstruct person (name age))
(defvar foo (make-person :name "foo" :age 30))
(match foo
  ((person name age) (list name age)))
=> ("foo" 30)

You can also use MAKE-INSTANCE style pattern syntax like:

(match foo
  ((person :name name :age age) (list name age)))
=> ("foo" 30)

This is equal to the example above except this implicitly resolves the slot names using the Metaobject Protocol. In this case, you have to make sure the slot names can be determined uniquely during the compilation. Otherwise, you will get a compiler error.

STRUCTURE

Matches any structure value, and its slot values.

Syntax:

structure-constructor-pattern ::= (structure CONC-NAME slot*)
                                | (CONC-NAME slot*)
slot ::= SLOT-NAME
       | (SLOT-NAME PATTERN*)

As in the CLASS constructor-pattern, STRUCTURE can be omitted. CONC-NAME is a prefix string of a predicate (CONC-NAME + "p") and accessors (CONC-NAME + SLOT-NAME). For example, if we have the following defstruct,

(defstruct person name age)

the structure constructor-pattern (person- name age) is valid because PERSON-P, PERSON-NAME and PERSON-AGE are available here. Technically, we don't need an actual structure definition. If we have the following code, for instance,

(defun point-p (p) (consp p))
(defun point-x (p) (car p))
(defun point-y (p) (cdr p))

the pattern matching below is valid.

(match (cons 1 2)
  ((point- x y) (list x y)))
=> (1 2)

Examples:

(defstruct (person (:conc-name :p-)
                   (:predicate p-p))
  name age)
(match (make-person :name "foo" :age 30)
  ((p- name age) (list name age)))
=> ("foo" 30)

As in the class constructor-pattern, you can also use MAKE-INSTANCE style pattern syntax like:

(match (cons 1 2)
  ((point- :x x :y y) (list x y)))
=> (1 2)

Derived-Pattern

A derived-pattern is a pattern that is defined with DEFPATTERN. There are some builtin derived patterns as below:

LIST

Expansion of LIST derived patterns:

(list a b c) => (cons a (cons b (cons c nil)))

LIST*

Expansion of LIST* derived patterns:

(list* a b c) => (cons a (cons b c))

SATISFIES

Expansion of SATISFIES derived patterns:

(satisfies f) => (guard it (f it))

EQ, EQL, EQUAL, EQUALP

Expansion of EQ, EQL, EQUAL, EQUALP derived patterns:

(eq 'foo) => (guard it (eq it 'foo))
(eql 123) => (guard it (eql it 123))
(equal '(1 2)) => (guard it (equal it '(1 2)))
(equalp "foo") => (guard it (equalp it "foo"))

TYPE

Expansion of TYPE derived patterns:

(TYPE type) => (guard it (typep it 'type))

Quasiquotation

You may want to use a quasiquote in a pattern specifier like:

(match '(1 2 3 4)
  (`(1 ,x ,@y) (list x y)))

To do so, you need to use a specific quasiquote reader, for example fare-quasiquote , loading fare-quasiquote-optima system, because there is no standard expanded form for quasiquote expressions.

Define Constructor Patterns

You can define your own constructor patterns by using the OPTIMA.CORE package. First, define a data structure for the constructor pattern.

(defstruct (my-cons-pattern (:include constructor-pattern)
                            (:constructor make-cons-pattern (car-pattern cdr-pattern
                                                             &aux (subpatterns (list car-pattern
                                                                                     cdr-pattern))))))

Note that you must keep SUBPATTERNS of the constructor pattern in sync so that optima can take care of them.

Second, specify a condition for when the destructor of two constructor patterns can be shared. This makes it possible to perform some optimizations.

(defmethod constructor-pattern-destructor-sharable-p ((x my-cons-pattern) (y my-cons-pattern))
  t)

Third, define a destructor generator for the constructor pattern. The destructor generator will make a destructor that specifies how to check the the data (PREDICATE-FORM) and how to access the data (ACCESSOR-FORMS).

(defmethod constructor-pattern-make-destructor ((pattern my-cons-pattern) var)
  (make-destructor :predicate-form `(consp ,var)
                   :accessor-forms (list `(car ,var) `(cdr ,var))))

Finally, define a parser and an unparser for the constructor pattern.

(defmethod parse-constructor-pattern ((name (eql 'my-cons)) &rest args)
  (apply #'make-my-cons-pattern (mapcar #'parse-pattern args)))
(defmethod unparse-pattern ((pattern my-cons-pattern))
  `(cons ,(unparse-pattern (my-cons-pattern-car-pattern pattern))
         ,(unparse-pattern (my-cons-pattern-cdr-pattern pattern))))

See the source code for more detail.

[Package] optima.core

[Function] %equal

%equal a b

Equality function for comparing pattern constants.

[Macro] %equals

%equals var value

Equality macro for comparing pattern constants. This specializes the comparison form to some specific form as follows:

(equals x nil)    => (null x)
(equals x 'foo)   => (eq x 'foo)
(equals x 123)    => (eql x 123)
(equals x '(a b)) => (%equals x '(a b))

[Function] %svref

%svref simple-vector index

Safe SVREF.

[Function] %assoc

%assoc item alist &key (test #'eql)

Safe ASSOC.

[Function] %get-property

%get-property item plist

Safe GETF.

[Class] destructor

[Type] destructor

destructor

[Function] destructor-accessor-forms

destructor-accessor-forms instance

[Function] make-destructor

make-destructor &key ((bindings bindings) nil) ((predicate-form predicate-form)
                                                nil) ((accessor-forms
                                                       accessor-forms)
                                                      nil)

[Class] variable-pattern

[Type] variable-pattern

variable-pattern

[Function] variable-pattern-name

variable-pattern-name instance

[Function] make-variable-pattern

make-variable-pattern &optional name

[Class] place-pattern

[Type] place-pattern

place-pattern

[Function] place-pattern-name

place-pattern-name instance

[Function] make-place-pattern

make-place-pattern name

[Class] constant-pattern

[Type] constant-pattern

constant-pattern

[Function] constant-pattern-value

constant-pattern-value instance

[Function] make-constant-pattern

make-constant-pattern value

[Class] complex-pattern

[Type] complex-pattern

complex-pattern

[Function] complex-pattern-subpatterns

complex-pattern-subpatterns instance

[Class] guard-pattern

[Type] guard-pattern

guard-pattern

[Function] guard-pattern-test-form

guard-pattern-test-form instance

[Function] guard-pattern-subpattern

guard-pattern-subpattern pattern

[Function] make-guard-pattern

make-guard-pattern subpattern test-form &aux (subpatterns (list subpattern))

[Class] not-pattern

[Type] not-pattern

not-pattern

[Function] not-pattern-subpattern

not-pattern-subpattern pattern

[Function] make-not-pattern

make-not-pattern subpattern &aux (subpatterns (list subpattern))

[Class] or-pattern

[Type] or-pattern

or-pattern

[Function] or-pattern-subpatterns

or-pattern-subpatterns instance

[Function] make-or-pattern

make-or-pattern &rest subpatterns

[Class] and-pattern

[Type] and-pattern

and-pattern

[Function] and-pattern-subpatterns

and-pattern-subpatterns instance

[Function] make-and-pattern

make-and-pattern &rest subpatterns

[Class] constructor-pattern

[Type] constructor-pattern

constructor-pattern

[Function] constructor-pattern-subpatterns

constructor-pattern-subpatterns instance

[Function] constructor-pattern-arity

constructor-pattern-arity pattern

[Function] constructor-pattern-destructor-sharable-p

constructor-pattern-destructor-sharable-p x y

[Function] constructor-pattern-make-destructor

constructor-pattern-make-destructor pattern var

[Class] cons-pattern

[Type] cons-pattern

cons-pattern

[Function] cons-pattern-car-pattern

cons-pattern-car-pattern pattern

[Function] cons-pattern-cdr-pattern

cons-pattern-cdr-pattern pattern

[Function] make-cons-pattern

make-cons-pattern car-pattern cdr-pattern &aux (subpatterns
                                                (list car-pattern cdr-pattern))

[Class] assoc-pattern

[Type] assoc-pattern

assoc-pattern

[Function] assoc-pattern-item

assoc-pattern-item instance

[Function] assoc-pattern-key

assoc-pattern-key instance

[Function] assoc-pattern-test

assoc-pattern-test instance

[Function] assoc-pattern-value-pattern

assoc-pattern-value-pattern pattern

[Function] make-assoc-pattern

make-assoc-pattern item value-pattern &key (key nil) (test nil) &aux (subpatterns
                                                                      (list
                                                                       value-pattern))

[Class] property-pattern

[Type] property-pattern

property-pattern

[Function] property-pattern-item

property-pattern-item instance

[Function] property-pattern-value-pattern

property-pattern-value-pattern pattern

[Function] make-property-pattern

make-property-pattern item value-pattern &aux (subpatterns (list value-pattern))

[Class] vector-pattern

[Type] vector-pattern

vector-pattern

[Function] vector-pattern-subpatterns

vector-pattern-subpatterns instance

[Function] make-vector-pattern

make-vector-pattern &rest subpatterns

[Class] simple-vector-pattern

[Type] simple-vector-pattern

simple-vector-pattern

[Function] simple-vector-pattern-subpatterns

simple-vector-pattern-subpatterns instance

[Function] make-simple-vector-pattern

make-simple-vector-pattern &rest subpatterns

[Class] class-pattern

[Type] class-pattern

class-pattern

[Function] class-pattern-subpatterns

class-pattern-subpatterns instance

[Function] class-pattern-class-name

class-pattern-class-name instance

[Function] class-pattern-slot-names

class-pattern-slot-names instance

[Function] make-class-pattern

make-class-pattern class-name &rest slot-specs

[Class] structure-pattern

[Type] structure-pattern

structure-pattern

[Function] structure-pattern-subpatterns

structure-pattern-subpatterns instance

[Function] structure-pattern-conc-name

structure-pattern-conc-name instance

[Function] structure-pattern-slot-names

structure-pattern-slot-names instance

[Function] make-structure-pattern

make-structure-pattern conc-name &rest slot-specs

[Function] pattern-variables

pattern-variables pattern

Returns the set of variables in PATTERN. If PATTERN is not linear, an error will be raised.

[Function] place-pattern-included-p

place-pattern-included-p pattern

[Function] check-patterns

check-patterns patterns

Check if PATTERNS are valid. Otherwise, an error will be raised.

[Function] lift-guard-patterns

lift-guard-patterns pattern

[Function] pattern-expand-function

pattern-expand-function name

[Function] pattern-expand-1

pattern-expand-1 pattern

[Function] pattern-expand

pattern-expand pattern

[Function] pattern-expand-all

pattern-expand-all pattern

[Function] parse-pattern

parse-pattern pattern

[Function] parse-constructor-pattern

parse-constructor-pattern name &rest args

[Function] unparse-pattern

unparse-pattern pattern

[Package] optima

[Macro] match

match arg &body clauses

Matches ARG with CLAUSES. CLAUSES is a list of the form of (PATTERN . BODY) where PATTERN is a pattern specifier and BODY is an implicit progn. If ARG matches some PATTERN, match then evaluates the corresponding BODY and returns the evaluated value. If no pattern matches, then returns NIL.

Evaluating a form (FAIL) in the clause body causes the latest pattern matching to fail. For example,

(match 1
  (x (if (eql x 1)
         (fail)
         x))
  (_ 'ok))

returns OK, because the form (FAIL) in the first clause is evaluated.

If BODY starts with the symbols WHEN or UNLESS, then the next form will be used to introduce (FAIL). That is,

(match list ((list x) when (oddp x) x))
(match list ((list x) unless (evenp x) x))

will be translated to

(match list ((list x) (if (oddp x) x (fail))))
(match list ((list x) (if (evenp x) (fail) x)))

Examples:

(match 1 (1 1))
=> 1
(match 1 (2 2))
=> 2
(match 1 (x x))
=> 1
(match (list 1 2 3)
  (list x y z) (+ x y z))
=> 6

[Macro] multiple-value-match

multiple-value-match values-form &body clauses

Matches the multiple values of VALUES-FORM with CLAUSES. Unlike MATCH, CLAUSES have to have the form of (PATTERNS . BODY), where PATTERNS is a list of patterns. The number of values that will be used to match is determined by the maximum arity of PATTERNS among CLAUSES.

Examples:

(multiple-value-match (values 1 2)
 ((2) 1)
 ((1 y) y))
=> 2

[Macro] ematch

ematch arg &body clauses

Same as MATCH, except MATCH-ERROR will be raised if not matched.

[Macro] multiple-value-ematch

multiple-value-ematch values-form &body clauses

Same as MULTIPLE-VALUE-MATCH, except MATCH-ERROR will be raised if not matched.

[Macro] cmatch

cmatch arg &body clauses

Same as MATCH, except a continuable MATCH-ERROR will be raised if none of the clauses match.

[Macro] multiple-value-cmatch

multiple-value-cmatch values-form &body clauses

Same as MULTIPLE-VALUE-MATCH, except a continuable MATCH-ERROR will be raised if none of the clauses match.

[Macro] fail

fail

Causes the latest pattern matching to fail. After this failure, matching continues at the next pattern.

[Class] match-error

[Type] match-error

match-error

[Function] match-error-values

match-error-values condition

[Function] match-error-patterns

match-error-patterns condition

[Macro] defpattern

defpattern name lambda-list &body body

Defines a derived pattern specifier named NAME. This is analogous to DEFTYPE.

Examples:

;; Defines a LIST pattern.
(defpattern list (&rest args)
  (when args
    `(cons ,(car args) (list ,@(cdr args)))))

[Package] optima.extra

[Pattern] alist

Syntax:

(alist (KEY . PATTERN)*)

Expansion:

(alist (k . p)*) => (and (assoc k p)*)

Examples:

(match '((1 . :one) (2 . :two) (3 . :three))
  ((alist (1 . x) (3 . y)) (list x y)))
=> (:ONE :THREE)

[Pattern] plist

Syntax:

(plist {KEY PATTERN}*)

Expansion:

(plist {k p}*) => (and (property k p)*)

Examples:

(match '(:name "John" :age 23)
  ((plist :name "John" :age age) age))
=> 23

[Macro] if-match

if-match pattern arg &body (then &optional else)

Equivalent to (match ARG (PATTERN THEN) (otherwise ELSE)).

[Macro] when-match

when-match pattern arg &body body

Equivalent to (match ARG (PATTERN BODY...)).

[Macro] unless-match

unless-match pattern arg &body body

Equivalent to (match ARG (PATTERN) (otherwise BODY...)).

[Macro] let-match

let-match bindings &body body

Similar to LET, except not only a variable but also a pattern can be used in BINDINGS.

[Macro] let-match*

let-match* bindings &body body

Similar to LET-MATCH but matches sequentially.

[Macro] let-match1

let-match1 pattern arg &body body

Equivalent to (let-match ((PATTERN ARG)) BODY...).

[Macro] lambda-match

lambda-match &body clauses

Equivalent to (lambda (arg) (match arg CLAUSES...)).

[Macro] lambda-ematch

lambda-ematch &body clauses

Equivalent to (lambda (arg) (ematch arg CLAUSES...)).

[Macro] lambda-cmatch

lambda-cmatch &body clauses

Equivalent to (lambda (arg) (cmatch arg CLAUSES...)).

[Macro] lambda-match1

lambda-match1 pattern &body body

Equivalent to (lambda-match (PATTERN BODY...)).

[Macro] lambda-ematch1

lambda-ematch1 pattern &body body

Equivalent to (lambda-ematch (PATTERN BODY...)).

[Macro] lambda-cmatch1

lambda-cmatch1 pattern &body body

Equivalent to (lambda-cmatch (PATTERN BODY...)).

Authors

  • Tomohiro Matsuyama

License

LLGPL

optima.ppcre - CL-PPCRE support for optima

[Package] optima.ppcre

[Pattern] ppcre

Syntax:

(ppcre REGEXP PATTERN*)

Matches REGEXP against the target string. Sub-PATTERNs will be used to match the matched groups, if the REGEXP matched.

Examples:

(match "2012-11-04"
  ((ppcre "^(\\d{4})-(\\d{2})-(\\d{2})$" year month day)
   (list year month day)))
=> ("2012" "11" "04")

Authors

  • Tomohiro Matsuyama

License

LLGPL

optima's People

Contributors

fare avatar guicho271828 avatar jasom avatar m2ym avatar malisper avatar naryl avatar rpgoldman avatar scymtym 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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

optima's Issues

String/vector/list patterns

Erlang has some fairly fancy matching on lists and binaries that is very useful when parsing.

For example:

%% Header is bound to the file header contents of a zip file, the initial match being the marker.
<<16#04034b50:32/little, Header/binary>> = ZipHeader.

%% Just a plain match
Foo = <<"hello">>,
<<"__", Foo/binary, "__">> = <<"__hello__">>.

There are also similar constructs for working with lists:

Foo = "hello",
"__" ++ Foo ++ "__" = "__hello__".

I'm not sure what the best translation for these would be. I guess the most important part of all this is that it is able to match subsequences. Perhaps a 'subseq' or 'concatenate' matcher is the way to go, where you could

(let ((foo "foo"))
  (match "__foo__"
    ((concatenate "__" foo "__") 'matched!)))

Not sure what the name of something like this should be.

Getting rid of anaphora

Can we get rid of anaphora? It's widely considered poor taste, it's not well maintained, and it's only used three times, in places where the already imported alexandria:when-let does the job. I have a patch that does the job...

A combination of list-pattern and guard-pattern causes a problem

;; A
(match '(0)
  ((list x) x))
;=> 0

;; expanded code of A
; (LET ((#:FORM5213 '(0)))
;   (IF (CONSP #:FORM5213)
;       (LET ((#:G5215 (CAR #:FORM5213)) (#:G5216 (CDR #:FORM5213)))
;         (DECLARE (IGNORABLE #:G5215 #:G5216))
;         (IF (OPTIMA::EQUALS #:G5216 NIL) (LET ((X #:G5215)) X) NIL))
;       NIL))

;; B
(match '(0)
  ((list (and x (when (numberp x)))) x))
;=> NIL

;; expanded code of B
; (LET ((#:FORM5197 '(0)))
;   (IF (CONSP #:FORM5197)
;       (LET ((#:G5199 (CAR #:FORM5197)) (#:G5200 (CDR #:FORM5197)))
;         (DECLARE (IGNORABLE #:G5199 #:G5200))
;         (IF (OPTIMA::EQUALS #:G5199 NIL)
;             (LET ((X #:G5199)) (IF (NUMBERP X) X NIL))
;             NIL))
;       NIL))

It seems that B returns an unexpected result.

Unused lexical variable THEN

In compile-[ce]?match-values:

(defun compile-match-values (values-form clauses else)
  (let* ((arity (loop for (patterns . then) in clauses
                      maximize (length patterns)))
         (vars (make-gensym-list arity "VAR")))
    `(multiple-value-bind ,vars ,values-form
       ,(compile-match vars clauses else))))

the variable then is not used.

For suppressing warnings, how about the following code?

(defun compile-match-values (values-form clauses else)
  (let* ((arity (loop for (patterns . nil) in clauses
                      maximize (length patterns)))
         (vars (make-gensym-list arity "VAR")))
    `(multiple-value-bind ,vars ,values-form
       ,(compile-match vars clauses else))))

It uses nil instead of then. (cf. CLHS: 6.1.1.7 Destructuring)

smatch

How about setf'able match?

[ce]match causes a compile error with multiple clauses

(5pm:ematch '(0 1 2)
  ((list 0 1 2) :a)
  ((list 3 4 5) :b))
;>> Error: While compiling an anonymous function :
;   Illegally quoted form (QUOTE ((LIST 0 1 2)) ((LIST 3 4 5))).
;      [Condition of type CCL::COMPILE-TIME-PROGRAM-ERROR]

Add a new rule for detecting a predicate function

Currently, we detect a predicate function by adding -P to the prefix, like PERSON-P for PERSON- prefix. We should also detect the predicate in the same way by adding P instead. This helps to detect the predicate that is generated by DEFSTRUCT.

CASElize

Some implementation optimize CASE with jump table. We can CASElize series of if-then-else so that the form can be optimized.

Quicklisp

Having this in quicklisp would be awesome.

Simplifier

(if test1
    (if test2
        then
        else)
    else)

could be simplified like

(if (and test1 test2)
    then
    else)

Also,

(let ((a var1))
  (let ((b var2))
    body))

could be simplified like

(let ((a var1)
      (b var2))
  body)

These simplification reduce tagbody introductions for else branch. Plus, simplification helps compiler to compile the code more quickly and produce the compact executables.

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.