Runtime evaluation/In an environment: Difference between revisions

From Rosetta Code
Content added Content deleted
(Adds Clojure solution)
(Omit from Lily)
Line 946: Line 946:
{{omit from|Haskell}} <!-- no "eval" in language spec -->
{{omit from|Haskell}} <!-- no "eval" in language spec -->
{{omit from|GUISS|Does not have variables}}
{{omit from|GUISS|Does not have variables}}
{{omit from|Lily}}

Revision as of 22:31, 14 August 2015

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.

See also

ALGOL 68

Works with: ALGOL 68G version Any - tested with release mk15-0.8b.fc9.i386 - this implementation is an interpretor, and evaluate is an extension to the standard

Variable names are generally not visible at run time with classic compilers. However ALGOL 68G is an interpretor and it retains this ability. Note that evaluate returns a string. <lang algol68>PROC eval_with_x = (STRING code, INT a, b)STRING: (INT x=a; evaluate(code) ) + (INT x=b; evaluate(code)); print((eval_with_x("2 ** x", 3, 5), new line))</lang> Output:

         +8        +32

AutoHotkey

Works with: AutoHotkey_H

AutoHotkey does not provide an API to the local symbol table. Local variables are also not supported within scopes outside functions. However, a local environment can be simulated by wrapping code in a temporary function. <lang AutoHotkey>msgbox % first := evalWithX("x + 4", 5) msgbox % second := evalWithX("x + 4", 6) msgbox % second - first return

evalWithX(expression, xvalue) { global script script = (

   expression(){
   x = %xvalue%  ; := would need quotes
   return %expression%
 }

) renameFunction("expression", "")  ; remove any previous expressions gosub load ; cannot use addScript inside a function yet exp := "expression" return %exp%() }

load: DllCall(A_AhkPath "\addScript","Str",script,"Uchar",0,"Cdecl UInt") return

renameFunction(funcName, newname){ static x%newname% := newname  ; store newname in a static variable so its memory is not freed strput(newname, &x%newname%, strlen(newname) + 1) if fnp := FindFunc(funcName)

 numput(&x%newname%, fnp+0, 0, "uint")

}</lang>

BBC BASIC

<lang bbcbasic> expression$ = "x^2 - 7"

     one = FN_eval_with_x(expression$, 1.2)
     two = FN_eval_with_x(expression$, 3.4)
     PRINT two - one
     END
     
     DEF FN_eval_with_x(expr$, x)
     = EVAL(expr$)</lang>

Bracmat

<lang>( ( eval-with-x

 =   code a b argument
   .   !arg:((=?code),?a,?b,?argument)
     &   (!b:?x&!code$!argument)
       + -1*(!a:?x&!code$!argument)
 )

& out$(eval-with-x$((='(.$x^!arg)),3,5,2)) & out$(eval-with-x$((='(.$x^!arg)),12,13,2)) );</lang> Output:

16
25

Clojure

We must define x as global, but we use dynamic bindings. Only functions within the binding will see the newly bound value of x, before it re-establishes the bindings that existed before. <lang clojure>(def ^:dynamic x nil)

(defn eval-with-x [program a b]

 (- (binding [x b] (eval program))
    (binding [x a] (eval program))))</lang>

