skogsbaer / write-your-python-program

BSD 3-Clause "New" or "Revised" License
1 stars 4 forks source link

Passing own function to library function breaks visualization #161

Open hannesbraun opened 3 days ago

hannesbraun commented 3 days ago

To reproduce this problem set up a directory structure like this:

.
├── app
│   └── example.py
├── libs
│   └── factorial
│       ├── __init__.py
...

example.py:

import factorial

def mul(a, b):
    return a * b

result = factorial.factorial(3, mul)
print(result)

init.py:

def factorial(n, op):
    if n <= 1:
        return 1
    prev = factorial(n - 1, op)
    a = op(n, prev)
    return a

Run the trace generator with something like PYTHONPATH=libs python3 main.py app/example.py and you should get an error.

The question remaining is: how should this situation be visualized?
Option 1: We can skip everything that is executed through the library. In the example, executing factorial.factorial would just be one step.
Option 2: We can somehow visualize the steps again once we reach code that is non-library code. In this latter case, do we omit the stack frames generated by the library and have the visualization "randomly" jump to some non-library code again? Option 3: (Is there another one?)

Option 2 would probably require more effort to realize as we always need to keep track of all the steps that are happening inside of a library to get a correct visualization (even if we don't visualize them). This would very likely also decrease the performance quite a bit.

skogsbaer commented 3 days ago

I think option 1 is good here. The visualization is targeted towards beginners. When teaching advanced features such as higher-order functions, we still can use the debugger.