tusharsadhwani / blog-comments

MIT License
0 stars 0 forks source link

How I added C-style for-loops to Python #8

Open utterances-bot opened 2 years ago

utterances-bot commented 2 years ago

How I added C-style for-loops to Python

Or alternatively: How I made the most cursed Python package of all time.

https://sadh.life/post/cursed-for/

chasrmartin commented 2 years ago

Seems like a lot of work to exactly simulate

for i in range(0,10,1): print(f”{i= }”)

tusharsadhwani commented 2 years ago

@chasrmartin there's some things that range-based for loops simply can't do, like:

for (i = 0; i < 100; i += 1):
    if data[i].startswith('ignore:'):
        i += 1

    process(data[i])

But regardless, this was just a curiosity of mine.

chasrmartin commented 2 years ago

for item in data: if item.startswith("ignore:"); continue process(item)

tusharsadhwani commented 2 years ago

@chasrmartin that is slightly different -- my example only skips the first occurrence of 'ignore:' in a contiguous set of those.

oriontvv commented 2 years ago

@tusharsadhwani Yes, the code should look like. (btw your code will crash if you need to skip an item on last iteration - typical c-like error with wrong indexing, while safe iterator will just terminate looping)

data = """1
2
ignore: should skip
ignore: shouldn't skip
3
ignore: should skip
ignore: shouldn't crash:)""".splitlines()

def process(item):
    print(f"processing {item}")

it = iter(data)
for item in it:
    if item.startswith("ignore:"):
        item = next(it)
    process(item)
oriontvv commented 2 years ago

Btw I like this tricky experiment, but for Guido sake don't use such a code in production)

tusharsadhwani commented 2 years ago

@oriontvv

data = """1
2
ignore: should skip
ignore: shouldn't skip
3
ignore: should skip""".splitlines()

def process(item):
    print(f"processing {item}")

it = iter(data)
for item in it:
    if item.startswith("ignore:"):
        item = next(it)
    process(item)

Output:

processing 1
processing 2
processing ignore: shouldn't skip
processing 3
Traceback (most recent call last):
  File "/data/user/0/ru.iiec.pydroid3/files/accomp_files/iiec_run/iiec_run.py", line 31, in <module>
    start(fakepyfile,mainpyfile)
  File "/data/user/0/ru.iiec.pydroid3/files/accomp_files/iiec_run/iiec_run.py", line 30, in start
    exec(open(mainpyfile).read(),  __main__.__dict__)
  File "<string>", line 14, in <module>
StopIteration

Being iterator based doesn't automatically fix the logic (;

tusharsadhwani commented 2 years ago

I see your point, yeah.

And of course. I sure hope nobody uses this package outside of simple scripts!

oriontvv commented 2 years ago

Ohh, thanks - I didn't know that previous behavior has been changed with PEP 479 (since python3.5)

KarstenSchulz commented 2 years ago

Thank you for these insights. I had much fun to follow your exploring path. Keep hacking and don‘t do that at home. 😁

Param302 commented 2 years ago

Great Blog! The way you made it possible is amazing.

EhsaasChaudhary commented 1 year ago

This is great now I can use this to iterate a list's elements as key inside dictionary and get desirable output

stuaxo commented 1 year ago

This is great, I had been wondering about how to get the body of a context manager as well as codec use - fun stuff.

tusharsadhwani commented 1 year ago

@stuaxo interesting! for what usecase did you need a "context-aware" context manager?

stuaxo commented 1 year ago

Good question, it was a while ago - I can't remember right now, but I feel like it was either the same sort of "use case" as your article, or it might have been something to do with when I was playing with building live coding stuff in python.

Probably more just for the wrongness though.

tinkercnc commented 1 year ago

@tusharsadhwani

for item in it:
    if item.startswith("ignore:"):
        #item = next(it)
        continue
    process(item)

This works... ;)

tusharsadhwani commented 1 year ago

@tinkercnc the behaviour is slightly different if there are two or more ignore lines adjacent to each other

aroberge commented 1 year ago

Cool post, and I really like your idea of using a context manager - something I would not have thought about.

Rather than using a codec, you could implement this with an import hook, as described in https://aroberge.github.io/ideas/docs/html/ ;-)

tusharsadhwani commented 1 year ago

@aroberge indeed! that's one way to solve it. but since this is a language feature I'm trying to implement that has to run in a single python script, in the REPL etc. i wouldn't find that solution very satisfying.