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.)