Runtime evaluation/In an environment: Difference between revisions

From Rosetta Code
Content added Content deleted
(→‎{{header|Python}}: alternate implementation using compile & introspection)
(→‎{{header|Python}}: swapped introspection for another way to use more than one variable)
Line 48: Line 48:
=={{header|Python}}==
=={{header|Python}}==


<lang python>code = raw_input('f(x): ')
<lang python>>>> def eval_with_x(code, a, b):
return eval(code, {'x':b}) - eval(code, {'x':a})
x = [input('x[%i]: ' % i) for i in [0,1]]
fx = [eval(code, {"x": xv}) for xv in x]
print "f({x[0]}) = {f0}; f({x[1]}) = {f1}; f({x[1]}) - f({x[0]}) = {ans}".format(
x=x, f0=fx[0], f1=fx[1], ans= fx[1] - fx[0] )</lang>


>>> eval_with_x('2 ** x', 3, 5)
Typical use would be <small>(user input is after the initial colon in a line)</small>:
<lang python>f(x): 2**x
24</lang>
x[0]: 3
x[1]: 5
f(3) = 8; f(5) = 32; f(5) - f(3) = 24</lang>


===Python using introspection===
===Python: for multiple names===
A slight change allows the evaluation to take multiple names:
In Python, one can compile an expression then query the compiled object to find out the names that are used. This second example uses this method:
<lang python>func = compile( raw_input('Enter expression: '),
<lang python>>>> def eval_with_args(code, **kwordargs):
return eval(code, kwordargs)
'compile_error.txt',
'eval' )
# ask for two sets of any names used in the expression
name = [{}, {}]
for n in func.co_names: name[0][n] = input('First value of %s: ' % n)
for n in func.co_names: name[1][n] = input('Second value of %s: ' % n)


>>> code = '2 ** x'
print "\n<Expression at second value set> - <Expression at first> =", \
>>> eval_with_args(code, x=5) - eval_with_args(code, x=3)
eval(func, name[1]) - eval(func, name[0])
24
</lang>
>>> code = '3 * x + y'
A simple use would be:
>>> eval_with_args(code, x=5, y=2) - eval_with_args(code, x=3, y=1)
<lang python>Enter expression: 2**x
7
First value of x: 3
>>> </lang>
Second value of x: 5

<Expression at second value set> - <Expression at first> = 24</lang>
and for an initial expression using multiple variables:
<lang python>Enter expression: 3 * x + y
First value of x: 1
First value of y: 2
Second value of x: 3
Second value of y: 4

<Expression at second value set> - <Expression at first> = 8</lang>


=={{header|Ruby}}==
=={{header|Ruby}}==

Revision as of 07:55, 18 February 2009

Task
Runtime evaluation/In an environment
You are encouraged to solve this task according to the task description, using any language you may know.

Given a program in the language representing a function, evaluate it with the variable x (or another name if that is not valid) bound to a provided value, then evaluate it again with x bound to another provided value, then subtract the result of the first from the second and return or print it.

Preferably, do so in a way which does not involve string manipulation of source code, and is plausibly extensible to a runtime-chosen set of bindings.

For more general examples and language-specific details, see Eval.

Common Lisp

<lang lisp> (defun eval-with-x (program a b)

 (let ((at-a (eval `(let ((x ',a)) ,program)))
       (at-b (eval `(let ((x ',b)) ,program))))
   (- at-b at-a)))

</lang>

<lang lisp> (eval-with-x '(exp x) 0 1) => 1.7182817 </lang>

This version ensures that the program is compiled, once, for more efficient execution:

<lang lisp> (defun eval-with-x (program a b)

 (let* ((f (compile nil `(lambda (x) ,program)))
        (at-a (funcall f a))
        (at-b (funcall f b)))
   (- at-b at-a)))

</lang>

Perl

<lang perl>our $x;

 # Only necessary if "use strict" is in effect or a
 # lexical $x (declared with "my") exists in this scope.

sub eval_with_x

  {my $code = shift;
   local $x = shift;
   my $first = eval $code;
   local $x = shift;
   return eval($code) - $first;}

print eval_with_x('3 * $x', 5, 10), "\n"; # Prints "15\n".</lang>

Note that this is a dynamic, not lexical, binding of $x.

Python

<lang python>>>> def eval_with_x(code, a, b): return eval(code, {'x':b}) - eval(code, {'x':a})

>>> eval_with_x('2 ** x', 3, 5) 24</lang>

Python: for multiple names

A slight change allows the evaluation to take multiple names: <lang python>>>> def eval_with_args(code, **kwordargs): return eval(code, kwordargs)

>>> code = '2 ** x' >>> eval_with_args(code, x=5) - eval_with_args(code, x=3) 24 >>> code = '3 * x + y' >>> eval_with_args(code, x=5, y=2) - eval_with_args(code, x=3, y=1) 7 >>> </lang>

Ruby

<lang ruby>def getBinding(x)

 binding

end

def eval_with_x(code, a, b)

 eval(code, getBinding(b)) - eval(code, getBinding(a))

end

puts eval_with_x('2 ** x', 3, 5) # Prints "24"</lang>

Scheme

Almost identical to the Common Lisp version above. <lang scheme>(define (eval-with-x prog a b)

 (let ((at-a (eval `(let ((x ',a)) ,prog)))
       (at-b (eval `(let ((x ',b)) ,prog))))
   (- at-b at-a)))</lang>