I'm using python, and I want a function that takes a string containing a mathematical expression of one variable (x) and returns a function that evaluates that expression using lambdas. Syntax should be such:
f = f_of_x("sin(pi*x)/(1+x**2)")
print f(0.5)
0.8
syntax should allow ( ) as well as [ ] and use standard operator precedence. Trig functions should have precedence lower than multiplication and higher than addition. Hence the string 'sin 2x + 1' would be equivalent to sin(2x)+1, though both are valid. This is for evaluating user input of algebraic and trigonometric expressions, so think math syntax not programming syntax. The list of supported functions should be easily extensible and the code should be clear and easy to understand. It's OK not to collapse constant expressions.
The sample function here is incomplete. It takes a nested list representing the expression and generates an appropriate function. While somewhat easy to understand, even this seems ugly for python.
import math
def f_of_x(op):
if (isinstance((op[0]), (int, long, float, complex)) ):
return (lambda x:op[0])
elif op[0]=="pi": return lambda x: 3.14159265358979
elif op[0]=="e": return lambda x: 2.718281828459
elif op[0]=="x": return lambda x: x
elif op[0]=="sin": return lambda x: math.sin(f_of_x(op[1])(x))
elif op[0]=="cos": return lambda x: math.cos(f_of_x(op[1])(x))
elif op[0]=="tan": return lambda x: math.tan(f_of_x(op[1])(x))
elif op[0]=="sqrt": return lambda x: math.sqrt(f_of_x(op[1])(x))
elif op[0]=="+": return lambda x: (f_of_x(op[1])(x))+(f_of_x(op[2])(x))
elif op[0]=="-": return lambda x: (f_of_x(op[1])(x))-(f_of_x(op[2])(x))
elif op[0]=="*": return lambda x: (f_of_x(op[1])(x))*(f_of_x(op[2])(x))
elif op[0]=="/": return lambda x: (f_of_x(op[1])(x))/(f_of_x(op[2])(x))
elif op[0]=="**": return lambda x: (f_of_x(op[1])(x))**(f_of_x(op[2])(x))
# should never get here with well formed input
return
def test():
# test function f(x) = sin(pi*x)/(1+x**2)
s = ['/',['sin',['*',['pi'],['x']]],['+',[1],['**',['x'],[2]]]]
f = f_of_x(s)
for x in range(30):
print " "*int(f(x*0.2)*30+10)+"x"
As a general guideline, think of your solution as a tutorial on lambdas and parsers - not code golf. The sample code is just that, so write what you feel is clearest.