Runtime evaluation/In an environment: Difference between revisions

From Rosetta Code
Content added Content deleted
(→‎{{header|Tcl}}: this imitates other examples (right?))
m (→‎{{header|Octave}}: modified to resemble to other examples)
Line 95: Line 95:
=={{header|Octave}}==
=={{header|Octave}}==


<lang octave>function r = calcit(f, val)
<lang octave>function r = calcit(f, val1, val2)
x = val;
x = val1;
r = eval(f);
a = eval(f);
x = val2;
b = eval(f);
r = b-a;
endfunction
endfunction


p = "x .* 2";
p = "x .* 2";
a = calcit(p, [1:3]);
disp(calcit(p, [1:3], [4:6]));</lang>
b = calcit(p, [4:6]);

disp(b-a);</lang>


Output:
Output:

Revision as of 10:45, 30 April 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 (as a string or AST) with a free variable named x (or another name if that is not valid syntax), evaluate it with x 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.

Do so in a way which:

  • does not involve string manipulation of the input source code
  • is plausibly extensible to a runtime-chosen set of bindings rather than just x
  • does not make x a global variable

or note that these are impossible.

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>

E

<lang e># Constructing an environment has to be done by way of evaluation for historical reasons which will hopefully be entirely eliminated soon. def bindX(value) {

 def [resolver, env] := e`
   def x                      # bind x and capture its resolver and the resulting environment
 `.evalToPair(safeScope)
 resolver.resolve(value)      # set the value
 return env

}

def evalWithX(program, a, b) {

 def atA := program.eval(bindX(a))
 def atB := program.eval(bindX(b))
 return atB - atA

}</lang>

<lang e>? evalWithX(e`(x :float64).exp()`, 0, 1)

  1. value: 1.7182818284590455</lang>

Forth

EVALUATE invokes the Forth interpreter on the given string. <lang forth>

f-" ( a b snippet" -- )
 [char] " parse   ( code len )
 2dup 2>r evaluate
 swap 2r> evaluate
 - . ;

2 3 f-" dup *" \ 5 (3*3 - 2*2) </lang> This can be used to treat a data stream as code, or to provide a lightweight macro facility when used in an IMMEDIATE word. <lang forth>

:macro ( "name <char> ccc<char>" -- )
 : [CHAR] ; PARSE  POSTPONE SLITERAL  POSTPONE EVALUATE
 POSTPONE ; IMMEDIATE
macro times 0 do ;
test 8 times ." spam " loop ;

see test

test
 8 0 
 DO     .\" spam " 
 LOOP
 ; ok

</lang>

Metafont

<lang metafont>vardef evalit(expr s, v) = save x; x := v; scantokens s enddef;

a := evalit("2x+1", 5); b := evalit("2x+1", 2); show (a-b); end</lang>

Octave

<lang octave>function r = calcit(f, val1, val2)

 x = val1;
 a = eval(f);
 x = val2;
 b = eval(f);
 r = b-a;

endfunction

p = "x .* 2"; disp(calcit(p, [1:3], [4:6]));</lang>

Output:

6   6   6

Perl

<lang perl>sub eval_with_x

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

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

PHP

<lang php><?php function eval_with_x($code, $a, $b) {

   $x = $a;
   $first = eval($code);
   $x = $b;
   $second = eval($code);
   return $second - $first;

}

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

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>

Tcl

<lang tcl>package require Tcl 8.5

proc eval_twice {func a b} {

   set x $a
   set 1st [expr $func];
   set x $b
   set 2nd [expr $func];
   expr {$2nd - $1st}

}

puts [eval_twice {2 ** $x} 3 5];</lang>