[Ecls-list] Simple Hello word! function
Pascal J. Bourguignon
pjb at informatimago.com
Sun Jul 4 00:24:55 UTC 2010
Louis Höfler <louis.hoefler at gmx.de> writes:
> Hello everyone.
> I wrote a simple (yet unstable and not tested)
> module for apache. It allows execution of
> lisp code like php code.
> You can download it here
> https://sourceforge.net/projects/mod-ecl/
> However. I try to execute this simple function:
> (defun hello-world () (print "Hello world!")) (hello-world)
> But the only thing printed out is
> hello-world
> If I copy paste the same code into ecl
> it also prints out hello-world.
> If I paste
> (defun hello-world () (print "Hello world!"))
> then press return
> then paste (hello-world)
> the string Hello world! is printed out.
> What am I doing wrong?
Expecting that the REPL will evaluate all the sexps you give it in one
chunk.
Or in your case, your very own ecl_eval function.
I find it a little confusing to name functions with the same prefix as
one library you use. What if a new version of that library now
provides its own ecl_eval function?
Perhaps you should first rename that function something like
mod_ecl_eval().
The second problem you have with this function, is that it has no
specification, no comment documenting its behavior.
If you had written:
cl_object ecl_eval(char* code)
/*
Reads ONE expression from the C string code, and evaluates it.
Returns the primary value returned from the evaluation of this
expression.
*/
{
...
}
then perhaps it would be clear why ecl_eval("(defun ...) (...)") just
does the defun and ignores the second expression.
Of course, I know it, and you knew it (since you called it several
times in sequence to evaluate several expressions, as for example, in
ecl_disable_console (which also lacks a documentation string^W
comment). But obviously, you FORGOT it! Why do you think we're
telling you to put documentation comments in your sources!
Now, you could instead define a function to evaluate all the
expressions it can read from a string. For example, you could specify
a function that would:
Read expressions from the strings and evaluates them in sequence,
until an error occurs, or no expression remains. Returns a list of
lists, each sublists containing either:
(T start-pos end-pos expression-read-and-evaluated T result-values)
(T start-pos end-pos expression-read-and-evaluated NIL error-condition)
(NIL start-pos end-pos unreadable-substring NIL error-condition)
The first sublist with NIL in its fifth position will be also the last of the
result.
Such as:
> (eval-from-string "(+ 1 2) (truncate 10 3) (* 3")
((T 0 8 (+ 1 2) T (3))
(T 8 24 (TRUNCATE 10 3) T (3 1))
(NIL 24 28 "(* 3" NIL #<a END-OF-FILE>))
Then you could take out the returned list and report results or
errors.
(defun eval-from-string (string)
"
Reads expressions from the strings and evaluates them in sequence,
until an error occurs, or no expression remains. Returns a list of
lists, each sublists containing either:
(T start-pos end-pos expression-read-and-evaluated T result-values)
(T start-pos end-pos expression-read-and-evaluated NIL error-condition)
(NIL start-pos end-pos unreadable-substring NIL error-condition)
The first sublist with NIL in its fifth position will be also the last of the
result.
"
(loop
:with result = '()
:with slength = (length string)
:with start = 0
:for current = start
:while (< start slength)
:do (multiple-value-bind (form end)
(handler-case
(read-from-string string t nil :start current)
(t (err)
(push (list nil current slength (subseq string current) nil err) result)
(return-from eval-from-string (nreverse result))))
(setf start end)
(handler-case
(push (list t current end form t (multiple-value-list (eval form))) result)
(t (err)
(push (list t current end form nil err) result)
(return-from eval-from-string (nreverse result)))))
:finally (return-from eval-from-string (nreverse result))))
--
__Pascal Bourguignon__ http://www.informatimago.com/
More information about the ecl-devel
mailing list