Re: eval() function

new topic     » goto parent     » topic index » view thread      » older message » newer message

Me wrote:

> Alex Chamberlain wrote:
>
>> After my unsuccessful attempt at using OOEU's eval() function,
>> I thought would write my own that will work with the normal rds
>> download.
>> But it won't work!
>>
>> }}}
<eucode>
>> constant EVAL_FILE_NAME = "tmp_evalfile.ex"
>> constant EVAL_ERROR = -1
>>
>> global function eval(sequence data)
>> 	integer tmp_fn, ret
>> 	sequence plat
>>
>> 	tmp_fn = open(EVAL_FILE_NAME, "w")
>> 	if tmp_fn = -1 then
>> 		puts(1, "Could not opne temporary eval file ... Sorry!")
>> 		return EVAL_ERROR
>> 	end if
>>
>> 	puts(tmp_fn, data)
>>
>> 	if platform() = DOS32 then
>> 		plat = "ex"
>> 	elsif platform() = WIN32 then
>> 		plat = "exw"
>> 	elsif (platform() = LINUX) or (platform() = FREEBSD) then
>> 		plat = "exu"
>> 	end if
>> 	puts(1, plat & " " & EVAL_FILE_NAME & " > eval.out")
>> 	ret = system_exec(plat & " " & EVAL_FILE_NAME, 0)
>> 	system("DELE " & EVAL_FILE_NAME, 0)
>> 	return ret
>> end function
>> </eucode>
{{{

>>
>> Can somebody help me?
>
>
> When I try to run that program, I get the following error message:
>    DOS32 has not been declared
>            if platform() = DOS32 then
>                                ^
> So at least you should write at the beginning of the program:
>    include misc.e
>
> Also when you have opened a file, don't forget to close it!
>
> And you have mixed up some things. blink
> Besides the missing 'include' statement, the program can not work,
> because you are redirecting the wrong command, you never read the output
> of the temporary program, and the function returns the wrong value.
> Additionally it looks to me that system_exec() can not be used for
> output redirection. But redirecting the output is not necessary at all
> here.
>
> Make a clear concept, you need 4 steps:
> a) write a temporary program for evaluating the expression and writing
>    the result to another temporary file
> b) run the temporary program (and delete the program file)
> c) read the content of the temporary result file, and convert it to
>    a number (and delete the file)
> d) return this number (do *not* return the return value of
>    system_exec()!)
>
> Now you have important hints. I'll not give you the complete program at
> the moment. Trying yourself is more fun! smile


Here comes the second part of my reply, firstly some more remarks:

It is often useful to write a function like this in a way, so that it is
as versatile as possible, and useful for different types of programs.
Now imagine a program with a nice looking GUI, and then a black console
window pops up with the message:
     "Could not open temporary eval file ... Sorry!"
Since this would look ugly, a versatile library function should not
output such messages itself, but return a specific error code, and let
the main program display the appropriate message (see code below).

Your function returns -1 to indicate an error. But -1 can also be a
valid result of the function, e.g.  eval("-2*0.5") => -1.
When eval() returns -1, how can the main program know whether this
special -1 is a valid result or an error flag? Answer: It cannot!
We must return error flags in a different way. From the top of my head
three possibilities come to my mind:
1) Always return a sequence of 2 elements, where the first element is a
   special flag, and the second element is the desired value, in case
   there is no error.
   This way is used e.g. by the Euphoria functions get() (see below) and
   value().
2) Always return an atom, and use a separate local or global error
   variable, which is set by eval() e.g.
        atom result
        integer error
        result = eval("1+1")
        if error then
           puts(1, "Can't calculate that.\n")
        else
           printf(1, "Result: %g\n", {result})
        end if
   This is not working code, but I hope you'll get the idea.
3) Always return an atom for a valid result, and a sequence in case of
   an error (or vice versa, like gets() does). This method is used in
   the code below.

In your code you used "DELE", I don't know that. On DOS and Windows it
must be "DEL". If "DELE" is not a typo, but a valid Linux/FreeBSD
command, you must change the code of the function, so that it uses the
proper command according to the current platform.

Like you did, I use 2 files. But my files both have the same extension,
so I only need 1 command to delete them.
This command is deliberately commented out currently. After running the
code, you should look at the contents of the file "eval_prg.tmp". Then
you probably will see what's going on. smile

include misc.e
include get.e

constant
   EVAL_PROG_NAME = "eval_prg.tmp",
   EVAL_RES_NAME  = "eval_res.tmp",
   EVAL_WRITE_ERR = {1},
   EVAL_READ_ERR  = {2}


global function eval (sequence expression)
   sequence plat, ret
   integer fn, sys

   -- write a temporary program for evaluating the expression and
   -- writing the result to another temporary file
   fn = open(EVAL_PROG_NAME, "w")
   if fn = -1 then
      return EVAL_WRITE_ERR
   end if
   printf(fn, "integer fn\n"
            & "fn = open(\"%s\", \"w\")\n"
            & "print(fn, %s)\n"
            & "close(fn)\n",
            {EVAL_RES_NAME, expression})
   close(fn)

   -- run the temporary program
   if platform() = DOS32 then
      plat = "ex"
   elsif platform() = WIN32 then
      plat = "exw"
   elsif (platform() = LINUX) or (platform() = FREEBSD) then
      plat = "exu"
   end if
   sys = system_exec(plat & " " & EVAL_PROG_NAME, 0)

   -- read the content of the temporary result file,
   -- and convert it to a number
   fn = open(EVAL_RES_NAME, "r")
   if fn = -1 then
      return EVAL_READ_ERR
   end if
   ret = get(fn)
   close(fn)

   -- delete temporary files
--    system("DEL *.tmp", 0)

   -- return the number from the temporary result file
   if ret[1] = GET_SUCCESS then
      return ret[2]
   else
      return EVAL_READ_ERR
   end if
end function


-- Demo
object result
sequence expression

expression = "3*2.5"
-- expression = "power(4,2)"

result = eval(expression)
if atom(result) then
   printf(1, "%s = %g\n", {expression, result})
elsif equal(result, EVAL_WRITE_ERR) then
   puts(1, "Could not write eval program ... Sorry!")
elsif equal(result, EVAL_READ_ERR) then
   puts(1, "Could not read eval result ... Sorry!")
end if
puts(1, "\nPress Enter to continue ...")
if getc(0) then end if


If you still have questions, just let us know.

Regards,
   Juergen

-- 
Have you read a good program lately?

new topic     » goto parent     » topic index » view thread      » older message » newer message

Search



Quick Links

User menu

Not signed in.

Misc Menu