A giant difference between eval in most languages versus lisp, is that eval in lisp doesn't just take in a string. Sounds somewhat subtle, but it can lead to some dramatic differences. And is, in at least a small part, why lisp people claim code is data. (I had a fun time exploring this a long time ago in https://taeric.github.io/CodeAsData.html)
Many practical applications of eval() boil down to accessing (and perhaps manipulating) scopes in a manner which the host language does not normally allow. Likewise, many potential dangers or pitfalls of eval() relate to how it allows (or does not allow) dynamically-assembled code to inherit access to some spatial or temporal scope of variables, definitions, "unsafe" libraries, and so forth. The interaction of eval() with scope is much a much more interesting design question than whether it accepts an AST, a string, or something in-between, except to the extent that non-stringy "programs" represent some form of reified closure.
I mean, you aren't wrong. But, little bobby tables is essentially what happens when you build up eval statements using a string, no?
if and only if a piece of eval'd code has the ability to produce harmful (let alone observable) side effects, which in a functional language will in turn largely be a consequence of what is imported into the code's scope.
Strictly, this isn't true, either? If you can influence what is returned from the evaluation, that may be enough to cause bugs, no? Without needing any access to scope or side effects. Consider a case where you use sql injection style modification to change an authz query so that it returns indicating the current user has admin rights. (Notably without making any external change in doing this.)
Granted, I fully cede that your point is largely right. Just feels like you are a bit too strong with the "if and only if" on it.
Lisp was supposed to ingest M-expressions and convert them internally. Eval would have been more like other languages had that plan not been abandoned. It is not meaningfully different for languages that construct an AST from a string before evaluation.
I'm not sure I follow? Presuming that the M-expressions were also made of atoms, they would still be meaningfully different than taking in the string of text. Closer to the same, agreed, but still not the same.
IIRC M-expressions broke homoiconicity, so you couldn't just spit sexps at eval and expect anything sensible. I believe that's a lot of the reason they never got implemented.
I'm still not sure I understand. It isn't like you can just throw sexps at an eval and expect something sensible, either? As a sibling was showing, calling eval on (1 2 3) will probably not be anything useful.
Seems that what makes strings terrible is that they don't really encode any other structure, already. Contrast this with atoms and lists, which do encode a bit of structure. It isn't just a string of characters, it is a list of atoms and lists. Structure is already part of the thing. It does not have to be parsed out.
If m-expressions would break that, I think I can see your point. But I'm confused on what would be the point of m-expressions, if they are largely just to remove structure from the content.
M-expressions were intended to be easier for humans to read and write. They weren't meant to be structured. They never got implemented because sexps aren't hard to work with and homoiconicity was an unexpected bonus.
Calling eval on (1 2 3) gives you exactly what you asked for. It's just probably not what you wanted. The problem isn't with eval, but with the idea that (eval (1 2 3)) or (eval '(1 2 3)) is what you want to do. You probably want (eval ''(1 2 3)) - two single quotes. That'll give you a list containing the first three positive integers.
The examples on the wiki page still have structure in the expressions. Though, I grant it is tough to see what was intended there?
From the name, though, I would expect that they would still be fully developed expressions. Just as I would not think you would say the string "(1 2 3)" is the same as the list `(1 2 3)`. Specifically, the structure of it being a list of items there is a vital part of the s-expression.
I don't understand the point on calling eval on the list `(1 2 3)`. My point is you can still have a syntax error, even if you pass it a structured list. Nothing more. To that end, it is not valid code. This does assume "is code" meant "is valid code." But, that feels a safe assumption?
For fun, if you don't allow a distinction between the list `(1 2 3)` and the string "(1 2 3)", then you can also flat out eval "(1 2 3)" without error. But that kind of gets to my core point, that the string and the list are different things.
is (1 2 3) code or data?
I don't understand the question? In particular, it feels out of place? The common claim is that code is data. This does not necessarily imply that data is code.
That said, amusingly, `(1 2 3)` can easily be considered code if you are able to evaluate permutation notation. No?
It depends on the dialect. If we consider Common Lisp, it's a piece of data that doesn't constitute a valid form; it is calling 1 as a function. Some Lisp dialects off the mainstream path handle it. One that comes to mind is PicoLisp which admits (1 2 3) as an expression producing (1 2 3) (that object itself, essentially "auto-quoted", I think).
Yes.
To be specific, it is data. It can also be code when placed in a context where code is expected (for example in the REPL).
If taken as code and evaluated it will probably raise some kind of exception (saying that '1' isn't a function). Saying that it isn't code because it raises an exception would be an interesting take, considering something like...
...would also raise an exception (something about wanting a number and getting a string) when evaluated, yet I doubt many people would argue that it isn't code.Data can also be taken literally, as is the case when macros get involved. We do that every time we define a function, for example:
In this case the argument x is passed through a list which doesn't get evaluated as code.And of course you can have conditional evaluating of data as code, which still makes it code even though it doesn't necessarily get evaluated:
...which will only evaluate the literal list (1 2 3) when the may-error function is passed a boolean false value.the whole point of the "code is data" mantra is that it is both - the list `(1 2 3)` and the lisp code that evaluates to said list when parsed and interpreted.
wouldn't the data version be '(1 2 3) ? sorry I am just trying to understand
Usually yes. To distinguish between lists and function calls. However if we are to pass code literals to eval, we need to quote them:
You're basically asking if literals are code. I imagine you'll get varied opinions about that.
(And yes, that can be used unquoted in a few different contexts in Lisp, such as a special form or macro, or if you've managed to convince the reader that 1 is a function.)