Reputation: 489
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
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