[C++-sig] Re: [BPL] python::interpreter proposal
Nicodemus
nicodemus at globalite.com.br
Sat Jan 4 00:05:17 CET 2003
Bjorn Pettersen wrote:
>>>I ended up making exec return an int so that we could do:
>>>
>>> int foo(int x) {
>>> static int ok = py::exec(
>>> "def foo(y):\n"
>>> " return y**y\n");
>>> return py::extract<int>(py::fn("foo")(x));
>>> }
>>>
>>>(i.e. only calling exec once).
>>>
>>>
>>You mean exec returning an int to describe success or
>>failure? I would
>>prefer an exception in case of an error, and returning void.
>>
>>
>No, the point was being able to declare the int static so py::exec() was
>only called on the first call to foo() -- and throwing an exception when
>something bad happens. No use wasting cycles re-executing the function
>definition every time... If someone has a more graceful suggestion I'm
>all ears :-)
>
>
I believe that a better aproach would be to separate the foo definition
in a separate function:
void create_foo()
{
static bool created = false;
if (!created) {
py::exec(
"def foo(y):\n"
" return y**y\n" );
created = true;
}
}
int foo(int x)
{
create_foo();
stringstream ss;
ss << "foo(" << x << ")" << endl;
return py::extract<int>(py::eval(ss.str()));
}
And even if there was no other approach, designing the interface of the
interpreter with this specific use in mind would be bad design, in my
opinion.
The ideal, in my opinion, would be something like:
// create_foo is called during initializtion
void create_foo()
{
py::exec(
"def foo(y):\n"
" return y**y\n" );
}
int foo(int x)
{
stringstream ss;
ss << "foo(" << x << ")" << endl;
return py::extract<int>(py::eval(ss.str()));
}
So, I think the only reason to make exec to return an int is to signal
an error, a job that is better handled by exceptions. 8)
>The script would look something like:
>
> x = foo(y)
> x += bar(y)
> x
>
>i.e. the value in x should be returned. We call it as:
>
> py::set("y", cppYObject); // assign our c++ object to variable 'y'
> int result = py::extract<int>(py::block(theCodeAbove));
>
>
I don't know about the real utility of such an approach... you can get
the same effect just by simply executing the code and then later inspect
the globals dictionary for the variable that you want:
{
string code =
"x = foo(y)\n"
"x += bar(y)";
py::exec(code);
int result = py::extract<int>(py::globals["x"]); // py::globals is
an instance of dict
}
So the functions "set" and "block" seems like code bloat to me. I think
we should concentrate in the very basic functionality, and to try to fit
any special case in this basic funcionality. If later the "special case"
proves to be common enough, then it can be incorporated.
Just my 2 cents,
Nicodemus.
More information about the Cplusplus-sig
mailing list