etc. In my book this is clearly useful, and its only scratching the surface. ( {} is actually List[] in Mathematica FullForm ... )
The point of symbolic representation is to represent the intended meaning. Its nothing about the "internal" implementation. Using symbols and simple tree structures to compactly express stuff is extremely powerful, and not coincidentally the essential way that human language works.
Sure, with a sufficiently dynamic language you can implement such functionality. The problem with Lisp is that by default symbols want to evaluate, and if you want to treat them symbolically you have to operate in a "special" mode. This makes things too complicated. There is a reason you don't see meaning represented by structure in pretty much any other language besides Mathematica.
Take is a really terrible example, even python has take built into the syntax (Take[lst, 2] -> lst[0:2]). But Mathematica does have nice pattern matching which few lisps have:
SolvePoly[a_*x+b_=0] := { -b/a }
SolvePoly[a_*x^2+b_*x+c_=0] := \
{ (-b + sqrt(b^2-4*a*c))/2a, (-b - sqrt(b^2-4*a*c))/2a }
SolvePoly[_] := "I only took high school algebra"
Of course, in principle one could write a pattern matching macro in lisp, and I imagine there are already some halfway implementations of it. That's pretty much just Turing Equivalence.
The point was not lst[0:2] in Python. See the definition of Take in Mathematica - it is quite a bit more capable.
You need also differentiate between 'pattern matching' and 'rewrite system'. Pattern matching is just taking a pattern, some data and see if it matches.
(match '(+ (* ?a x) ?b) '(+ (* 123.0 x) z)) -> T
Routines like the above are found in many books about Lisp and have been provided in Lisp libraries for decades.
Specifying rewrite rules with patterns for mathematical purposes (simplification, integration, differentiation, ...) is also almost as old as Lisp. Norvig's book 'Paradigm's of AI Programming' explains how it is implemented in Lisp. These things are at the heart of several computer algebra systems written in Lisp - like Macsyma.
how would one define SolvePoly or even Take for that matter in terms of Mathematica if it were not "built in"? I am not saying it is impossible (I really do not know and thus I am curious).
Same way you would do it in lisp - you'd build a function to do pattern matching and use conditionals to test which pattern is matched.
(defun solve-poly (p)
(if (match '(+ (* ?a x) ?b) poly))
(-b/a where b, a come from (extract-values-from-pattern-match poly))
(some code for second order)
))
(Some code borrowed from lispm's comment. Not sure which library the match function comes from.)
What is ' other than a special mode? The fact is that symbols are treated more systematically in Mathematica, and that makes it easier to assemble and dissemble symbolic structures of all sorts.
Sounds like a case of blub. You look at Mathematica and see some weird stuff that is probably equivalent in power to multimethods or whatever, I look at Lisp and think how can I possibly live without civilized pattern matching.
As far as Lisp-based AI goes, its in fact very easy to miss it, but this is probably not the thread to get into Lisp's cultural issues.
Symbols are not treated more systematically in Mathematica.
QUOTE is a special operator in Lisp that causes the evaluator to return its argument unevaluated.
(quote a) -> a
(quote (+ 1 2)) -> (+ 1 2)
(quote "abc") -> "abc"
Mathematica has a different strategy for computation, one that is based on rewrite rules. Expressions are rewritten until they can't no longer be rewritten.
In Lisp evaluation
(+ a a)
gives an error if the variable A has no value.
In Mathematica it would be reduced to
(* 2 a) ; in Lisp syntax
if A has no value.
But that has little to do with the processing capabilities of Lisp. A function like Take can be written very natural in Lisp - there is NO special mode needed. The function takes data and computes results.
You may want to get out of your Mathematica blub and learn some Lisp.
Writing the 'Take' function is a good exercise. Stuff like that are basic exercises in Lisp courses.
> The problem with Lisp is that by default symbols want to evaluate, and if you want to treat them symbolically you have to operate in a "special" mode.
So you're saying that variable bindings should be lazy? That if a symbol is not bound to a value, it should be treated as an unevaluated symbol?
I'm not quite certain what your point is. The actual functionality of Take can be easily replicated in most languages, and indeed, most languages have a version of Take called "slice".
But if your example is meant to demonstrate why lazy symbol evaluation is good, then I'm afraid it fails on that point too. There doesn't seem to be anything in your example that is particularly noteworthy.
Could you perhaps explain your point in more detail?
Clojure and Scheme have take and drop, though the semantics are slightly different from those of Mathematica. They can be written in almost any language.
My point is that putting "structure assumptions in argument lists", though not a good idea 100% of the time, is often extremely useful, as illustrated by the example.
The greater point is that if this is so, one might as well deal in a model of computation that is a natural fit for that way of thinking.
I've been doing a lot of work in Scala and Actionscript. How I wish they had that family of functions in full generality. Why are they missing from most languages? Because that is not how people think in them.
Wow, Lisp has Take. I wrote one. It took me a few minutes:
CL-USER 58 > (take '(a b c d) 2)
(A B)
CL-USER 59 > (take '(a b c d) -2)
(C D)
CL-USER 60 > (take '(a b c d) '(0 3))
(A B C)
CL-USER 61 > (take '(a b c d) '(0 -1 2))
(A C)
CL-USER 62 > (take '((a b c d) (1 2 3 4) (5 6 7 8)) 2 2)
((A B) (1 2))
Take[{a,b,c,d},2] --> {a,b}
Take[{a,b,c,d},-2] -> {c,d}
Take[{a,b,c,d},{1,3}] -> {a,b,c}
Take[{a,b,c,d},{1,-1,2}] -> {a,c}
Take[{{a,b,c,d},{1,2,3,4},{5,6,7,8}},2,2] -> {{a, b}, {1, 2}}
etc. In my book this is clearly useful, and its only scratching the surface. ( {} is actually List[] in Mathematica FullForm ... )
The point of symbolic representation is to represent the intended meaning. Its nothing about the "internal" implementation. Using symbols and simple tree structures to compactly express stuff is extremely powerful, and not coincidentally the essential way that human language works.
Sure, with a sufficiently dynamic language you can implement such functionality. The problem with Lisp is that by default symbols want to evaluate, and if you want to treat them symbolically you have to operate in a "special" mode. This makes things too complicated. There is a reason you don't see meaning represented by structure in pretty much any other language besides Mathematica.