[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