<lang clojure>(eval-with-x '(* x x) 4 9) => 65</lang>


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>

Déjà Vu

<lang dejavu>local fib n: if <= n 1: n else: + fib - n 1 fib - n 2

local :code !compile-string dup "-- fib x" #one less than the xth fibonacci number

!run-blob-in { :fib @fib :x 4 } code !run-blob-in { :fib @fib :x 6 } code !. -</lang>

Output:
5

E

<lang e># Constructing an environment has to be done by way of evaluation

  1. for historical reasons which will hopefully be entirely eliminated soon.

def bindX(value) {

 def [resolver, env] := e`    # bind x and capture its resolver and the
   def x                      # 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>

EchoLisp

We evaluate prog in a new environment which is an association list ((x x-value)), and could be ((x x-value) (y y-value)....) <lang lisp> (define (eval-with-x prog x)

   (eval prog (environment-new (list (list 'x x)))))

(define prog '( + 1 (* x x)))

(eval-with-x prog 10) → 101 (eval-with-x prog 1000) → 1000001 (- (eval-with-x prog 1000) (eval-with-x prog 10)) → 999900

check x is unbound (no global)

x 😖️ error: #|user| : unbound variable : x </lang>

Erlang

Functions below are used by dynamic variable names. Any changes here needs to be backwards compatible, or dynamic variable names must also be changed. <lang Erlang> -module( runtime_evaluation ).

-export( [evaluate_form/2, form_from_string/1, task/0] ).

evaluate_form( Form, {Variable_name, Value} ) -> Bindings = erl_eval:add_binding( Variable_name, Value, erl_eval:new_bindings() ), {value, Evaluation, _} = erl_eval:expr( Form, Bindings ), Evaluation.

form_from_string( String ) -> {ok, Tokens, _} = erl_scan:string( String ), {ok, [Form]} = erl_parse:parse_exprs( Tokens ), Form.

task() -> Form = form_from_string( "X." ), Variable1 = evaluate_form( Form, {'X', 1} ), io:fwrite( "~p~n", [Variable1] ), Variable2 = evaluate_form( Form, {'X', 2} ), io:fwrite( "~p~n", [Variable2] ), io:fwrite( "~p~n", [Variable2 - Variable1] ). </lang>

Output:
14> runtime_evaluation:task().
1
2
1

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>

Genyris

One way is to use a macro. In genyris, macros are lazy functions which execute twice, the return value is also evaluated in the caller's environment: <lang genyris>defmacro add100() (+ x 100)

var x 23 var firstresult (add100) x = 1000 print

   + firstresult (add100)</lang>

This prints 1223.

Another way is to use dynamically scoped variables. In Genyris, symbols prefixed with a period are looked up in the caller's environment, not the lexical environment of the closure. When a dictionary is the first element of the expression, an environment is created and the &rest is evaluated.

<lang genyris>def add100() (+ .x 100)

(dict) # create an environment capable of holding dynamic bindings

  var .x 23           # create a binding in the dictionary
  var firstresult (add100)
  .x = 1000
  print 
      + firstresult (add100)</lang>

Dictionaries can hold bindings to dynamic symbols. To minimize the danger of dynamic scope there is no recursive ascent in the binding lookup. <lang genyris>(dict)

  var .x 23           
  (dict)
      print .x # fails</lang>

Go

<lang go>package main

import (

   "bitbucket.org/binet/go-eval/pkg/eval"
   "fmt"
   "go/parser"
   "go/token"

)

func main() {

   // an expression on x
   squareExpr := "x*x"
   // parse to abstract syntax tree
   fset := token.NewFileSet()
   squareAst, err := parser.ParseExpr(squareExpr)
   if err != nil {
       fmt.Println(err)
       return
   }
   // create an environment or "world"
   w := eval.NewWorld()
   // allocate a variable
   wVar := new(intV)
   // bind the variable to the name x
   err = w.DefineVar("x", eval.IntType, wVar)
   if err != nil {
       fmt.Println(err)
       return
   }
   // bind the expression AST to the world
   squareCode, err := w.CompileExpr(fset, squareAst)
   if err != nil {
       fmt.Println(err)
       return
   }
   // directly manipulate value of variable within world
   *wVar = 5
   // evaluate
   r0, err := squareCode.Run()
   if err != nil {
       fmt.Println(err)
       return
   }
   // change value
   *wVar--
   // revaluate
   r1, err := squareCode.Run()
   if err != nil {
       fmt.Println(err)
       return
   }
   // print difference
   fmt.Println(r0.(eval.IntValue).Get(nil) - r1.(eval.IntValue).Get(nil))

}

// int value implementation. type intV int64

func (v *intV) String() string { return fmt.Sprint(*v) } func (v *intV) Get(*eval.Thread) int64 { return int64(*v) } func (v *intV) Set(_ *eval.Thread, x int64) { *v = intV(x) } func (v *intV) Assign(t *eval.Thread, o eval.Value) {

   *v = intV(o.(eval.IntValue).Get(t))

}</lang> Output:

9

Groovy

The solution: <lang groovy>def cruncher = { x1, x2, program ->

  Eval.x(x1, program) - Eval.x(x2, program)

}</lang>

Test Program: <lang groovy>def fibonacciProgram = x < 1 ? 0 : x == 1 ? 1 : (2..x).inject([0,1]){i, j -> [i[1], i[0]+i[1]]}[1]

println "F(${10}) - F(${5}) = ${Eval.x(10, fibonacciProgram)} - ${Eval.x(5, fibonacciProgram)} = " + cruncher(10, 5, fibonacciProgram)</lang>

Output:

F(10) - F(5) = 55 - 5 = 50

J

Explicit

The following satisfies the requirements: <lang j> EvalWithX=. monad : 0

   'CODE V0 V1'=. y
   (". CODE [ x=. V1) - (". CODE [ x=. V0)
  )
  
  EvalWithX '^x';0;1

1.71828183</lang>

Tacit

However, it is easier via point-free coding: <lang j> (0&({::) -~&>/@:(128!:2&.>) 1 2&{) '^';0;1 1.71828183</lang>

Explicit again

Or, using y as the free variable, instead of x: <lang J>EvalDiffWithY=: dyad define

  -~/verb def x"_1 y

)</lang>

Example use:

<lang J> '^y' EvalDiffWithY 0 1 1.71828</lang>

This can be extended to support a user declared argument name:

<lang J>EvalDiffWithName=: adverb define

  -~/m adverb def ('(m)=.y';x)"_1 y

)</lang>

This works by preceding the user provided expression with a statement which assigns the argument value to a local variable whose name was provided by the user. [Note that this implementation skirts the requirement that the implementation does not manipulate strings -- instead we manipulate a structure containing strings.]

Example use:

<lang J> '^George' 'George' EvalDiffWithName 0 1 1.71828

  'Z + 2^Z' 'Z' EvalDiffWithName 2 3

5</lang>

Of course this could be re-defined such that the free variable declaration appears to the left of the expression ('Z' 'Z + 2^Z' Example 2 3). However, J's currying and precedence rules might make that less convenient to use, if this were ever used in a real program.

Java

Works with: Java version 6+

Although Java is a compiled static language and expression evaluation is not intrinsic part of Java, we can still generate a class at run time and so emulate evaluation of string expressions. Java 1.6 provides some APIs for this sort of thing.

Issues:

  • this is not thread-safe because it writes a generated class to the file system, then loads it
  • the supplied code to evaluate is assumed to be an expression rather than a series of statements
  • the supplied expression should evaluate to a number
  • the same class is generated twice - never mind
  • it's painfully verbose, but we're bending the language quite a bit
  • the exception handling is minimal, but if something goes wrong you should get a stack dump and the exception might be helpful...

<lang java5>import java.io.File; import java.lang.reflect.Method; import java.net.URI; import java.util.Arrays; import javax.tools.JavaCompiler; import javax.tools.SimpleJavaFileObject; import javax.tools.ToolProvider;

public class Eval {

   private static final String CLASS_NAME = "TempPleaseDeleteMe";
   private static class StringCompiler
           extends SimpleJavaFileObject {
       final String m_sourceCode;
       private StringCompiler( final String sourceCode ) {
           super( URI.create( "string:///" + CLASS_NAME + Kind.SOURCE.extension ), Kind.SOURCE );
           m_sourceCode = sourceCode;
       }
       @Override
       public CharSequence getCharContent( final boolean ignoreEncodingErrors ) {
           return m_sourceCode;
       }
       private boolean compile() {
           final JavaCompiler javac = ToolProvider.getSystemJavaCompiler();
           return javac.getTask( null, javac.getStandardFileManager( null, null, null ),
               null, null, null, Arrays.asList( this )
           ).call();
       }
       private double callEval( final double x )
               throws Exception {
           final Class<?> clarse = Class.forName( CLASS_NAME );
           final Method   eval   = clarse.getMethod( "eval", double.class );
           return ( Double ) eval.invoke( null, x );
       }
   }
   public static double evalWithX( final String code, final double x )
           throws Exception {
       final StringCompiler sc = new StringCompiler(
           "class "
               + CLASS_NAME
               + "{public static double eval(double x){return ("
               + code
               + ");}}"
           );
       if ( ! sc.compile() ) throw new RuntimeException( "Compiler error" );
       return sc.callEval( x );
   }
   public static void main( final String [] args ) 
           throws Exception /* lazy programmer */ {
       final String expression = args [ 0 ];
       final double x1         = Double.parseDouble( args [ 1 ] );
       final double x2         = Double.parseDouble( args [ 2 ] );
       System.out.println(
           evalWithX( expression, x1 )
           - evalWithX( expression, x2 )
       );
   }

}</lang>

Example usage - calculating the difference of two squares (i.e. 9 - 2 = 7):

java Eval "Math.pow(x,2)" 3 1.414213562373095

Output:

7.0

JavaScript

eval uses the environment from the calling function.

<lang javascript>function evalWithX(expr, a, b) {

   var x = a;
   var atA = eval(expr);
   x = b;
   var atB = eval(expr);
   return atB - atA;

}</lang>

<lang javascript>evalWithX('Math.exp(x)', 0, 1) // returns 1.718281828459045</lang>

Liberty BASIC

<lang lb>

expression$ = "x^2 - 7"

Print (EvaluateWithX(expression$, 5) - EvaluateWithX(expression$, 3)) End

Function EvaluateWithX(expression$, x)

   EvaluateWithX = Eval(expression$)

End Function </lang>

Lua

<lang lua> code = loadstring"return x^2" --this doesn't really need to be input, does it? val1 = setfenv(code, {x = io.read() + 0})() val2 = setfenv(code, {x = io.read() + 0})() print(val2 - val1) </lang>

In Lua 5.2 one can use the new load function to evaluate a string as Lua code and specify its environment:

Works with: Lua version 5.2

<lang lua>env = {} f = load("return x", nil, nil, env) env.x = tonumber(io.read()) -- user enters 2 a = f() env.x = tonumber(io.read()) -- user enters 3 b = f() print(a + b) --> outputs 5</lang>

Mathematica

<lang Mathematica>Input source code is "10 x" , X is locally bound to 3 & 2 and the resulting expressions evaluated. (10 x /. x -> 3 ) - (10 x /. x -> 2 ) -> 10</lang>

MATLAB / 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;

end</lang> Usage:

p = 'x .* 2';
disp(calcit(p, [1:3], [4:6]));

Output:

6   6   6

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>

ooRexx

The ooRexx interpret instruction executes dynamically created ooRexx code in the current variable context. <lang ooRexx> say evalWithX("x**2", 2) say evalWithX("x**2", 3.1415926)

routine evalWithX
 use arg expression, x
 -- X now has the value of the second argument
 interpret "return" expression

</lang> Output:

4
9.86960406

Oz

<lang oz>declare

  fun {EvalWithX Program A B}
     {Compiler.evalExpression Program env('X':B) _}
     -
     {Compiler.evalExpression Program env('X':A) _}   
  end

in

  {Show {EvalWithX "{Exp X}" 0.0 1.0}}</lang>

PARI/GP

There are many ways of doing this depending on the particular interpretation of the requirements. This code assumes that f is a string representing a GP closure. <lang parigp>test(f,a,b)=f=eval(f);f(a)-f(b); test("x->print(x);x^2-sin(x)",1,3)</lang>

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>

Perl 6

<lang perl6>sub eval_with_x($code, *@x) { [R-] @x.map: -> \x { eval $code } }

say eval_with_x('3 * x', 5, 10); # Says "15". say eval_with_x('3 * x', 5, 10, 50); # Says "135".</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>

PicoLisp

<lang PicoLisp>(let Expression '(+ X (* X X)) # Local expression

  (println
     (+
        (let X 3
           (eval Expression) )
        (let X 4
           (eval Expression) ) ) )
  (let Function (list '(X) Expression)   # Build a local function
     (println
        (+
           (Function 3)
           (Function 4) ) ) ) )</lang>

Output:

32
32

Pike

Pike can only compile complete classes. therefore binding a value to a variable is only possible by string manipulation. even Pikes own interactive mode which seemingly evaluates expressions wraps them into a class and replaces variable references before compiling: <lang Pike>> int x=10; Result: 10 > x * 5; Result: 50 > dump wrapper Last compiled wrapper: 001: mapping(string:mixed) ___hilfe = ___Hilfe->variables; 002: # 1 003: mixed ___HilfeWrapper() { return (([mapping(string:int)](mixed)___hilfe)->x) * 5; ; } 004: ></lang> ___Hilfe is an object which stores all created variables;

to solve the problem in the task i would create a function that can take arguments: <lang Pike>string payload = "x * 5";

program demo = compile_string("string eval(mixed x){ " + payload + "; }");

demo()->eval(10); Result: 50 demo()->eval(20); Result: 100</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>

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>

R

We can set up thing so that the "unbound" variable can be any accepted symbol for variables. <lang R>evalWithAB <- function(expr, var, a, b) {

 env <- new.env()           # provide a separate env, so that the choosen
 assign(var, a, envir=env)  # var name do not collide with symbols inside
                            # this function (e.g. it could be even "env")
 atA <- eval(parse(text=expr), env)
                            # and then evaluate the expression inside this
                            # ad hoc env-ironment
 assign(var, b, envir=env)
 atB <- eval(parse(text=expr), env)
 return(atB - atA)

}

print(evalWithAB("2*x+1", "x", 5, 3)) print(evalWithAB("2*y+1", "y", 5, 3)) print(evalWithAB("2*y+1", "x", 5, 3)) # error: object "y" not found</lang>

Racket

Same hack as the on in the CL/Scheme entries: <lang Racket>

  1. lang racket

(define ns (make-base-namespace)) (define (eval-with-x code a b)

 (define (with v) (eval `(let ([x ',v]) ,code) ns))
 (- (with b) (with a)))

</lang>

Better: a more direct use of eval with just the code (for example, this won't break if we use a namespace with a different meaning for let, which is very possible in Racket): <lang Racket>

  1. lang racket

(define ns (make-base-namespace)) (define (eval-with-x code a b)

 (define (with v)
   (namespace-set-variable-value! 'x v #f ns)
   (eval code ns))
 (- (with b) (with a)))

</lang>

REBOL

<lang rebol>prog: [x * 2] fn: func [x] [do bind prog 'x] a: fn 2 b: fn 4 subtract b a</lang>

Result:

4

REXX

<lang rexx>/*REXX program to demonstrate some run-time evaulations. */

a=fact(3) b=fact(4) say b-a exit /*stick a fork in it, we're done.*/

/*───────────────────────────────────FACT subroutine────────────────────*/ fact: procedure; parse arg n; !=1; do j=2 to n;  !=!*j; end; return !</lang> output

18

Ruby

<lang ruby>def bind_x_to_value(x)

 binding

end

def eval_with_x(code, a, b)

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

end

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

The magic here is how the binding method works with the bind_x_to_value(x) method. When bind_x_to_value is called, it sets its local variable x to the value passed. The binding method then returns a reference to the current context (or stack frame) to the caller. eval can then use the local variable x in this context.

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>


Sidef

<lang ruby>func eval_with_x(code, x, y) {

   var f = eval(code);
   x = y;
   eval(code) - f;

}

say eval_with_x(x: 3, y: 5, code: '2 ** x'); # => 24</lang>

SNOBOL4

This program defines (at runtime) a function triple(), compiles it, and then executes it twice, with values x = 1 and then x = 3. The program subtracts the returned value from the first call from the value returned from the first call, and prints the result. In this example, the value x is passed as a parameter to the function triple().

<lang SNOBOL4> compiled = code(' define("triple(x)") :(a);triple triple = 3 * x :(return)')  :<compiled> a x = 1

    first = triple(x)
    x = 3
    output = triple(x) - first  

end</lang>

Output:

6

If you specifically wanted to not pass x as a parameter but instead use it as a value from the environment, that's easy too:

<lang SNOBOL4> compiled = code(' define("triple()") :(a);triple triple = 3 * x :(return)')  :<compiled> a x = 1

    first = triple(x)
    x = 3
    output = triple(x) - first  

end</lang>

The output is the same.

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>

In 8.5, apply makes environments like this "first class":

Works with: Tcl version 8.5

<lang tcl>package require Tcl 8.5 proc eval_with {body a b} {

   set lambda [list x $body]
   expr {[apply $lambda $b] - [apply $lambda $a]}

}

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

TXR

Translation of: Common Lisp

In TXR's embedded Lisp dialect, we can implement the same solution as Lisp or Scheme: transform the code fragment by wrapping a let around it which binds a variable, and then evaluating the whole thing:

<lang txr>(defun eval-subtract-for-two-values-of-x (code-fragment x1 x0)

 (- (eval ^(let ((x ,x1)) ,code-fragment))
    (eval ^(let ((x ,x0)) ,code-fragment))))

(eval-subtract-for-two-values-of-x 1 2) ;; yields -4.67077427047161</lang>

Cutting edge TXR code provides access to the environment manipulation functions, making this possible:

<lang txr>(defun eval-subtract-for-two-values-of-x (code-fragment x1 x0)

 (let ((e1 (make-env (list (cons 'x x1))))   ;; create two environments stuffed with binding for x
       (e0 (make-env (list (cons 'x x0)))))
   (- (eval code-fragment e1)                ;; pass these environment to eval
      (eval code-fragment e0))))

(eval-subtract-for-two-values-of-x '(exp x) 1 2)</lang>

Alternatively, empty environments can be made and extended with bindings:

<lang txr>(defun eval-subtract-for-two-values-of-x (code-fragment x1 x0)

 (let ((e1 (make-env))
       (e0 (make-env)))
   (env-vbind e1 'x x1)
   (env-vbind e0 'x x0)
   (- (eval code-fragment e1)
      (eval code-fragment e0))))

(eval-subtract-for-two-values-of-x '(exp x) 1 2)</lang>

Explicit environment manipulation has the disadvantage of being hostile against compiling. (See notes about compilation in the Common Lisp example.)

there is an eval function which takes an environment parameter. However, currently there isn't any access to the manipulation of environment objects. It's probably a bad idea because run time tricks with lexical environments lead to programs that are not compilable.

Lastly, we can also solve this problem using dynamically scoped (a.k.a "special") variables. The problem description specifically says that the solution is not to use global variables. Though we must define the variables as global, we do not use the global bindings; we use dynamic bindings.

There is a hidden global variable, namely the dynamic environment itself. That's how eval is able to resolve the free-variable x occurring in code-fragment without receiving any environment parameter.

However, our two let constructs carefully save and restore the dynamic environment (and therefore any prior value of x), even in the face of exceptions, and

<lang txr>(defvar x)

(defun eval-subtract-for-two-values-of-x (code-fragment x1 x0)

 (- (let ((x x1)) (eval code-fragment))
    (let ((x x0)) (eval code-fragment))))

(eval-subtract-for-two-values-of-x '(exp x) 1 2)</lang>

TI-89 BASIC

<lang ti89b>evalx(prog, a, b) Func

 Local x,eresult1,eresult2
 a→x
 expr(prog)→eresult1
 b→x
 expr(prog)→eresult2
 Return eresult2-eresult1

EndFunc

■ evalx("ℯ^x", 0., 1)

                     1.71828</lang>

There are no facilities for control over the environment; expr() evaluates in the same environment as the caller, including local variables. [Someone please verify this statement.]

UNIX Shell

The backquotes ` ... ` capture the standard output of a subshell. Changes to parameter x in the subshell will not affect its parent shell.

<lang bash>eval_with_x() { set -- "`x=$2; eval "$1"`" "`x=$3; eval "$1"`" expr "$2" - "$1" }

eval_with_x ' # compute 2 ** $x p=1 while test $x -gt 0; do p=`expr $p \* 2` x=`expr $x - 1` done echo $p ' 3 5

  1. Prints '24'</lang>

zkl

<lang zkl>fcn evalWithX(text,x) {

  f:=Compiler.Compiler.compileText(text);
  f.x = x; // set free var in compiled blob
  f.__constructor(); // run blob
  vm.regX   // compiler sets the VMs X register for cases like this

} const TEXT="var x; x*2"; // variables need to be declared evalWithX(TEXT,5) - evalWithX(TEXT,3) #--> 4</lang> This is not a complete solution but close.

Another way to do this is to create a class on the fly that contains the code to be run and reusing that class. The class just acts like as a container for x and a function: <lang zkl>var klass=Compiler.Compiler.compileText("var x; returnClass(x*2)"); (klass.__constructor(klass.x=5) - klass.__constructor(klass.x=3)).println();</lang> returnClass(x) is required in a constructor if you want to return something other than self. klass.x=y pokes y into the instance variable x. Running the constructor runs x*2.

Output:
4