I love Racket's #;. I want to see it in every language that I ever use again. Can it be added to other Lisps via their macro systems? Or does the commenting character break the macro system's ability to read the code?
A sufficient answer will demonstrate a macro being built in any Lisp other than Racket that allows for a change in the commenting system. You need not actually implement Racket's #;, but I would like it if you do. Lisps with the least similarity to Racket, e.g. Clojure or any non-Scheme will be particularity nice to see.
#; isn't a macro, it's what Common lisp would call a readmacro: what it does is defined at read time, not later than that. Read macros which aim to completely suppress input are mildly perilous because there needs to be a way of saying 'read the following thing, but ignore it', and that's only possible if any other readmacros behave well: there's nothing to stop someone defining a readmacro which produces some side-effect even if reading is suppressed.
However, well-behaved readmacros (which includes all of the standard ones and the rest of the standard reader) in CL won't do that: they'll listen to whether reading is being suppressed, and behave accordingly.
CL allows you to do this as standard by using its conditionalisation on features, and in particular #+(or) <expr> will always skip <expr>.
But you can define your own: #; is not predefined so you can define it:
(set-dispatch-macro-character
#\# #\;
(lambda (stream char n)
(declare (ignore char))
(let ((*read-suppress* t))
(dotimes (i (or n 1) (values))
(read stream)))))
After this, or at least with a better tested version of this, then #; <expr> (or obviously #;<expr>) will read as whitespace, and #2; ... ... will skip two following expressions:
> (let ((x #;1 #2; 2 3 4)) x)
4
What you are looking for is #+(or) reader macro.
Since (or) evaluates to nil, the condition is always false the following form is never evaluated.
Related
I'm trying to create a new language in Racket where statements are on separate lines. A newline defines the end of a statement and the start of a new one.
I read through the Create Languages chapter of the guide which was very useful but the examples were focused on extending s-exp-like languages. The only option I see is manually writing my own parser for read and read-syntax.
I was hoping to use readtables but I don't know if I can. I tried:
(make-readtable #f #f 'non-terminating-macro my-read-line-fn)
but I don't know if this is much help. I guess I could create a sub-readtable that does things like read-word, read-string which I dispatch to based on what character my-read-line-fn gets.
Is that the best strategy or is there a predefined way of reading until the end of line?
I don't think you need to do anything with the readtable. Your lang/reader.rkt can provide your own read-syntax that can read/parse however it wants, and presumably stop when it encounters EOL.
One interesting example is Brainfudge. Its concept of a "statement" is a single character, but IIUC also [ brackets ].
See its lang/reader.rkt and parser.rkt for the low-level bits, and then try to understand how that is ultimately evaluated as Racket expressions.
You do indeed need to write version of read and read-syntax that parse your language. The readtable is only meant to modify the builtin read, so I suggest that you take a look at Parser Tools (http://docs.racket-lang.org/parser-tools/index.html), which is tool for writing parsers in the lex/yacc style.
An alternative is to use ragg:
http://www.hashcollision.org/ragg/
Install Ragg using the package manager in DrRacket. Search for ragg in the list of available packages.
Make your own reader.rkt:
#lang s-exp syntax/module-reader
(test test)
#:read-syntax my-read-syntax
#:read my-read
;; override default read (won't be used but is required)
(define (my-read in) (read-line in))
;; override read-syntax by reading in one string at a time and
;; pass it to statement-string->code to get code as dara and
;; make it syntax with datum->syntax
(define (my-read-syntax in)
(datum->syntax #f (statement-string->code (read-line in))))
;; This is actually how you want your code
;; to become s-expressions. I imagine that my
;; module has a primitive called code that
;; interprets the string as is
(define (statement-string->code str)
(list 'code str))
Racket doesn't have "statements", so the concept of newlines ending "statements" is nonsensical.
If your motivation is to reduce or do away with parentheses, I encourage you to use a "standard alternative" reader like sweet-expressions, rather than making something home-grown.
I'm writing an emacs major mode for a programming environment which supports two slightly different programming languages. Both are lisps (one is Scheme), so both use s-expressions. The two languages are differentiated by their function definition keyword: scheme uses define, while the other language (which is called xtlang) uses bind-func
So, in the same buffer, I have
(define foo ; this is scheme
(lambda (a)
(+ scheme-fn a))
(bind-func bar ; this is xtlang
(lambda (b)
(* xtlang-fn b))
I've got the font-locking working, using something like
(font-lock-add-keywords nil
'(("(\\(define\\)\\>"
(1 font-lock-keyword-face))
("(\\(bind-func\\)\\>"
(1 font-lock-keyword-face))
("\\<scheme-fn\\>"
(0 font-lock-function-name-face))
("\\<xtlang-fn\\>"
(0 font-lock-function-name-face))
))
What I'd like to be able to do is to be able to colour the parens differently based on the language (scheme/xtlang).
So, colour all the parens in the form red if the top-level defun is a define, and blue if it's a bind-func, while still highlighting all the keywords/functions within the forms as normal.
This may require multi-line font locking, since the define/bind-func will probably be on a previous line to the keywords to be highlighted. This thread suggests that font-lock-multiline in conjunction with match-anchored in font-lock-keywords may be the answer, but then goes on to suggest that font-lock-multiline should only be used in situations where the multi-line aspect is the exception rather than the rule.
My other option seems to be to use syntax-propertize, but I'm a bit confused about how that works - the documentation is a bit sparse.
The easiest way to handle this is utilizing the following fact:
MATCHER can be either the regexp to search for, or the function name
to call to make the search (called with one argument, the limit of the
search;
In other words, you could replace regexps like "\\<scheme-fn\\>" with a function that repeatedly search for the regexp using re-search-forward, and return if a match is found in the correct context.
For a concrete example of a package that use this technique, look at cwarn-mode, which is part of the standard Emacs distribution.
I have a question concerning evaluation of lists in lisp.
Why is (a) and (+ a 1) not evaluated,
(defun test (a) (+ a 1))
just like (print 4) is not evaluated here
(if (< 1 2) (print 3) (print 4))
but (print (+ 2 3)) is evaluated here
(test (print (+ 2 3)))
Does it have something to do with them being standard library functions? Is it possible for me to define functions like that in my lisp program?
As you probably know, Lisp compound forms are generally processed from the outside in. You must look at the symbol in the first position of the outermost nesting to understand a form. That symbol completely determines the meaning of the form. The following expressions all contain (b c) with completely different meaning; therefore, we cannot understand them by analyzing the (b c) part first:
;; Common Lisp: define a class A derived from B and C
(defclass a (b c) ())
;; Common Lisp: define a function of two arguments
(defun a (b c) ())
;; add A to the result of calling function B on variable C:
(+ a (b c))
Traditionally, Lisp dialects have divided forms into operator forms and function call forms. An operator form has a completely arbitrary meaning, determined by the piece of code which compiles or interprets that functions (e.g. the evaluation simply recurses over all of the function call's argument forms, and the resulting values are passed to the function).
From the early history, Lisp has allowed users to write their own operators. There existed two approaches to this: interpretive operators (historically known as fexprs) and compiling operators known as macros. Both hinge around the idea of a function which receives the unevaluated form as an argument, so that it can implement a custom strategy, thereby extending the evaluation model with new behaviors.
A fexpr type operator is simply handed the form at run-time, along with an environment object with which it can look up the values of variables and such. That operator then walks the form and implements the behavior.
A macro operator is handed the form at macro-expansion time (which usually happens when top-level forms are read, just before they are evaluated or compiled). Its job is not to interpret the form's behavior, but instead to translate it by generating code. I.e. a macro is a mini compiler. (Generated code can contain more macro calls; the macro expander will take care of that, ensuring that all macro calls are decimated.)
The fexpr approach fell out of favor, most likely because it is inefficient. It basically makes compilation impossible, whereas Lisp hackers valued compilation. (Lisp was already a compiled language from as early as circa 1960.) The fexpr approach is also hostile toward lexical environments; it requires the fexpr, which is a function, to be able to peer into the variable binding environment of the form in which its invoked, which is a kind of encapsulation violation that is not allowed by lexical scopes.
Macro writing is slightly more difficult, and in some ways less flexible than fexprs, but support for macro writing improved in Lisp through the 1960's into the 70's to make it close to as easy as possible. Macro originally had receive the whole form and then have to parse it themselves. The macro-defining system developed into something that provides macro functions with arguments that receive the broken-down syntax in easily digestible pieces, including some nested aspects of the syntax. The backquote syntax for writing code templates was also developed, making it much easier to express code generation.
So to answer your question, how can I write forms like that myself? For instance if:
;; Imitation of old-fashioned technique: receive the whole form,
;; extract parts from it and return the translation.
;; Common Lisp defmacro supports this via the &whole keyword
;; in macro lambda lists which lets us have access to the whole form.
;;
;; (Because we are using defmacro, we need to declare arguments "an co &optional al",
;; to make this a three argument macro with an optional third argument, but
;; we don't use those arguments. In ancient lisps, they would not appear:
;; a macro would be a one-argument function, and would have to check the number
;; of arguments itself, to flag bad syntax like (my-if 42) or (my-if).)
;;
(defmacro my-if (&whole if-form an co &optional al)
(let ((antecedent (second if-form)) ;; extract pieces ourselves
(consequent (third if-form)) ;; from whole (my-if ...) form
(alternative (fourth if-form)))
(list 'cond (list antecedent consequent) (list t alternative))))
;; "Modern" version. Use the parsed arguments, and also take advantage of
;; backquote syntax to write the COND with a syntax that looks like the code.
(defmacro my-if (antecedent consequent &optional alternative)
`(cond (,antecedent ,consequent) (t ,alternative))))
This is a fitting example because originally Lisp only had cond. There was no if in McCarthy's Lisp. That "syntactic sugar" was invented later, probably as a macro expanding to cond, just like my-if above.
if and defun are macros. Macros expand a form into a longer piece of code. At expansion time, none of the macro's arguments are evaluated.
When you try to write a function, but struggle because you need to implement a custom evaluation strategy, its a strong signal that you should be writing a macro instead.
Disclaimer: Depending on what kind of lisp you are using, if and defun might technically be called "special forms" and not macros, but the concept of delayed evaluation still applies.
Lisp consists of a model of evaluation of forms. Different Lisp dialects have different rules for those.
Let's look at Common Lisp.
data evaluates to itself
a function form is evaluated by calling the function on the evaluated arguments
special forms are evaluated according to rules defined for each special operator. The Common Lisp standard lists all of those, defines what they do in an informal way and there is no way to define new special operators by the user.
macros forms are transformed, the result is evaluated
How IF, DEFUN etc. works and what they evaluated, when it is doen and what is not evaluated is defined in the Common Lisp standard.
I've heard that Lisp's macro system is very powerful. However, I find it difficult to find some practical examples of what they can be used for; things that would be difficult to achieve without them.
Can anyone give some examples?
Source code transformations. All kinds. Examples:
New control flow statements: You need a WHILE statement? Your language doesn't have one? Why wait for the benevolent dictator to maybe add one next year. Write it yourself. In five minutes.
Shorter code: You need twenty class declarations that almost look identical - only a limited amount of places are different. Write a macro form that takes the differences as parameter and generates the source code for you. Want to change it later? Change the macro in one place.
Replacements in the source tree: You want to add code into the source tree? A variable really should be a function call? Wrap a macro around the code that 'walks' the source and changes the places where it finds the variable.
Postfix syntax: You want to write your code in postfix form? Use a macro that rewrites the code to the normal form (prefix in Lisp).
Compile-time effects: You need to run some code in the compiler environment to inform the development environment about definitions? Macros can generate code that runs at compile time.
Code simplifications/optimizations at compile-time: You want to simplify some code at compile time? Use a macro that does the simplification - that way you can shift work from runtime to compile time, based on the source forms.
Code generation from descriptions/configurations: You need to write a complex mix of classes. For example your window has a class, subpanes have classes, there are space constraints between panes, you have a command loop, a menu and a whole bunch of other things. Write a macro that captures the description of your window and its components and creates the classes and the commands that drive the application - from the description.
Syntax improvements: Some language syntax looks not very convenient? Write a macro that makes it more convenient for you, the application writer.
Domain specific languages: You need a language that is nearer to the domain of your application? Create the necessary language forms with a bunch of macros.
Meta-linguistic abstraction
The basic idea: everything that is on the linguistic level (new forms, new syntax, form transformations, simplification, IDE support, ...) can now be programmed by the developer piece by piece - no separate macro processing stage.
Pick any "code generation tool". Read their examples. That's what it can do.
Except you don't need to use a different programming language, put any macro-expansion code where the macro is used, run a separate command to build, or have extra text files sitting on your hard disk that are only of value to your compiler.
For example, I believe reading the Cog example should be enough to make any Lisp programmer cry.
Anything you'd normally want to have done in a pre-processor?
One macro I wrote, is for defining state-machines for driving game objects. It's easier to read the code (using the macro) than it is to read the generated code:
(def-ai ray-ai
(ground
(let* ((o (object))
(r (range o)))
(loop for p in *players*
if (line-of-sight-p o p r)
do (progn
(setf (target o) p)
(transit seek)))))
(seek
(let* ((o (object))
(target (target o))
(r (range o))
(losp (line-of-sight-p o target r)))
(when losp
(let ((dir (find-direction o target)))
(setf (movement o) (object-speed o dir))))
(unless losp
(transit ground)))))
Than it is to read:
(progn
(defclass ray-ai (ai) nil (:default-initargs :current 'ground))
(defmethod gen-act ((ai ray-ai) (state (eql 'ground)))
(macrolet ((transit (state)
(list 'setf (list 'current 'ai) (list 'quote state))))
(flet ((object ()
(object ai)))
(let* ((o (object)) (r (range o)))
(loop for p in *players*
if (line-of-sight-p o p r)
do (progn (setf (target o) p) (transit seek)))))))
(defmethod gen-act ((ai ray-ai) (state (eql 'seek)))
(macrolet ((transit (state)
(list 'setf (list 'current 'ai) (list 'quote state))))
(flet ((object ()
(object ai)))
(let* ((o (object))
(target (target o))
(r (range o))
(losp (line-of-sight-p o target r)))
(when losp
(let ((dir (find-direction o target)))
(setf (movement o) (object-speed o dir))))
(unless losp (transit ground)))))))
By encapsulating the whole state-machine generation in a macro, I can also ensure that I only refer to defined states and warn if that is not the case.
With macros you can define your own syntax, thus you extend Lisp and make it
suited for the programs you write.
Check out the, very good, online book Practical Common Lisp, for practical examples.
7. Macros: Standard Control Constructs
8. Macros: Defining Your Own
Besides extending the language's syntax to allow you to express yourself more clearly, it also gives you control over evaluation. Try writing your own if in your language of choice so that you can actually write my_if something my_then print "success" my_else print "failure" and not have both print statements get evaluated. In any strict language without a sufficiently powerful macro system, this is impossible. No Common Lisp programmers would find the task too challenging, though. Ditto for for-loops, foreach loops, etc. You can't express these things in C because they require special evaluation semantics (people actually tried to introduce foreach into Objective-C, but it didn't work well), but they are almost trivial in Common Lisp because of its macros.
R, the standard statistics programming language, has macros (R manual, chapter 6). You can use this to implement the function lm(), which analyzes data based on a model that you specify as code.
Here's how it works: lm(Y ~ aX + b, data) will try to find a and b parameters that best fit your data. The cool part is, you can substitute any linear equation for aX + b and it will still work. It's a brilliant feature to make statistics computation easier, and it only works so elegantly because lm() can analyze the equation it's given, which is exactly what Lisp macros do.
Just a guess -- Domain Specific Languages.
Macros are essential in providing access to language features. For instance, in TXR Lisp, I have a single function called sys:capture-cont for capturing a delimited continuation. But this is awkward to use by itself. So there are macros wrapped around it, such as suspend, or obtain and yield which provide alternative models for resumable, suspended execution. They are implemented here.
Another example is the complex macro defstruct which provides syntax for defining a structure type. It compiles its arguments into lambda-s and other material which is passed to the function make-struct-type. If programs used make-struct-type directly for defining OOP structures, they would be ugly:
1> (macroexpand '(defstruct foo bar x y (z 9) (:init (self) (setf self.x 42))))
(sys:make-struct-type 'foo 'bar '()
'(x y z) ()
(lambda (#:g0101)
(let ((#:g0102 (struct-type #:g0101)))
(unless (static-slot-p #:g0102 'z)
(slotset #:g0101 'z
9)))
(let ((self #:g0101))
(setf (qref self x)
42)))
())
Yikes! There is a lot going on that has to be right. For instance, we don't just stick a 9 into slot z because (due to inheritance) we could actually be the base structure of a derived structure, and in the derived structure, z could be a static slot (shared by instances). We would be clobbering the value set up for z in the derived class.
In ANSI Common Lisp, a nice example of a macro is loop, which provides an entire sub-language for parallel iteration. A single loop invocation can express an entire complicated algorithm.
Macros let us think independently about the syntax we would like in a language feature, and the underlying functions or special operators required to implement it. Whatever choices we make in these two, macros will bridge them for us. I don't have to worry that make-struct is ugly to use, so I can focus on the technical aspects; I know that the macro can look the same regardless of how I make various trade-offs. I made the design decision that all struct initialization is going to be done by some functions registered to the type. Okay, that means that my macro has to take all the initializations in the slot-defining syntax, and compile the anonymous functions, where the slot initialization is done by code generated in the bodies.
Macros are compilers for bits of syntax, for which functions and special operators are the target language.
Sometimes people (non-Lisp people, usually) criticize macros in this way: macros don't add any capabilities, only syntactic sugar.
Firstly, syntactic sugar is a capability.
Secondly, you also have to consider macros from a "total hacker perspective": combining macros with implementation-level work. If I'm adding features to a Lisp dialect, such as structures or continuations, I am actually extending the power. The involvement of macros in that enterprise is essential. Even though macros aren't the source of the new power (it doesn't emanate from the macros themselves), they help tame and harness it, giving it expression.
If you don't have sys:capture-cont, you can't just hack up its behavior with a suspend macro. But if you don't have macros, then you have to do something awfully inconvenient to provide access to a new feature that isn't a library function, namely hard-coding some new phrase structure rules into a parser.
I've been working through Practical Common Lisp and as an exercise decided to write a macro to determine if a number is a multiple of another number:
(defmacro multp (value factor)
`(= (rem ,value ,factor) 0))
so that :
(multp 40 10)
evaluates to true whilst
(multp 40 13)
does not
The question is does this macro leak in some way? Also is this "good" Lisp? Is there already an existing function/macro that I could have used?
Siebel gives an extensive rundown (for simple cases anyway) of possible sources of leaks, and there aren't any of those here. Both value and factor are evaluated only once and in order, and rem doesn't have any side effects.
This is not good Lisp though, because there's no reason to use a macro in this case. A function
(defun multp (value factor)
(zerop (rem value factor)))
is identical for all practical purposes. (Note the use of zerop. I think it makes things clearer in this case, but in cases where you need to highlight, that the value you're testing might still be meaningful if it's something other then zero, (= ... 0) might be better)
Your macro looks fine to me. I don't know what a leaky macro is, but yours is pretty straightforward and doesn't require any gensyms. As far as if this is "good" Lisp, my rule of thumb is to use a macro only when a function won't do, and in this case a function can be used in place of your macro. However, if this solution works for you there's no reason not to use it.
Well, in principle, a user could do this:
(flet ((= (&rest args) nil))
(multp 40 10))
which would evaluate to NIL... except that ANSI CL makes it illegal to rebind most standard symbols, including CL:=, so you're on the safe side in this particular case.
In generial, of course, you should be aware of both referential untransparency (capturing identifiers from the context the macro is expanded in) and macro unhygiene (leaking identifiers to expanded code).
No, no symbol introduced in the macro's "lexical closure" is released to the outside.
Note that leaking isn't NECESSARILY a bad thing, even if accidental leaking almost always is. For one project I worked on, I found that a macro similar to this was useful:
(defmacro ana-and (&rest forms)
(loop for form in (reverse forms)
for completion = form then `(let ((it ,form))
(when it
,completion))
finally (return completion)))
This allowed me to get "short-circuiting" of things needed to be done in sequence, with arguments carried over from previous calls in the sequence (and a failure signalled by returning NIL). The specific context this code is from is for a hand-written parser for a configuration file that has a cobbled-together-enough syntax that writing a proper parser using a parser generator was more work than hand-rolling.