6 ms·
Can you include a good description of reading macros? I'm still looking for good explanation with examples of their power.
by avmich 10y ago
Can you include a good description of reading macros? I'm still looking for good explanation with examples of their power.
- xenophonf 10y agoDo you mean reader macros? Those are used to implement new kinds of syntax within Common Lisp's parser, the READ function. Even standard parts of Common Lisp syntax are defined this way, such as quote (') or backquote (`). For more examples, see http://lisper.in/reader-macros/ http://lisper.in/reader-macros/.
- aidenn0 10y agoActually the entirety of Common Lisp's parser except for numbers, symbols, and the consing dot are implemented as read macros.
- junke 10y agoA reader macro is not a kind of macros [0]. It is a way to customize the Lisp reader by associating a custom function to an entry in the readtable. So you can say that character '[' will be tied to a custom reader function, which reads from a stream and produces a Lisp object, at readtime. The standard sharpsign[1] character is used to read different kind of structures: complex numbers #C(0 1), structs #S(tree :left nil :right nil), and so on. In particular, you can have sharpsign-dot, which reads a lisp form, evaluates it at read time; the result is the form being read. Also, you can use #1= and #1# to affect parts of your code to reader variables and reuse them in other places. If the PRINT-CIRCLE (there are earmuffs around it, but I can't format it here) variable is set to true, here is a quine: #1=(print '#1#) [0] http://www.lispworks.com/documentation/HyperSpec/Body/26_glo_r.htm#reader_macro http://www.lispworks.com/documentation/HyperSpec/Body/26_glo... [1] http://www.lispworks.com/documentation/HyperSpec/Body/02_dh.htm http://www.lispworks.com/documentation/HyperSpec/Body/02_dh....
- martinflack 10y agoYou probably mean reader macros. Here are a few resources: Hyperspec reference for predefined sharpsign reader macros: http://www.lispworks.com/documentation/HyperSpec/Body/02_dh.htm http://www.lispworks.com/documentation/HyperSpec/Body/02_dh.... A blog post where Vsevolod Dyomkin creates a reader macro to notate list comprehensions to his liking: http://lisp-univ-etc.blogspot.com/2013/01/real-list-comprehensions-in-lisp.html http://lisp-univ-etc.blogspot.com/2013/01/real-list-comprehe... A blog post where Inaimathi mentions using CLSQL reader macros to facilitate reading SQL expressions in code: http://langnostic.blogspot.com/2011/03/clsql-and-nothing-else.html http://langnostic.blogspot.com/2011/03/clsql-and-nothing-els... Let Over Lambda chapter 4 which has various examples: http://letoverlambda.com/index.cl/guest/chap4.html http://letoverlambda.com/index.cl/guest/chap4.html
- xyience 10y agoA diagram helps when you start getting into read/compile time discussions, see slides 13 through 17 of http://www.slideshare.net/adorepump/clojure-an-introduction-for-java-programmers http://www.slideshare.net/adorepump/clojure-an-introduction-... to see how the evaluation model for Clojure (which is similar enough to Lisp) differs from most other languages. One of the many differences between Clojure and Lisp though is that Lisp supports user-defined reader macro definitions, so you can add things like the nice persistent map literal syntax of Clojure to Lisp if you really want to.
- baggers 10y agoI found them useful when I looked at clojure and saw their shorthand syntax for lambdas where #(* % %) is a lambda that takes one argument and squares it. You can get some tidy things that are similar with regular macros but to make it actually equivalent your need to hook into the reader..and that's what reader macros are for. So within the hour I had something that let me write λ(* _ _) The best bit though, is that this isn't some nasty hack. This is supported by the spec, so I can package this up and let other people us it just like any other functionality we care to ship around. That's my favorite thing really, being able to treat approaches to writing code in the same way we treat the functionality we make using code.
- kazinator 10y ago> That's my favorite thing really, being able to treat approaches to writing code in the same way we treat the functionality we make using code. You mean ... programming the programming language? > I can package this up ... Not really; it will clash with someone else's use of λ. Read macros do not "package" particularly well. (Racketlang has a good solution for this: you put a #lang whatever directive at the top of a file and then the rest of the file uses the special syntax associated with that lang name). It's very easy to overestimate the usefulness of read syntax. This feature of Common Lisp is used far less than newcomers might imagine, though there are some famous examples of it. If you randomly sample Lisp code, you are much more likely to find a macro than a read macro. > So within the hour I had something that let me write λ( _ _)* Do you plan to type "lambda" with args enough times to eventually that hour of your life back? Ha. Useful syntax for writing anonymous functions can be had, without relying on read macros at all. cl-op: https://code.google.com/archive/p/cl-op/ https://code.google.com/archive/p/cl-op/ Note how if we take λ(* _ _) and then just move the parenthesis over the Greek symbol, we get (λ * _ _). This saves almost the same amount of typing. If your Lisp recognizes λ as a symbol token, then all you have to do now is write a regular macro. Basically, just get the cl-op package and then set up λ as an alias for op: (defmacro λ (&rest args) `(op ,@args)). In TXR Lisp, I implemented a more powerful op which has numbered arguments, and an escape syntax for inner ops to refer to outer ops. Y combinator with TXR Lisp op: ;; The Y combinator: (defun y (f) [(op @1 @1) (op f (op [@@1 @@1]))]) ;; The Y-combinator-based factorial: (defun fac (f) (do if (zerop @1) 1 (* @1 [f (- @1 1)]))) ;; Test: (format t "~s\n" [[y fac] 4]) Combinators return us to your topic of writing a function which squares its argument. Instead of a condensed lambda notation like (op * _ _) for doing this with syntax, we can have a combinator, like (dup #'). This is nicer in a Lisp-1 language where we can just do (dup ). Dup takes its argument, which is a two-argument function, and returns a one-argument function which calls that function with two copies of the argument: (defun dup (fun) (lambda (arg) (funcall fun arg arg))) (funcall (dup #'*) 2) -> 4 (mapcar (dup #'*) '(1 2 3)) -> (1 4 9)
- jonathankoren 10y agoIt's just a macro. It's pretty much exactly like a #define in C
- junke 10y agoThey only share the name.
- _ph_ 10y agoThis is pretty much wrong. C macros have a simple substitution language. But all Common Lisp macros can run arbitrary common lisp functions to compute the macro expansion. That means, you are not limited to pattern matching, but can write a program - in the same programming language you are using for your application - to compute the expansion. Of course there are simple cases which are just syntax rewrites, but there are also complex cases, like the loop macro. The loop macro allows you to specify looping constructs in an almost natural language.
- sedachv 10y agoRead macros are great because you can use them to turn the Common Lisp parser into a parser for any language you want (no restrictions on the grammar), so you essentially get compilers for free. I wrote a one-pass C preprocessor and parser in just under a thousand lines of code: https://github.com/vsedach/Vacietis/blob/master/compiler/reader.lisp https://github.com/vsedach/Vacietis/blob/master/compiler/rea...