On the other hand, isn't one lesson from modern computing that treating data as code is really dangerous? I have yet to see this addressed by Lisp advocates.
On the other hand, isn't one lesson from modern computing that treating data as code is really dangerous? I have yet to see this addressed by Lisp advocates.
1. Python, Perl, Ruby, and even Java have support for code as data. If this makes Lisp a risky language, then you should be very worried about all of the above.
2. It is easier to disable code-as-data primitives (eval for example) than it is to add them to a language that lacks such support. I use Lisp for code that is not public-facing; the ability to extend the program at runtime can be very useful when security is not an issue. Languages that lack support for such things are harder to work with for cases like mine.
3. Code-as-data in Lisp is primarily a compile time feature, not a run time feature. Most Lisp programmers are using this feature via the macro system, rather than having programs that compute new functionality based on their inputs. You can disable all runtime support for treating code as data, and still take advantage of it at compile time.
Maintainability? If done right "code is data" could improve the maintainability, or decrease it drastically, just like any other feature. If you have 80 lines of comments for every 10 lines of code, you've decreased your maintainability, comments are dangerous by that logic.
Maybe the power of Lisp's data-as-code is worth the risk. We don't stop using string concatenation because of SQL injection. It's just that I've never even read so much as a warning about this feature, and I'm curious what Lisp users have to say about it.
eval("dangerous python code here")
As I pointed out, it is a problem in any language that has eval. The way you deal with it, is you never eval anything untrusted, which is actually extremely easy to do. I don't believe I've ever used eval ever.In CL specifically, because the reader can evaluate code as well, every time you use the read function, you should know these two things: 1) never use it for user input. 2) bind read-eval to nil. You'll be fine, or more accurately, no worse than anybody else :)
On the other hand macros, and having a json style serialization format that is much more powerful and actually extensible is a big plus :)
(defun read-data ()
(let ((data (let ((*read-eval* 'nil)) (read))))
(mapcar
(lambda (x) (format 't "~a: ~a~%" (car x) (cdr x)))
data)))
Then I can (read-data)
(("a" . 1) ("b" . 2) ("c" . (funcall (lambda () (princ "I ran code!")))))
And the following will print. a: 1
b: 2
c: (FUNCALL (LAMBDA () (PRINC I ran code!)))
But of course unless I eval the code, arbitrary code will not run (assuming I haven't forgotten some aspect of the reader)....have you really looked? Here is a warning, in the section titled, "Reader Security:"
To be fair, no. I'm not a practicing Lisp programmer; I just admire the language. But I've read a fair number of Lisp tutorials, as well as SICP, and I don't recall it being mentioned. I'm glad it's out there somewhere!
The power of "code is/as data" means that Lisp macros can manipulate code as easily as other Lisp code manipulates data. It's not really about eval.
That seems to be the consensus among all the people replying to me. :-) Fair enough. The difference I see is that lots of Lisp authors praise "no syntax" and code-as-data, so it seems to be encouraged, whereas I don't see Python programmers encouraging use of eval. Lisp seems designed for this kind of meta-programming. And it's really cool! It just makes me nervous.
As an outsider, I really appreciate the responses from you all. Basically you seem to be saying, "It's not an issue. We use it for macros, not for untrusted inputs. Don't call eval and you're fine." Obviously I wouldn't want you to do anything else. :-)
Anyway, thanks for the replies. It's great to have a community where I can ask Lisp users about something like this and learn what they think! It's something I've wondered about for a long time.
Allowing code to be treated as data is a very powerful thing when it comes to programming. But of course, with more power there is more danger.