Runtime evaluation/In an environment: Difference between revisions

From Rosetta Code
Content added Content deleted
(→‎{{header|Groovy}}: mark incorrect. Should be easy to fix, but I don't know Groovy syntax so as to add the function & result manipulation)
Line 83: Line 83:


=={{header|Groovy}}==
=={{header|Groovy}}==

{{incorrect|Groovy|While it does appear to evaluate a program with several bindings of ''x'', and as such does illustrate the relevant features of Groovy, it does not evaluate the program exactly twice, does not take the program or the values of ''x'' as parameters, and does not subtract the results of evaluation.}}


This program evaluates the Groovy program solution to the "[[Yuletide Holiday]]" task:
This program evaluates the Groovy program solution to the "[[Yuletide Holiday]]" task:

Revision as of 23:47, 4 May 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>

Groovy

This example is incorrect. Please fix the code and remove this message.

Details: While it does appear to evaluate a program with several bindings of x, and as such does illustrate the relevant features of Groovy, it does not evaluate the program exactly twice, does not take the program or the values of x as parameters, and does not subtract the results of evaluation.

This program evaluates the Groovy program solution to the "Yuletide Holiday" task: <lang groovy> Eval.x(2008..2121, inFormat = new java.text.SimpleDateFormat("yyyy-MM-dd") checkFormat = new java.text.SimpleDateFormat("EEE")

result = [] x.each {

   Date date = inFormat.parse("${it}-12-25")
   if (checkFormat.format(date) == "Sun") result.add it

}

print result ) </lang>

Output:

[2011, 2016, 2022, 2033, 2039, 2044, 2050, 2061, 2067, 2072, 2078, 2089, 2095, 2101, 2107, 2112, 2118]

Metafont

<lang metafont>vardef evalit(expr s, va, vb) = save x,a,b; x := va; a := scantokens s; x := vb; b := scantokens s; a-b enddef;

show(evalit("2x+1", 5, 3)); end</lang>

Octave

In Octave, undeclared variables are local.

<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>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] ;# ==> 24</lang>

Here's another take, similar to other answers. It passes a code block to be evaled, not just an expression for expr <lang tcl>proc eval_with_x {code val1 val2} {

   expr {[set x $val2; eval $code] - [set x $val1; eval $code]}

} eval_with_x {expr {2**$x}} 3 5 ;# ==> 24</lang>