Runtime evaluation/In an environment: Difference between revisions
Runtime evaluation/In an environment (view source)
Revision as of 13:13, 28 August 2022
, 1 year agosyntax highlighting fixup automation
Thundergnat (talk | contribs) m (syntax highlighting fixup automation) |
|||
Line 22:
<!-- {{does not work with|ELLA ALGOL 68|Any This implementation is a compiler}} -->
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'''.
<
(INT x=a; evaluate(code) ) + (INT x=b; evaluate(code));
print((eval_with_x("2 ** x", 3, 5), new line))</
Output:
<pre>
Line 38:
<br>
Given the above, the task may easily be implemented along these lines:
<syntaxhighlight lang="applescript">
on task_with_x(pgrm, x1, x2)
local rslt1, rslt2
Line 45:
rslt2 - rslt1
end task_with_x
</syntaxhighlight>
Example usage (for legibility purposes, the program is stored into an intermediate variable):
<syntaxhighlight lang="applescript">
set pgrm_with_x to "
on run {x}
Line 54:
task_with_x(pgrm_with_x, 3, 5)
</syntaxhighlight>
The result is 24.0 (a real number).
Line 61:
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.
<
msgbox % second := evalWithX("x + 4", 6)
msgbox % second - first
Line 92:
if fnp := FindFunc(funcName)
numput(&x%newname%, fnp+0, 0, "uint")
}</
=={{header|BBC BASIC}}==
<
one = FN_eval_with_x(expression$, 1.2)
two = FN_eval_with_x(expression$, 3.4)
Line 102:
DEF FN_eval_with_x(expr$, x)
= EVAL(expr$)</
=={{header|Bracmat}}==
<syntaxhighlight lang="text">( ( eval-with-x
= code a b argument
. !arg:((=?code),?a,?b,?argument)
Line 113:
& out$(eval-with-x$((='(.$x^!arg)),3,5,2))
& out$(eval-with-x$((='(.$x^!arg)),12,13,2))
);</
Output:
<pre>16
Line 121:
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.
<
(defn eval-with-x [program a b]
(- (binding [x b] (eval program))
(binding [x a] (eval program))))</
<
=> 65</
Here's another version which avoids the global by compiling a local function with a single argument x (the ~'x is how to avoid automatic namespace qualification of symbols in a syntax quote):
<
(defn eval-with-x [program a b]
(let [func (eval `(fn [~'x] ~program))]
(- (func b) (func a))))
</syntaxhighlight>
<
=> 65</
=={{header|Common Lisp}}==
<
(let ((at-a (eval `(let ((x ',a)) ,program)))
(at-b (eval `(let ((x ',b)) ,program))))
(- at-b at-a)))</
<
=> 1.7182817</
This version ensures that the program is compiled, once, for more efficient execution:
<
(let* ((f (compile nil `(lambda (x) ,program)))
(at-a (funcall f a))
(at-b (funcall f b)))
(- at-b at-a)))</
=={{header|Déjà Vu}}==
<
if <= n 1:
n
Line 168:
!run-blob-in { :fib @fib :x 4 } code
!run-blob-in { :fib @fib :x 6 } code
!. -</
{{out}}
<pre>5</pre>
=={{header|E}}==
<
#for historical reasons which will hopefully be entirely eliminated soon.
def bindX(value) {
Line 187:
def atB := program.eval(bindX(b))
return atB - atA
}</
<
# value: 1.7182818284590455</
=={{header|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)....)
<
(define (eval-with-x prog x)
(eval prog (environment-new (list (list 'x x)))))
Line 207:
x
😖️ error: #|user| : unbound variable : x
</syntaxhighlight>
=={{header|Elena}}==
Line 213:
Using VM console client:
<
import extensions'scripting;
Line 224:
console.printLine(
text,",",arg," = ",program.eval(arg.toReal()));
}</
{{out}}
<pre>
Line 236:
=={{header|Erlang}}==
Functions below are used by [[Dynamic_variable_names#Erlang| dynamic variable names]]. Any changes here needs to be backwards compatible, or [[Dynamic_variable_names#Erlang| dynamic variable names]] must also be changed.
<syntaxhighlight lang="erlang">
-module( runtime_evaluation ).
Line 258:
io:fwrite( "~p~n", [Variable2] ),
io:fwrite( "~p~n", [Variable2 - Variable1] ).
</syntaxhighlight>
{{out}}
Line 270:
=={{header|Factor}}==
Being a stack-based language, there is usually no need to bind data stack objects to a variable name. This is the idiomatic way to do it, with <code>eval</code> referencing what it needs from the data stack:
<
: eval-bi@- ( a b program -- n )
tuck [ ( y -- z ) eval ] 2bi@ - ;</
<
65</
Also note that, since programs are first-class denizens in Factor, the use cases for <code>eval</code> are few. Normally, you would pass in a program as a quotation:
<
<
65</
However, we can adhere to the letter of the task. Although we are using a dynamic variable for x, it exists in a temporary, non-global namespace. As far as I can tell, <code>eval</code> is unaware of surrounding lexical scope.
<
: eval-with-x ( a b program -- n )
tuck
[ [ x ] dip [ ( -- y ) eval ] curry with-variable ] 2bi@ - ;</
<
65
IN: scratchpad x get .
f</
=={{header|Forth}}==
EVALUATE invokes the Forth interpreter on the given string.
<
[char] " parse ( code len )
2dup 2>r evaluate
Line 297:
- . ;
2 3 f-" dup *" \ 5 (3*3 - 2*2)</
This can be used to treat a data stream as code, or to provide a lightweight macro facility when used in an IMMEDIATE word.
<
: [CHAR] ; PARSE POSTPONE SLITERAL POSTPONE EVALUATE
POSTPONE ; IMMEDIATE
Line 313:
DO .\" spam "
LOOP
; ok</
=={{header|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:
<
var x 23
Line 323:
x = 1000
print
+ firstresult (add100)</
This prints 1223.
Line 329:
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.
<
(dict) # create an environment capable of holding dynamic bindings
Line 336:
.x = 1000
print
+ firstresult (add100)</
Dictionaries can hold bindings to dynamic symbols. To minimize the danger of dynamic scope there is no recursive ascent in the binding lookup.
<
var .x 23
(dict)
print .x # fails</
=={{header|Go}}==
<
import (
Line 410:
func (v *intV) Assign(t *eval.Thread, o eval.Value) {
*v = intV(o.(eval.IntValue).Get(t))
}</
Output:
<pre>
Line 419:
The solution:
<
Eval.x(x1, program) - Eval.x(x2, program)
}</
Test Program:
<
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)</
Output:
Line 436:
===Explicit===
The following satisfies the requirements:
<
'CODE V0 V1'=. y
(". CODE [ x=. V1) - (". CODE [ x=. V0)
Line 442:
EvalWithX '^x';0;1
1.71828183</
===Tacit===
However, it is easier via point-free coding:
<
1.71828183</
===Explicit again===
Or, using y as the free variable, instead of x:
<
-~/verb def x"_1 y
)</
Example use:
<
1.71828</
This can be extended to support a user declared argument name:
<
:
-~/m adverb def ('(m)=.y';x)"_1 y
)</
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.]
Line 471:
Example use:
<
1.71828
'Z + 2^Z' 'Z' EvalDiffWithName 2 3
5</
Of course this could be re-defined such that the free variable declaration appears to the left of the expression (<code>'Z' 'Z + 2^Z' Example 2 3</code>). However, J's [[currying]] and precedence rules might make that less convenient to use, if this were ever used in a real program.
Line 490:
* the exception handling is minimal, but if something goes wrong you should get a stack dump and the exception ''might'' be helpful...
<
import java.lang.reflect.Method;
import java.net.URI;
Line 557:
);
}
}</
Example usage - calculating the difference of two squares (i.e. 9 - 2 = 7):
Line 569:
eval uses the environment from the calling function.
<
var x = a;
var atA = eval(expr);
Line 575:
var atB = eval(expr);
return atB - atA;
}</
<
=={{header|Jsish}}==
From Javascript entry.
<
function evalWithX(expr, a, b) {
var x = a;
Line 598:
evalWithX('Math.exp(x)', 1, 0) ==> -1.71828182845905
=!EXPECTEND!=
*/</
{{out}}
Line 607:
{{works with|Julia|0.6}}
<
return quote
x = $a
Line 616:
end
@evalwithx(2 ^ x, 3, 5) # raw expression (AST)</
One can even perform the task without using macros:
<
a = eval(quote let x = $a; return $expr end end)
b = eval(quote let x = $b; return $expr end end)
Line 628:
evalwithx(:(2 ^ x), 3, 5)
evalwithx("2 ^ x", 3, 5)</
=={{header|Kotlin}}==
{{trans|JavaScript}}
When you try to compile the following program, it will appear to the compiler that the local variable 'x' is assigned but never used and warnings will be issued accordingly. You can get rid of these warnings by compiling using the -nowarn flag.
<
fun evalWithX(expr: String, a: Double, b: Double) {
Line 645:
fun main(args: Array<String>) {
println(evalWithX("Math.exp(x)", 0.0, 1.0))
}</
{{out}}
Line 653:
=={{header|Liberty BASIC}}==
<syntaxhighlight lang="lb">
expression$ = "x^2 - 7"
Line 661:
Function EvaluateWithX(expression$, x)
EvaluateWithX = Eval(expression$)
End Function </
=={{header|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)
</syntaxhighlight>
In Lua 5.2 one can use the new <code>load</code> function to evaluate a string as Lua code and specify its environment:
Line 675:
{{works with|Lua|5.2}}
<
f = load("return x", nil, nil, env)
env.x = tonumber(io.read()) -- user enters 2
Line 681:
env.x = tonumber(io.read()) -- user enters 3
b = f()
print(a + b) --> outputs 5</
=={{header|Mathematica}}/{{header|Wolfram Language}}==
<
(10 x /. x -> 3 ) - (10 x /. x -> 2 )
-> 10</
=={{header|MATLAB}} / {{header|Octave}}==
Line 692:
In Octave, undeclared variables are local.
<
x = val1;
a = eval(f);
Line 698:
b = eval(f);
r = b-a;
end</
Usage:
<pre>p = 'x .* 2';
Line 708:
=={{header|Metafont}}==
<
save x,a,b; x := va; a := scantokens s;
x := vb; b := scantokens s; a-b
Line 714:
show(evalit("2x+1", 5, 3));
end</
=={{header|Nim}}==
<
macro eval(s, x: static[string]): untyped =
parseStmt(&"let x={x}\n{s}")
echo(eval("x+1", "3.1"))</
{{out}}
<pre>
Line 730:
=={{header|ooRexx}}==
The ooRexx interpret instruction executes dynamically created ooRexx code in the current variable context.
<syntaxhighlight lang="oorexx">
say evalWithX("x**2", 2)
say evalWithX("x**2", 3.1415926)
Line 739:
-- X now has the value of the second argument
interpret "return" expression
</syntaxhighlight>
Output:
<pre>
Line 747:
=={{header|Oz}}==
<
fun {EvalWithX Program A B}
{Compiler.evalExpression Program env('X':B) _}
Line 754:
end
in
{Show {EvalWithX "{Exp X}" 0.0 1.0}}</
=={{header|PARI/GP}}==
There are many ways of doing this depending on the particular interpretation of the requirements. This code assumes that <var>f</var> is a string representing a GP closure.
<
test("x->print(x);x^2-sin(x)",1,3)</
=={{header|Perl}}==
<
{my $code = shift;
my $x = shift;
Line 770:
return eval($code) - $first;}
print eval_with_x('3 * $x', 5, 10), "\n"; # Prints "15".</
=={{header|Phix}}==
Line 779:
still not escape the eval() context, and still have to be explicitly requested as a
return value, as per the second {"x"} parameter [aka rset] to eval().
<!--<
<span style="color: #008080;">without</span> <span style="color: #008080;">javascript_semantics</span>
<span style="color: #7060A8;">requires</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"1.0.1"</span><span style="color: #0000FF;">)</span>
Line 790:
<span style="color: #0000FF;">?</span><span style="color: #000000;">eval_with_x</span><span style="color: #0000FF;">(</span><span style="color: #008000;">"integer x = power(2,x)"</span><span style="color: #0000FF;">,</span><span style="color: #000000;">3</span><span style="color: #0000FF;">,</span><span style="color: #000000;">5</span><span style="color: #0000FF;">)</span>
<!--</
{{out}}
(As in 2<small><sup>5</sup></small> - 2<small><sup>3</sup></small> === 32 - 8 === 24)
Line 799:
=={{header|PHP}}==
<
function eval_with_x($code, $a, $b) {
$x = $a;
Line 809:
echo eval_with_x('return 3 * $x;', 5, 10), "\n"; # Prints "15".
?></
=={{header|PicoLisp}}==
<
(println
(+
Line 823:
(+
(Function 3)
(Function 4) ) ) ) )</
Output:
<pre>32
Line 830:
=={{header|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:
<
Result: 10
> x * 5;
Line 840:
003: mixed ___HilfeWrapper() { return (([mapping(string:int)](mixed)___hilfe)->x) * 5; ; }
004:
></
___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:
<
program demo = compile_string("string eval(mixed x){ " + payload + "; }");
Line 851:
Result: 50
demo()->eval(20);
Result: 100</
=={{header|Python}}==
<
return eval(code, {'x':b}) - eval(code, {'x':a})
>>> eval_with_x('2 ** x', 3, 5)
24</
A slight change allows the evaluation to take multiple names:
<
return eval(code, kwordargs)
Line 870:
>>> code = '3 * x + y'
>>> eval_with_args(code, x=5, y=2) - eval_with_args(code, x=3, y=1)
7</
=={{header|R}}==
We can set up thing so that the "unbound" variable can be any accepted symbol for variables.
<
env <- new.env() # provide a separate env, so that the choosen
assign(var, a, envir=env) # var name do not collide with symbols inside
Line 888:
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</
=={{header|Racket}}==
Same hack as the on in the CL/Scheme entries:
<syntaxhighlight lang="racket">
#lang racket
(define ns (make-base-namespace))
Line 899:
(define (with v) (eval `(let ([x ',v]) ,code) ns))
(- (with b) (with a)))
</syntaxhighlight>
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
<tt>let</tt>, which is very possible in Racket):
<syntaxhighlight lang="racket">
#lang racket
(define ns (make-base-namespace))
Line 912:
(eval code ns))
(- (with b) (with a)))
</syntaxhighlight>
=={{header|Raku}}==
Line 918:
{{Works with|rakudo|2015-12-22}}
For security, you must explicitly allow use of 'EVAL'.
<syntaxhighlight lang="raku"
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 "105".</
=={{header|REBOL}}==
<
fn: func [x] [do bind prog 'x]
a: fn 2
b: fn 4
subtract b a</
Result:
Line 937:
=={{header|REXX}}==
<
say '──────── enter the 1st expression to be evaluated:'
Line 960:
drop x /*X var. is no longer a global variable*/
exit 0 /*stick a fork in it, we're all done. */</
{{out|output|text= }}
<pre>
Line 976:
=={{header|Ring}}==
<
expression = "return pow(x,2) - 7"
one = evalwithx(expression, 1.2)
Line 984:
func evalwithx expr, x
return eval(expr)
</syntaxhighlight>
Output:
<pre>
Line 992:
=={{header|Ruby}}==
<
binding
end
Line 1,000:
end
puts eval_with_x('2 ** x', 3, 5) # Prints "24"</
The magic here is how the <code>binding</code> method works with the <code>bind_x_to_value(x)</code> method.
Line 1,008:
=={{header|Scala}}==
<
def evalWithX(expr: String, a: Double, b: Double)=
Line 1,015:
println(evalWithX("Math.exp(x)", 0.0, 1.0))
}</
=={{header|Scheme}}==
Almost identical to the [[Common Lisp]] version above.
<
(let ((at-a (eval `(let ((x ',a)) ,prog)))
(at-b (eval `(let ((x ',b)) ,prog))))
(- at-b at-a)))</
=={{header|Sidef}}==
<
var f = eval(code);
x = y;
Line 1,031:
}
say eval_with_x(x: 3, y: 5, code: '2 ** x'); # => 24</
=={{header|Simula}}==
<
CLASS ENV;
Line 1,298:
END.
</syntaxhighlight>
{{out}}
<pre>
Line 1,307:
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().
<
a x = 1
first = triple(x)
x = 3
output = triple(x) - first
end</
Output:
Line 1,319:
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:
<
a x = 1
first = triple(x)
x = 3
output = triple(x) - first
end</
The output is the same.
=={{header|Tcl}}==
<
set x $a
set 1st [expr $func]
Line 1,337:
}
puts [eval_twice {2 ** $x} 3 5] ;# ==> 24</
Here's another take, similar to other answers. It passes a code block to be <code>eval</code>ed, not just an expression for <code>expr</code>
<
expr {[set x $val2; eval $code] - [set x $val1; eval $code]}
}
eval_with_x {expr {2**$x}} 3 5 ;# ==> 24</
In 8.5, <tt>apply</tt> makes environments like this "first class":
{{works with|Tcl|8.5}}
<
proc eval_with {body a b} {
set lambda [list x $body]
Line 1,354:
}
eval_with {expr {2**$x}} 3 5 ;# ==> 24</
=={{header|TI-89 BASIC}}==
<
Func
Local x,eresult1,eresult2
Line 1,369:
■ evalx("ℯ^x", 0., 1)
1.71828</
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.] [[Category:TI-89 BASIC examples needing attention]]
Line 1,376:
The <code>(eval)</code> function returns a pair, where the first element is boolean flag indicating success of running the code, and the second element is a string containing the output of code execution.
<
MainModule: {
Line 1,385:
(to-Int (with x 1 (snd (eval code)))))
))
}</
{{out}}
<pre>
Line 1,397:
In TXR's embedded Lisp dialect, we can implement the same solution as Lisp or Scheme: transform the code fragment by wrapping a <code>let</code> around it which binds a variable, and then evaluating the whole thing:
<
(- (eval ^(let ((x ,x1)) ,code-fragment))
(eval ^(let ((x ,x0)) ,code-fragment))))
(eval-subtract-for-two-values-of-x 1 2) ;; yields -4.67077427047161</
Cutting edge TXR code provides access to the environment manipulation functions, making this possible:
<
(let ((e1 (make-env (list (cons 'x x1)))) ;; create two environments stuffed with binding for x
(e0 (make-env (list (cons 'x x0)))))
Line 1,411:
(eval code-fragment e0))))
(eval-subtract-for-two-values-of-x '(exp x) 1 2)</
Alternatively, empty environments can be made and extended with bindings:
<
(let ((e1 (make-env))
(e0 (make-env)))
Line 1,423:
(eval code-fragment e0))))
(eval-subtract-for-two-values-of-x '(exp x) 1 2)</
Explicit environment manipulation has the disadvantage of being hostile against compiling. (See notes about compilation in the Common Lisp example.)
Line 1,435:
However, our two <code>let</code> constructs carefully save and restore the dynamic environment (and therefore any prior value of <code>x</code>), even in the face of exceptions, and
<
(defun eval-subtract-for-two-values-of-x (code-fragment x1 x0)
Line 1,441:
(let ((x x0)) (eval code-fragment))))
(eval-subtract-for-two-values-of-x '(exp x) 1 2)</
=={{header|UNIX Shell}}==
The backquotes <tt>` ... `</tt> capture the standard output of a subshell. Changes to parameter ''x'' in the subshell will not affect its parent shell.
<
set -- "`x=$2; eval "$1"`" "`x=$3; eval "$1"`"
expr "$2" - "$1"
Line 1,460:
echo $p
' 3 5
# Prints '24'</
=={{header|Wren}}==
Line 1,466:
However, it only appears to work with module level variables.
<
var x
Line 1,477:
Meta.eval("x = x - y")
System.print("Delta x = %(x)")</
{{out}}
Line 1,487:
=={{header|zkl}}==
<
f:=Compiler.Compiler.compileText(text);
f.x = x; // set free var in compiled blob
Line 1,494:
}
const TEXT="var x; x*2"; // variables need to be declared
evalWithX(TEXT,5) - evalWithX(TEXT,3) #--> 4</
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:
<
(klass.__constructor(klass.x=5) - klass.__constructor(klass.x=3)).println();</
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.
{{out}}<pre>4</pre>
|