Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to define symbols that will work like ( and ) by symbol macro?

I am trying define symbols a and b in following way

a + 1 1 b
2

I am trying to do this by using define-symbol-macro

(define-symbol-macro a '( )
(define-symbol-macro b ') )

but this way is not working.

like image 252
boucekv Avatar asked Oct 11 '13 13:10

boucekv


People also ask

What is symbol in macro?

Symbol macros are special macros with the *. ems file suffix. They are created when you select the desired elements in the schematic and then select the menu item Edit > Create window macro / symbol macro.


2 Answers

What Lisp does with source code

Common Lisp is an incredibly flexible language, in part because its source code can be easily represented using the same data structures that are used in the language. The most common form of macro expansion transforms the these structures into other structures. These are the kind of macros that you can define with define-symbol-macro, define-compiler-macro, defmacro, and macrolet. Before any of those kind of macroexpansions can be performed, however, the system first needs to read the source from an input stream (typically a file, or an interactive prompt). That's the reader's responsibility. The reader also is capable of executing some special actions when it encounters certain characters, such ( and '. What you're trying to do probably needs to be happening down at the reader level, if you want to have, e.g., (read-from-string "a + 1 1 b") return the list (+ 1 1), which is what you want if you want (eval (read-from-string "a + 1 1 b")) to return 2. That said, you could also define a special custom language (like loop does) where a and b are treated specially.

Use set-macro-character, not define-symbol-macro

This isn't something that you would do using symbol-macros, but rather with macro characters. You can set macro characters using the aptly named set-macro-character. For instance, in the following, I set the macro character for % to be a function that reads a list, using read-delimited-list that should be terminated by ^. (Using the characters a and b here will prove very difficult, because you won't be able to write things like (set-macro-character ...) afterwards; it would be like writing (set-m(cro-ch(r(cter ...), which is not good.)

CL-USER> (set-macro-character #\% (lambda (stream ignore)
                                    (declare (ignore ignore))
                                    (read-delimited-list #\^ stream)))
T
CL-USER> % + 1 1 ^
2

The related set-syntax-from-char

There's a related function that almost does what you want here, set-syntax-from-char. You can use it to make one character behave like another. For instance, you can make % behave like (

CL-USER> (set-syntax-from-char #\% #\()
T
CL-USER> % + 1 1 )
2

However, since the macro character associated with ( isn't looking for a character that has the same syntax as ), but an actual ) character, you can't simply replace ) with ^ in the same way:

CL-USER> (set-syntax-from-char #\^ #\))
T
CL-USER> % + 1 1 ^
; Evaluation aborted on #<SB-INT:SIMPLE-READER-ERROR "unmatched close parenthesis" {1002C66031}>.

set-syntax-from-char is more useful when there's an existing character that, by itself does something that you want to imitate. For instance, if you wanted to make ! an additional quotation character:

CL-USER> (set-syntax-from-char #\! #\')
T
CL-USER> (list !a !(1 2 3))
(A (1 2 3))

or make % be a comment character, like it is in LaTeX:

CL-USER> (set-syntax-from-char #\% #\;)
T
CL-USER> (list 1 2 % 3 4
               5 6)
(1 2 5 6)

But consider why you're doing this at all…

Now, even though you can do all of this, it seems like something that would be utterly surprising to anyone who ran into it. (Perhaps you're entering an obfuscated coding competition? ;)) For the reasons shown above, doing this with commonly used characters such as a and b will also make it very difficult to write any more source code. It's probably a better bet to define an entirely new readtable that does what you want, or even write a new parser. even though (Common) Lisp lets you redefine the language, there are still things that it probably makes sense to leave alone.

like image 100
Joshua Taylor Avatar answered Jan 03 '23 22:01

Joshua Taylor


A symbol-macro is a symbol that stands for another form. Seems like you want to look at reader macros.

  • http://clhs.lisp.se/Body/f_set__1.htm
  • http://dorophone.blogspot.no/2008/03/common-lisp-reader-macros-simple.html

I would second Rainer's comment though, what are you trying to make?

like image 33
Baggers Avatar answered Jan 03 '23 23:01

Baggers