Runtime evaluation/In an environment: Difference between revisions
(→{{header|Octave}}: ++ metafont) |
(clarify task: mention not using a global variable, avoid the 'provided code is a function' interpretation) |
||
Line 1: | Line 1: | ||
{{task}} Given a program in the language |
{{task}} Given a program in the language with a free variable named <var>x</var> (or another name if that is not valid syntax), evaluate it with <var>x</var> bound to a provided value, then evaluate it again with <var>x</var> 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: |
|||
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. |
|||
* does not involve string manipulation of source code |
|||
* is plausibly extensible to a runtime-chosen set of bindings rather than just <var>x</var> |
|||
* does not make <var>x</var> a ''global'' variable |
|||
or note that these are impossible. |
|||
For more general examples and language-specific details, see [[Eval]]. |
For more general examples and language-specific details, see [[Eval]]. |
||
Line 79: | Line 83: | ||
=={{header|Metafont}}== |
=={{header|Metafont}}== |
||
{{incorrect|Metafont|Either do not use a global variable, or note that this is impossible.}} |
|||
<lang metafont>string p; |
<lang metafont>string p; |
||
p := "2x + 1"; |
p := "2x + 1"; |
||
Line 89: | Line 96: | ||
=={{header|Octave}}== |
=={{header|Octave}}== |
||
{{incorrect|Octave|Either do not use a global variable, or note that this is impossible.}} |
|||
<lang octave>p = "x .* 2"; |
<lang octave>p = "x .* 2"; |
||
Line 112: | Line 121: | ||
=={{header|PHP}}== |
=={{header|PHP}}== |
||
{{incorrect|PHP|Either do not use a global variable, or note that this is impossible.}} |
|||
<lang php><?php |
<lang php><?php |
||
Line 166: | Line 177: | ||
=={{header|Tcl}}== |
=={{header|Tcl}}== |
||
{{incorrect|Tcl|The code provided should not itself be a function, but have x as a free variable.}} |
|||
<lang tcl>package require Tcl 8.5 |
<lang tcl>package require Tcl 8.5 |
||
Revision as of 23:14, 29 April 2009
You are encouraged to solve this task according to the task description, using any language you may know.
Given a program in the language 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 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)
- 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>string p; p := "2x + 1"; x := 5; a := scantokens p; message decimal a; % 11 x := 2; b := scantokens p; message decimal b; % 5</lang>
Octave
<lang octave>p = "x .* 2"; x = [1:3]; a = eval(p); x = [4:6]; b = eval(p); disp(b-a);</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 1st [apply $func $a] set 2nd [apply $func $b] expr {$2nd - $1st}
}
eval_twice {x {expr {2 ** $x}}} 3 5 ;# ==> 24</lang>