Adrien
Adrien

Reputation: 489

Common Lisp equivalent to Racket's "module languages"

I would like to create a DSL (domain-specific language) with a set of Common Lisp macros, and restrict parsing of the files written in the DSL. I have no need to define a special syntax, only to limit the expressivity of the DSL so that you can't load a file containing arbitrary commands.

In Racket, this functionality is provided by so-called "module languages", using forms like except-out or all-from-out to define which language bindings are available from within the DSL, see https://docs.racket-lang.org/guide/module-languages.html

You can also perform static checks on the DSL files, to check that they follow your specifications. This is explained in this article by Matthew Flatt: http://queue.acm.org/detail.cfm?id=2068896 (in the sections about "Module Languages" and "Static Checks")

Is there an easy way to obtain a similar functionality in Common Lisp?

Upvotes: 2

Views: 367

Answers (1)

Sylwester
Sylwester

Reputation: 48745

It's called packages. You create a package and define what to import and export.

(defpackage :my-fancy-package                       
  (:use :common-lisp)
  (:export :test))

(in-package :my-fancy-package)
(defun test (x)
 (list x x))

(defpackage :test
  (:use :my-fancy-package))

(in-package :test)

(+ 1 2) ; get undefined function +
(test 1 2)
; ==> (1 2)

It's not as secure as racket since it's meant to keep us from mixing definitions not shield against operations:

(cl:+ 1 2)
; ==> 3

CL don't have all-from-out etc, but you can export with a loop:

(let ((pack (find-package :my-fancy-package)))
  (do-all-symbols (sym pack) 
    (when (eql (symbol-package sym) pack) 
      (export sym))))

About static checks I don't think so. You can have compile time checks in macros and runtime checks in functions.

Upvotes: 3

Related Questions