#esoteric-python

1 messages ยท Page 87 of 1

formal sandal
#

But it drains them

rugged sparrow
#

so does zip doesnt it?

formal sandal
#
zip([1], my_generator_which_has_1000_elements)
rugged sparrow
#

!e py gen = (x for x in range(10)) print(*zip([1],gen)) print(*gen)

night quarryBOT
#

@rugged sparrow :white_check_mark: Your eval job has completed with return code 0.

001 | (1, 0)
002 | 1 2 3 4 5 6 7 8 9
rugged sparrow
#

damn

formal sandal
#

Implementing such zip would lead to an implementation of next

rugged sparrow
#

yea. i wonder how next could be implemented

edgy kelp
#

no statements?

formal sandal
#

only assignment, and no builtins

#

and dunders, I think

rugged sparrow
#

yea no dunders

#

otherwise next = lambda i:i.__next__()

formal sandal
#
next = lambda i:[*(1/0for e in i)]

This shifts an iterator by one, but it obviously blows up

#

Implementing any of next, zip or list.append (or any mutation apart from qutables) would lead to the implementation of all three and possibly much more.

rugged sparrow
#

i dont know if they are possible with the current limitations

formal sandal
#

somehow implementing nonlocal or exception catching/silencing is in the same category

rugged sparrow
#

yea

formal sandal
#

because

mutable = lambda x=None:(lambda[nonlocal x] y: (x:=y), lambda[nonlocal x]: x)
setter, getter = mutable()
#

The only mutability mechanism that allows some sort of detection is exhausting an iterator and checking if it wasn't empty or if it was equal to someting.

#

Maybe lazy (head, lambda:tail)-lists can work as generators, but how do you make them mutable.

#

oh, wait, I have an idea

#

You can combine lazy lists with quantum mutables!

#
>>> qutable = lambda:(1for i in(1))
>>> observe = lambda q:[*q]==[1]
>>> a = qutable() # unobserved (U)
>>> observe(a) # unobserved (U) -> observed (O)
True
>>> observe(a) # O
False
>>> observe(a) # O
False
#

The 'qutable' will be unobserved only when a given element hasn't been generated yet.

#

I don't know how that would work with lazy lists, but it's easy with greedy ones.

#

Basically, it allows you to remember the position in a list

rugged sparrow
#

im curious if we could find a way to unexhause the qutable

formal sandal
#

I don't think it's possible. But maybe it's possible to create mutability from the ground up using qutables and lazy lists (although I'll have to do it with greedy ones first).

rugged sparrow
#

its prob possible to remake mutablity

formal sandal
#

For example, you can recreate a natural number that can only be incremented.

#

and other extremely useless things!

rugged sparrow
#

like most of the things made here

formal sandal
#

absolutely

rugged sparrow
#

what if we allow non-dunder methods

#

so .append is allowed but .__next__ wouldnt be

formal sandal
#

that's too easy

rugged sparrow
#

fair

formal sandal
#

!e

Q = lambda:(1for i in[1])
obs = lambda q:[*q]==[1]

a = ("lorem", Q(),
    ("ipsum", Q(),
    ("dolor", Q(),
    ("sit",   Q(),
    ("amet",  Q(),
     None
    )))))

qnext = lambda qlist: (
    None if qlist is None
    else (lambda e, q, rest:
        e if obs(q) else qnext(rest)
    )(*qlist)
)
print(qnext(a))
print(qnext(a))
print(qnext(a))
print(qnext(a))
print(qnext(a))
print(qnext(a))
print(qnext(a))
night quarryBOT
#

@formal sandal :white_check_mark: Your eval job has completed with return code 0.

001 | lorem
002 | ipsum
003 | dolor
004 | sit
005 | amet
006 | None
007 | None
formal sandal
#

Maybe it can be rewritten as a loop, but this will work for <1000 elements

rugged sparrow
#

thats clever

formal sandal
#

we have found The Quantum Loophole!

#

Now we need somehow to make it work with lazy lists

#

Maybe it's possible with default arguments

#

Like, it can be [q1] for the first element, then [q1, q2] for the second one and so on. Or something

rugged sparrow
#
f = lambda a:((d:={'a':a}),lambda a:d.__setitem__('a',a),lambda:d.__getitem__('a'))[1:]
``` if only
#

we need some setitem(l:list,i:int,o:object) primitive

#

otherwise its not possible for us to do much more

rugged sparrow
#

@formal sandal slight modification to the rule set. allow def func():

#
def next(i):
    for o in i:
        return o``` cause then we can do this
formal sandal
#

I can see your point

#

But again,

that's too easy

rugged sparrow
#

theres a difference between too easy and making a challenge possible

#

while would still be forbidden

bleak raft
#

Anyone here any good with pythonnet or IronPython?

rugged sparrow
#

wrong channel

bleak raft
rugged sparrow
#

this channel is more for strange uses of python/ weird coding/ abusing syntax

#

i guess

stark fable
#

has anyone come up with a properly infinite generator yet?

#

(i.e. one that won't stop working past a certain multiple of the recursion limit)

edgy kelp
#

depends on how much you like your memory lambda: (y:=[0], (x for x in y if not y.append(0)))[1]

edgy kelp
snow beacon
#

They might correspond to local variables leaving scope and being garbage collected.

edgy kelp
#

Wouldn't that be a gradual rise and then a sudden dropoff?

snow beacon
#

Unless it allocates in advance.

thin trout
#

CPython doesn't allocate in advance AFAIK

stark fable
#

lambda: (y:=[0], (x for x in y if not y.append(0)))[1]
append

#

append isn't allowed :<

edgy kelp
#

ah thought it was only dunders

#

is it possible then? Believe that only leaves recursion as we don't get normal usable loops

formal sandal
#

Yes.

#

I think we can allow changing the recursion limit.

#

But we can pretend that the stack is infinite!

edgy kelp
#

that'll crash fairly quickly at the c level

stark fable
#

a truly infinite one might not be possible but something like this is probably close enough py r=lambda l=500:((yield from x(l-1))for x in[lambda l:[0],r,r])if l else[1]

formal sandal
#

You can't yield in a generator expression, can you?

#

!e

r=lambda l=500:((yield from x(l-1))for x in[lambda l:[0],r,r])if l else[1]
night quarryBOT
#

@formal sandal :x: Your eval job has completed with return code 1.

001 |   File "<string>", line 1
002 | SyntaxError: 'yield' inside generator expression
stark fable
#

...huh

#

in python 3.7 you can

#

but apparently not in python 3.8

#

although this does work in 3.8 py r=lambda l=500:((yield 0),(yield from r(l-1)),(yield from r(l-1)))if l else[1]

#

and given that the length of the list basically doubles(ish) every time you increase l by 1, by 500 you're dealing with about 2^500 which is 3273390607896141870013189696827599152216642046043064789483291368096133796404674554883270092325904157150886684127560071009217256545885393053328527589376

#

which is probably too big to worry about

formal sandal
#

yield works in lambdas?

#

huh

#

Is this like the Ackermann function?

#

no, that's something completely different

#

oh, I got it

stark fable
#

it's literally just recursively calling itself twice

formal sandal
#

yep

#

Have you seen the mutable finite generator implementation?

#

I've been thinking about infinite (or just lazy) generators.

#

Maybe the easiest way of implementing them is to ship each generator with a really long linked list (from my implementation) of qutables.

#

The 'next element' function can also take a boolean argument -- whether it is called the first time or not.

#

Otherwise, you won't be able to create generators that produce side-effects.

#

So the lazy part of a lazy list of natural numbers can be defined as:

_inat = lambda n=0:lambda first:(n, _inat(n+1)) + ()*bool(print(n) if first else 0)
#

Then you would have a special lazy list runtime that would accept a lazy list together with a greedy companion list.

#

Imagine a beginner opening this channel by accident...

hollow patrol
#
(lambda f: f(f, 0))(lambda f: (
  x := x + 1,
  print(x),
  f(f, x)
))```
#
do_while = lambda condition, callback: (
  (lambda f: (
    f(f)
  ))(lambda f: (
    (
      callback(),
      f(f)
    ) if condition() else None
  ))
)
edgy kelp
#

What's the first snippet supposed to do?

hollow patrol
#

the first snippet is just an infinite counter that prints each value

#

0 then 1 then 2 etc

edgy kelp
#

Doesn't look valid to me

hollow patrol
#

it works when I try it

#

well there's one bug

#
(lambda f: f(f, 0))(lambda f, x: (
  x := x + 1,
  print(x),
  f(f, x)
))
#

but then it works

edgy kelp
#

that's better

hollow patrol
#

and do_while uses a similar mechanism

edgy kelp
#

but won't it just stop at the recursion llimit?

hollow patrol
#

where it just recursively calls itself and its callback until the condition is false

#

and that's true

#

i don't see another way though

#

you could always increase the recursion limit

edgy kelp
#

can't go over a few thousand

hollow patrol
#

someone should make http://www.onelinerizer.com/ for python 3

#

question

#

how could i make take_while access the scope of the higher function like so

#
(lambda: (
  do_while := (lambda condition, callback: (
    (lambda f: (
      f(f)
    ))(lambda f: (
      (
        callback(),
        f(f)
      ) if condition() else None
    ))
  )),
  x := 1,
  do_while(lambda: 5 > x, lambda: (
    x := x + 1
  ))
))()
formal sandal
#

I don't think you can do that easily.

#

You can wrap the value in a list and then pass that list.

rugged sparrow
#

@hollow patrol that is for py2

hollow patrol
#

i meant py3

rugged sparrow
#

if we want to implement all the builtins we can without redefining mutables and such, we need to figure out next and a setval primitive

hollow patrol
#

alright

#

@rugged sparrow i made a do_while function above, but how can I edit higher variable scopes with lambdas like I tried to there

rugged sparrow
#

you cant cause lambdas cant bind nonlocal

hollow patrol
#

should I make some sort of variable dictionary and use that?

formal sandal
#

But you can pass a list containing that value

rugged sparrow
#

thats why we need to figure out altering mutables

formal sandal
#

With current conditions, proper next and setval are probably impossible, but with built-in methods it's trivial.

hollow patrol
#

What do you mean proper next and proper setval?

#

What are those?

formal sandal
#

next that works with generators properly

rugged sparrow
#

!e print(next(iter('abc')))

night quarryBOT
#

@rugged sparrow :white_check_mark: Your eval job has completed with return code 0.

a
rugged sparrow
#

next calls __next__ on the arg by default

#

can also be given a second arg that is returned if the generator is exhaused

hollow patrol
#

how does next not work properly with generators already?

rugged sparrow
#

our rules dont let us call dunders

hollow patrol
#

just use next?

rugged sparrow
#

so we are having trouble implementing next

#

the goal is reimplmentation

hollow patrol
#

oh

rugged sparrow
#

if we could def then next is easy

hollow patrol
#

i'm working on a py3 onelinerizer for python 3.8

formal sandal
#

Or if we could catch an exception somehow.

hollow patrol
#

why aren't you allowing yourself to call dunders

rugged sparrow
#

catching an exception requires __import__ in py3.8

formal sandal
#

@hollow patrol Because that'd make everyting way easier

hollow patrol
#

ok

#

why not make a generator expression from the iterable

#

and use send

formal sandal
#

You can't use builtins

#

and built-in methods

stark fable
#

no builtins, including builtin dunders

hollow patrol
#

isn't a generator expression not a builtin method

#

and send isn't a dunder

stark fable
#

send is a builtin

hollow patrol
#

oh

stark fable
#

and where's the builtin method in this ```py

import dis
dis.dis('(x for x in [1, 2, 3])')
1 0 LOAD_CONST 0 (<code object <genexpr> at 0x000002B9BA979240, file "<dis>", line 1>)
2 LOAD_CONST 1 ('<genexpr>')
4 MAKE_FUNCTION 0
6 LOAD_CONST 2 ((1, 2, 3))
8 GET_ITER
10 CALL_FUNCTION 1
12 RETURN_VALUE

Disassembly of <code object <genexpr> at 0x000002B9BA979240, file "<dis>", line 1>:
1 0 LOAD_FAST 0 (.0)
>> 2 FOR_ITER 10 (to 14)
4 STORE_FAST 1 (x)
6 LOAD_FAST 1 (x)
8 YIELD_VALUE
10 POP_TOP
12 JUMP_ABSOLUTE 2
>> 14 LOAD_CONST 0 (None)
16 RETURN_VALUE```

hollow patrol
#

you guys are making this very hard on yourselves

rugged sparrow
#

thats the point lol

hollow patrol
#

you're removing basically every useful method in Python

formal sandal
#

A builtin in this context is a name of an object or a method that is accessed directly and defined at startup. (True and such are keywords, not builtins)

stark fable
#

not "basically every useful method", every method

#

every function and method is banned

#

excluding things we define ourself

hollow patrol
#

alright

rugged sparrow
#
type = lambda o:o.__class__

type(type(()))('a',(),{})``` would this be allowed?
hollow patrol
#

__class__ is a dunder

rugged sparrow
#

but we arent directly calling it

formal sandal
#
x = lambda i:(i,i.__iadd__)
#

then this would be allowed ^

rugged sparrow
#

ah thats true

stark fable
#

would something like lambda x: x.__class__.__name__ be allowed?

#

since it's not calling anything

rugged sparrow
#

yea

#

we can allow that

hollow patrol
#

that can be rewritten as x.__getattr__('__class__').__getattr__('__name__')

#

right?

formal sandal
#

That still feels like cheating, since it's a built-in attribute

hollow patrol
#

it's still calling __getattr__

#

it kind of is cheating

formal sandal
#

What it's actually doing isn't important, since we're not calling it directly

stark fable
#

well you can rewrite a call to include __call__ but that doesn't mean you're cheating by calling something

rugged sparrow
#

some of these issues would be solved if we allow def

formal sandal
#

Yes, maybe we can allow def

#

it would allow nonlocal, next and exception catching

rugged sparrow
#
def next(i, d):
  for o in i:
    return o
  return d
#

and while

formal sandal
#
def mutable():
  x = None
  def setter(y):
    nonlocal x
    x = y
    return x
  def getter():
    return x
  return (getter, setter)
rugged sparrow
#

cant you just x = y now?

stark fable
#

and x = None

formal sandal
#

yes, my version would actually be illegal

rugged sparrow
#

we can create hacky class-like's now

stark fable
#

are we still banning actual classes?

rugged sparrow
#

yes

formal sandal
#
def mutable():
  x = None
  sentinel = {"__sentinel__"}
  def f(arg=sentinel):
      nonlocal x
      if arg is not sentinel:
          x = arg
      return x
  return f
stark fable
#

hang on a second

#

are dictionary assignments allowed?

rugged sparrow
#

yes now they are

formal sandal
#

Actually, now mutability is too easy

rugged sparrow
#

right but now we can focus on actually writing challenging stuff

#

instead of being stuck on one hurdle

stark fable
#

what things are there that we haven't done yet and want to do

rugged sparrow
#

a proper zip

#

rn i have one but it exhausts the generators its passed

formal sandal
#
def zip(a, b):
    ia = (i for i in a)
    ib = (i for i in b)
    try:
        while True:
            yield (next(ia), next(ib))
    except:
        return
#

But it might have an off-by-one error

#

Maybe we could add some silly constraints, like 'no more than 5 vowels per function'

stark fable
#

no more than 5 vowels per function
...what

formal sandal
#

Well, this zip uses 31 vowels

#

If you count def

rugged sparrow
#

zip takes any number of iterators

formal sandal
#

Yep

hollow patrol
#

how can you do from z import x with lambdas

#

and expressions only

rugged sparrow
#

__import__('z',fromlist=['x'])

#

afaik

hollow patrol
#

so does that return a tuple?

#

well, thanks!

rugged sparrow
#

im not sure what it returns

hollow patrol
#

it still returns a module

proper vault
#

fromlist afaik only matters when you are importing from a package in a package

rugged sparrow
#

yea you're right

hollow patrol
#

i guess i'll just translate

#
from MODULE import NAME1, NAME2

as

(
  __mod := __IMPORT__('MODULE'),
  NAME1 := __mod.NAME1,
  NAME2 := __mod.NAME2
)
proper vault
#

ye, that is simplest

hollow patrol
#

how should I do from MODULE import *

proper vault
#

globals().update(vars(__import__('module')))

#

may work

hollow patrol
#

that only works in the global scope

#
def x():
  from y import *
proper vault
#

you cannot dynamically create names in the local scope as far as I know without some really complicated hacks

hollow patrol
#

the imports are only in the locals there

#

and that's true

#

i guess I'll deal with globals then

rugged sparrow
#

@hollow patrol you could __import__(mod).__dict__ and loop thru the items to do from mod import *

hollow patrol
#

true

proper vault
#

you still need to modify globals to create a string name, no?

hollow patrol
#

yeah you still need to modify globals

#

you're right on that

rugged sparrow
#

i thought you were using a dict namespace

hollow patrol
#

oh, i'm using :=

proper vault
#

if you are using a dict, you may as well just .update

hollow patrol
#

if I was that would be true

#

but rn i'm using local assignment

rugged sparrow
#

globals().update(__import__(mod).__dict__) cursed

hollow patrol
#

i'm doing globals().update(vars(__import__('module')))

rugged sparrow
#

i would filter out dunder vars

hollow patrol
#

alright

rugged sparrow
#

some modules define mod.__all__ with a list of imports used for * imports

hollow patrol
#

i'll add that in later

#
            return ast.Call(
                func = ast.Attribute(
                    attr = 'update',
                    value = ast.Call(
                        func = ast.Name(
                            id = 'globals',
                        ),
                        args = [],
                        keywords = []
                    )
                ),
                args = [

                ],
                keywords = []
            )
#

that's what I'm at so far

zealous widget
#

i've used __all__ to iterate through namespaces too

hollow patrol
#

how can I convert classes to type calls

#

with their bodies having logic

#

eg.

#
class x:
  y = 3
  if True:
    z = 4
rugged sparrow
#

easier to convert to a __build_class__ call

#

prob

hollow patrol
#

huh

#

thanks @rugged sparrow

rugged sparrow
#

__build_class__ takes the body of the class compiled + a couple other args like the class name

hollow patrol
#

yeah

#

i saw

#

the body of the class is a function object

rugged sparrow
#

yea

hollow patrol
#

and that's easy since I already have code that converts bodies to expressions

#

like for loops and ifs to list comprehensions

#

and I can just put that in a lambda

rugged sparrow
#

how are you planning on handling try:except:finally

hollow patrol
#

i'm not sure

#

maybe with generators

rugged sparrow
#

you can use a context decorator to emulate a try except

hollow patrol
#

how can I do a while loop while maintaining variable context

rugged sparrow
#

like ```py
x = 0
while True:
x += 1

gentle pagoda
#

is there a py3 way of doing try/except as an expression? onelinerizer needs some deprecated contextlib functions

proper vault
#

you use contextlib.ContextDecorator

gentle pagoda
#

@proper vault how?

proper vault
#
(lambda f:type('',(__import__('contextlib').ContextDecorator,),dict(
    __enter__ = lambda *_: None,
     __exit__ = lambda s, ex, *_: ex and f() or 1))()(f)())(lambda: print(int(input())*2))
```something like this
#

you essentially use it to run a context manager inline

gentle pagoda
#
x = (
    lambda f: type(
        '',
        (__import__('contextlib').ContextDecorator,),
        dict(
            __enter__ = lambda *_: None,
            __exit__ = lambda s, ex, *_: ex and f() or 1
        )
    )
    ()
    (f)
    ()
)
(lambda: print(int(input())*2))``` what is the `__exit__` function doing, and why do you call they type 3 times? @proper vault
proper vault
#

are you familiar with context managers?

#
    )   #close the type declaration
    ()  #create an instance of the ContextDecorator subclass
    (f) #apply the decorator
    ()  #call the decorated function
gentle pagoda
#

oh i see

#

i know how context managers work, im not sure why you do ex and f() or 1 though

proper vault
#

well ex is None if there was no exception, so the and short circuits and stops the function

#

if there was an exception, f() get evaluated, and therefore called. or 1 is just to make sure True is returned from the context manager, as that means the exception was handled

#

it could be rewritten (f() or True) if ex is not None else None

gentle pagoda
#

okay, so f is the hander function (and the body of try can go in __enter__ right?)

#

why do you have to return 1?

proper vault
#

because if you return false from a context manager, it raises the exception. Body of the try is the f. What I wrote is essentially

def f():
    print(int(input())*2)
try:
    f()
except:
    f()
#

the body of the try is the decorated function

#

the body of except/finally (depending on how you write the exit function) is in __exit__. __enter__ is just a noop here

gentle pagoda
#

ah ok. can i have a callback that is run if f raises an exception?

#

oh right, i just run something else in __exit__

proper vault
#

ye

gentle pagoda
#

and f is the wrapped function

proper vault
#

ye, I also used it in the except body here, which on second thought made it a lot loss clear, my apologies

gentle pagoda
#

no worries :) thankyou so much

#

thats really helpful

hollow patrol
#

I have an idea

#

Instead of

do_while(lambda: True, lambda: (

))
#

I can do

(
  x := 0,
  [
    (x := x + 1) for _ in do_while(lambda: True)
  ]
)```
hollow patrol
#

How do you catch and raise errors in lambdas?

proper vault
hollow patrol
#

alright

#

@proper vault what about raising?

proper vault
#

(()for()in()).throw(ValueError) IIRC

hollow patrol
#

ah, thanks

hollow patrol
#

I have a question

#

with __build_class__, does the function return a dict

#

the first argument for the function

#

does the func return a dict

#

or are its locals used

hollow patrol
#

I'm a bit disappointed that I can't do i[0] := 1 or i.x := 1

rugged sparrow
#

@hollow patrol the first arg of build class returns None

#

__build_class__ returns the class object

hollow patrol
#

I mean the output of the lambda

#

That we pass in

rugged sparrow
#

the lambda passed in needs a load_name op with the arg of the class name

#

and use setattrs

hollow patrol
#

i know

#

my question is how does it get the lambda body

#

does the lambda return a dict

hollow patrol
#
x = (
    lambda f: type(
        '',
        (__import__('contextlib').ContextDecorator,),
        dict(
            __enter__ = lambda *_: None,
            __exit__ = lambda s, ex, *_: ex and f() or 1
        )
    )
    ()
    (f)
    ()
)
(lambda: print(int(input())*2))
#

hmm

#

trying to see how to use that for try except

#

how would I do a finally?

#

also how would I maintain scope?

#

how can I set variables in the inner function that apply to the outer

#

how can you do global, nonlocal and local?

proper vault
#

Finally you do the same way, just without checking for truthy ex

grim dragon
#

why is this channel named esoteric python?

#

I plan on being more active on this server soon...just finishing up a network+ certification

snow beacon
#

It's about Python, hence the word Python, but it's unconventional, hence the 'esoteric'.

thin trout
#

Basically the goal of this channel is to make GvR have an heart attack the quickest possible if he come here

#

so we try to use the most anti-pattern possible to achieve this goal

snow beacon
#

A lot of it is lipgrams, like "no parentheses" or "only lambdas".

thin trout
#

Or no line breaks

proper vault
#

or single expression only

snow beacon
#

Or we try to shorten code disgustingly much.

brisk zenith
#

or we make 2 + 2 == 5

hollow patrol
#

question

#

how can I use nonlocals in lambdas

marsh void
#

apart from modifying bytecode, I don't see a way

thin trout
#

I feel like at this point this is a valid solution haha

proper vault
#

maybe you could pass the locals() dict into the inner function

#

oh wait, you cant change things in it either

formal sandal
#

!e

exec(__import__("gzip").decompress(__import__("base64").b85decode(b'ABzY8{o%`A0{`7sO>dkq5WVv&9C|S+Lg{tY<WMz-s%llKxvf?fVNGH!UoxO%yW+oh#(WvuY?COb`oOO7_<7#E@eE#)#dS^CZGO+QOw^Bj|0S;Z#v?FTQWkY1+oUNaE8?7Q2uwZC+w+w0c?ZR{kic6}h(?q}(C_cDHRvC_iD`4J_+Wqou^5xQl8n)sXQ{S^L-MAT1xbDVz!MrqmVXzr3(0Br1LlG6xqYD~=aA&!p0c|(eAZmD&Lr0ae_qe0l4bRIv%;h!n~lljrl&no8jv(!2Wj&7z;(nmeLfH*H?h9Z0>zjDxrewgGypD6-2@yG7YR=ud2$#Chh%)~rcM_xafo`{LB~I#m6L(BEiU%cQISI!Lm3=__gbM8#7boPpy-KX$L)U!nMn0B=UfVjkr<0GF}jGC!LAQT!JnouJR24`@QR(SHr9?IYUr3!C}N5pW8@?8Fa3}#{0FcA%0?H^=YcEF&aiE(?A_>I#`2+dP=@0(UQo44F0R$Yy1o|cSk#={0pD9G;nq8iaQNSfq?D2;4S^HdoEHsA$`+n!DSLuMOAX%%6ug5@cd+A(NXipUpEaHD+*GYHnEEGGTceZc0KZX!yLMt21Ui5T3HOEY0-_}2hSNWyTBL)L$VLekC3?&bsLy@6{BCp9=@+yBE}LVo=U5&@Gv!AWOAv?cMFOs%@0#?gacBk*OKr9^b2TcpFjIl$pJg$WI&`H>2Pd3~XYZaTlhJ`6VPWzhs;f*i)Q|jN`)RjIWDDDNu+P$O0$OI3_pfR`wcN4Y&K=gE(cSo_Mqj}rif#p~Dw)ExASw-_$tqYELxapk4Hf5MLWL-3pimLu#rA3!3BXqeEUN&Pm1@W*KsPdMz?{#AI~Muy#8VbHXtMPgi}#Jfs~Pimqa^wv&SvRa=h^r{xvW&*`LQol$_FFt=BHvGqY4CuM1dIfX`t#S{9GQMj7o}%u{jP(MWxeZF%iVvMQe*SESx$si<GJ7y`i5wd-)ss`1u~LU$UzmcJ%%Wb11H!QK4RRZ%zw{j*N3HTAg)q==@crX*$4H@Y?$eU^)i!eGC8q')))

class MaybeInt(SumType):
    Just.of( int )
    Nothing.of( () )

print(MaybeInt)

x = MaybeInt.Just(42)
print(f"{x=}, {type(x)=}, {MaybeInt.Just}")
assert isinstance(x, int) and isinstance(x, MaybeInt) and isinstance(x, MaybeInt.Just) and not isinstance(x, MaybeInt.Nothing)

n = MaybeInt.Nothing()
print(f"{n=}, {type(n)=}, {MaybeInt.Nothing}")
assert isinstance(n, tuple) and isinstance(n, MaybeInt) and isinstance(n, MaybeInt.Nothing) and not isinstance(n, MaybeInt.Just)
night quarryBOT
#

@formal sandal :white_check_mark: Your eval job has completed with return code 0.

001 | MaybeInt {'Just': <:MaybeInt.Just :: <class 'int'>>, 'Nothing': <:MaybeInt.Nothing :: ()>}
002 | x=42, type(x)=embellished('MaybeInt.Just', <class 'int'>), MaybeInt.Just
003 | n=(), type(n)=embellished('MaybeInt.Nothing', ()), MaybeInt.Nothing
formal sandal
#

@marsh void That's the module with a function that creates a class, a metaclass and a metametaclass dynamically.

thin trout
#

Abstract art code haha

real galleon
#

what does << do?

proper vault
#

bit shift left

real galleon
#

Alr

#

so im guessing >> is a right shift

proper vault
#

ye

formal sandal
#

Well...

#

apart from numbers, it does what you want

proper vault
#
0b001100 << 2 == \
0b110000
0b001100 >> 2 == \
0b000011
#

ye, you can override it to make it whatever you need, from monadic bind to function composition (as long as you use a custom class for the function)

formal sandal
#

!e

import sys

class FlushOnWrite:
    def __init__(self, text):
        self.text = text

    def __ostream__(self, file):
        file.write(self.text)
        file.flush()

endl = FlushOnWrite("\n")

class OStream:
    def __init__(self, file):
        self.file = file

    def __lshift__(self, obj):
        if hasattr(obj, "__ostream__"):
            obj.__ostream__(self.file)
        else:
            self.file.write(str(obj))
        return self

cout = OStream(sys.stdout)

cout << "Your age is: " << 42 << "!" << endl;
night quarryBOT
#

@formal sandal :white_check_mark: Your eval job has completed with return code 0.

Your age is: 42!
formal sandal
#

@real galleon

real galleon
#

yeeass?

formal sandal
#

what does << do?

#

^

#

:)

real galleon
#

hmmm

#

im not new to python but i never knew it could look so artisitc xd

formal sandal
#

I even put a ; to make it clear that I'm doing something ugly.

real galleon
#

xd

#

i lvoe it

hollow patrol
#

I really want to add a try to my lambda

#

Without breaking scope

real galleon
#

anyone got a bytes alpha bet xd

#

ahh nvm i forgot i can just look up sommat like ascii characters

hollow patrol
#

Maybe there's an alternate solution

#

One idea I have is

formal sandal
#

You can create a function rewriter that mutates the __code__ of a lambda.

hollow patrol
#
[
  (
    #HANDLE EXCEPTION
  )
  for e in catch_errors(lambda: ())
]
#

and I don't want to do that

#

I'm trying to output ast

formal sandal
#

oh

hollow patrol
#

I really have two choices

#

Either I have to switch my variables to use a dictionary system

#

or I have to find a way to do a try and catch with scope

#

just like I did with while

#
[ ( ... ) for _ in do_while(lambda: ...) ]
proper vault
#

another option would be use globals only and mangle names depending on scope

formal sandal
#

You can apply the code rewriter anonymously and inline...fully?

hollow patrol
#

that means the bytecode rewriter would have to be anonymous as well

formal sandal
#

yep

hollow patrol
#

I'm not sure how to write bytecode though

formal sandal
#

@proper vault That will not work if you have several instances of a closured function

proper vault
#

ah, good point

formal sandal
#

So maybe you'll have to assign some 'call id' to each function

#

Then maintain a scope for each call id

hollow patrol
#

I want to differentiate between lambdas with separate scopes

#

And lambda sharing the parent scope

#

Basically, nonlocals in lambdas

formal sandal
#

Well, you can do that by defining some stuff in these scopes.

#
scope[1234] = {"__parent_scope__": 256, "__nonlocal__": ["x", "y"], "__global__": ["CONSTANT1"], "__local__": {...}}
hollow patrol
#

I have no idea how I'd make that work

#

and where scope comes from

formal sandal
#

You'll have to wrap everything in a scope manager function. That will produce lots of noise, though.

hollow patrol
#

Why can't I only wrap functions that I need to manage scope in the function

#
(
  f := lambda x, y: print(x, y), #f doesn't share scope
  y := parent_scope(lambda a, b: print(a, b)), #y does share scope
)
#

where parent_scope modifies bytecode

formal sandal
#

Maybe you could somehow use inspect, but I'm not sure

hollow patrol
#

and I think it's cheating to use exec('nonlocal x') inside of the lambdas

formal sandal
#

It shouldn't work

#

nonlocal is a declaration AFAIK

#

!e

import dis
def f():
  x = 1
  def g():
    nonlocal x
    return x
  return g
G = f()
dis.dis(G)
night quarryBOT
#

@formal sandal :white_check_mark: Your eval job has completed with return code 0.

001 |   6           0 LOAD_DEREF               0 (x)
002 |               2 RETURN_VALUE
formal sandal
#

!e

import dis
def g():
  return x
dis.dis(g)
night quarryBOT
#

@formal sandal :white_check_mark: Your eval job has completed with return code 0.

001 |   3           0 LOAD_GLOBAL              0 (x)
002 |               2 RETURN_VALUE
formal sandal
#

Yep, it's a totally different instruction.

#

But you could simply replace that in bytecode

hollow patrol
#

hold on

#

how would I add in LOAD_DEREF to lambdas

#

how do you edit bytecode at all?

formal sandal
#

You use f.__code__.replace(co_code=...)

hollow patrol
#

!e

import dis
def f():
  x = 1
  return x
dis.dis(f)
night quarryBOT
#

@hollow patrol :white_check_mark: Your eval job has completed with return code 0.

001 |   3           0 LOAD_CONST               1 (1)
002 |               2 STORE_FAST               0 (x)
003 | 
004 |   4           4 LOAD_FAST                0 (x)
005 |               6 RETURN_VALUE
formal sandal
#

!e

def f():
  x = 1
  def g():
    nonlocal x
    return x
  return g

def g():
  return x

G = f()

print(f"{G.__code__.co_code=}")
print(f"{g.__code__.co_code=}")
night quarryBOT
#

@formal sandal :white_check_mark: Your eval job has completed with return code 0.

001 | G.__code__.co_code=b'\x88\x00S\x00'
002 | g.__code__.co_code=b't\x00S\x00'
hollow patrol
#

!e

import dis
def f():
  x = 1
  def g():
    nonlocal x
    x = 1
    return x
  return g
G = f()
dis.dis(G)
night quarryBOT
#

@hollow patrol :white_check_mark: Your eval job has completed with return code 0.

001 |   6           0 LOAD_CONST               1 (1)
002 |               2 STORE_DEREF              0 (x)
003 | 
004 |   7           4 LOAD_DEREF               0 (x)
005 |               6 RETURN_VALUE
hollow patrol
#

so

#

I'd replace LOAD_FAST STORE_FAST with LOAD_DEREF STORE_DEREF?

#

or am I wrong?

formal sandal
#

!e

def f():
  x = 1
  def g():
    nonlocal x
    return x
  return g

def g():
  return x

G = f()

print([*map(hex, G.__code__.co_code)])
print([*map(hex, g.__code__.co_code)])
night quarryBOT
#

@formal sandal :white_check_mark: Your eval job has completed with return code 0.

001 | ['0x88', '0x0', '0x53', '0x0']
002 | ['0x74', '0x0', '0x53', '0x0']
formal sandal
#

Yes

hollow patrol
#

alright

#

how can I replace them?

formal sandal
#

You'll need to replace b'\x74\x00' with b'\x88\x00'

hollow patrol
#

and what about b'\x53\x00' ?

marsh void
#

not really always \x00

real galleon
formal sandal
#

yes, x just happend to be the variable 0

marsh void
#

@real galleon you forgot an operator

hollow patrol
#

!e

def f():
  x = 1
  def g():
    nonlocal x
    x = 2
    return x
  return g

def g():
  x = 2
  return x

G = f()

print([*map(hex, G.__code__.co_code)])
print([*map(hex, g.__code__.co_code)])
night quarryBOT
#

@hollow patrol :white_check_mark: Your eval job has completed with return code 0.

001 | ['0x64', '0x1', '0x89', '0x0', '0x88', '0x0', '0x53', '0x0']
002 | ['0x64', '0x1', '0x7d', '0x0', '0x7c', '0x0', '0x53', '0x0']
marsh void
#

between c and (a ^ a)

real galleon
#

just seen aha thank you

hollow patrol
#

so I replace x74 with x88

formal sandal
#

yep

#

!e

import dis

def g():
     return x

g.__code__ = g.__code__.replace(co_code=g.__code__.co_code.replace(b'\x74\x00', b'\x88\x00'))

g()
night quarryBOT
#

@formal sandal :warning: Your eval job has completed with return code 139 (SIGSEGV).

[No output]
formal sandal
#

as intended

hollow patrol
#

and what about the other one

formal sandal
#

my favourite error

hollow patrol
#

I have to do LOAD_DEFER and STORE_DEFER right

real galleon
#

any reasons why it wouldn't strip the numbers?

s=7;print(s);msg='  g 5 2 3 3 3 3 2 5 2    52 5   2 5\
522  232        o   21   3  67 52 837 623 498   7 od\
ay sir';msg=msg.strip('5');msg=msg.strip('2');msg=msg.strip('3');msg=msg.strip('1');msg=msg.strip('6');msg=msg.strip('7');msg=msg.strip('8');msg=msg.strip('9');msg=msg.strip('4');msg=msg.strip('52');msg=msg.strip('522');msg=msg.strip('232');msg=msg.strip('21');msg=msg.strip('67');msg=msg.strip('837');msg=msg.strip('623');msg=msg.strip('498');msg=msg.strip(' ');print(msg)
formal sandal
real galleon
#

oki

hollow patrol
#

@formal sandal you're only replacing x74 with x88

formal sandal
#

This channel is for stuff that will make you want to unsee it, so

hollow patrol
#

does this account for both

formal sandal
#

Yes, STORE will have to be replaced as well manually

hollow patrol
#

storing and loading

marsh void
#

strip removes numbers from ends

hollow patrol
#

alright

#

why not

#

g.__code__ = g.__code__.replace(co_code=g.__code__.co_code.replace(b'\x74', b'\x88'))

#

why do you need the \x00

#

sorry, I'm new to bytecode editing

formal sandal
#

\x00 there indicates the variable index or something

#

(me too!)

hollow patrol
#

alright

#

so then I could do something like

#
def parent_scope(f):
  f.__code__ = f.__code__.replace(co_code=f.__code__.co_code.replace(b'\x74', b'\x88'))
  return f
#

and then

formal sandal
#

If you want to take all variables from the parent scope, then... maybe

hollow patrol
#

yep, all of them from the direct parent scope

#

this is equal to

        parent_scope := (
            lambda f: (
                f.__setattr__(
                    "__code__",
                    f.__code__.replace(
                        co_code=f.__code__.co_code.replace(b"t", b"\x88")
                    ),
                ),
                f,
                None,
            )[(-1)]
        )
#

right?

#

oh yep

#

except the return

formal sandal
#

But \x74 could potentially refer to something else, so you'll have to experiment

hollow patrol
#

actually

#
def parent_scope(f):
  f.__code__ = f.__code__.replace(co_code=f.__code__.co_code.replace(b'\x74\x00', b'\x88\x00'))
  return f
#
       parent_scope := (
            lambda f: (
                f.__setattr__(
                    "__code__",
                    f.__code__.replace(
                        co_code=f.__code__.co_code.replace(b"t\x00", b"\x88\x00")
                    ),
                ),
                f
            )[(-1)]
        )
#

so like this?

formal sandal
#

yes, and you'll also need to change the store

hollow patrol
#

wait, those are separate instructions?

formal sandal
#

of course

#

one for getting, one for setting

hollow patrol
#

is store something like \x74\x01

#

or \x75\x00

formal sandal
#

!e

import dis

def f():
  x, y = 1, 2
  def g():
    nonlocal x, y
    return x + y
  return g

dis.dis(f())
night quarryBOT
#

@formal sandal :white_check_mark: Your eval job has completed with return code 0.

001 |   7           0 LOAD_DEREF               0 (x)
002 |               2 LOAD_DEREF               1 (y)
003 |               4 BINARY_ADD
004 |               6 RETURN_VALUE
formal sandal
#

!e

def f():
  x, abc = 1, 2
  def g():
    nonlocal x, abc
    return x + abc
  return g

print(*map(hex, f().__code__.co_code))
night quarryBOT
#

@formal sandal :white_check_mark: Your eval job has completed with return code 0.

0x88 0x1 0x88 0x0 0x17 0x0 0x53 0x0
hollow patrol
#

oh

#

0x1

formal sandal
#

Here, 0x88 is the instruction, and 0x1 and 0x0 are its arguments

hollow patrol
#

so is that like the variable index?

formal sandal
#

yes

hollow patrol
#

alright

#

so why not just replace all 0x88

#

with that account for any variables like that too

#

with the 88 index

formal sandal
#

88 corresponds to the LOAD_DEREF instruction, which fetches a variable from the local scope of the parent closure.

hollow patrol
#

!e

def f():
  x, abc = 1, 2
  def g():
    nonlocal x, abc
    x, abc = 1
  return g

print(*map(hex, f().__code__.co_code))
night quarryBOT
#

@hollow patrol :white_check_mark: Your eval job has completed with return code 0.

0x64 0x1 0x5c 0x2 0x89 0x1 0x89 0x0 0x64 0x0 0x53 0x0
hollow patrol
#

what is 0x89

#

!e

night quarryBOT
#
Command Help

!eval [code]
Can also use: e

*Run Python code and get the results.

This command supports multiple lines of code, including code wrapped inside a formatted code
block. Code can be re-evaluated by editing the original message within 10 seconds and
clicking the reaction that subsequently appears.

We've done our best to make this sandboxed, but do let us know if you manage to find an
issue with it!*

formal sandal
#

!e

import dis
def f():
  x, abc = 1, 2
  def g():
    nonlocal x, abc
    x, abc = 1
  return g
dis.dis(f())
night quarryBOT
#

@formal sandal :white_check_mark: Your eval job has completed with return code 0.

001 |   6           0 LOAD_CONST               1 (1)
002 |               2 UNPACK_SEQUENCE          2
003 |               4 STORE_DEREF              1 (x)
004 |               6 STORE_DEREF              0 (abc)
005 |               8 LOAD_CONST               0 (None)
006 |              10 RETURN_VALUE
hollow patrol
#

!e

def f():
  x, abc = 1, 2
  def g():
    nonlocal x, abc
    x, abc = 1
  return g

#print(*map(hex, f().__code__.co_code))
dis.dis(f)
night quarryBOT
#

@hollow patrol :x: Your eval job has completed with return code 1.

001 | Traceback (most recent call last):
002 |   File "<string>", line 9, in <module>
003 | NameError: name 'dis' is not defined
formal sandal
#

it must be UNPACK_SEQUENCE

hollow patrol
#

oh hold on

formal sandal
#

maybe

hollow patrol
#

!e

import dis
def f():
  x, abc = 1, 2
  def g():
    nonlocal x, abc
    x = abc
  return g
dis.dis(f())
night quarryBOT
#

@hollow patrol :white_check_mark: Your eval job has completed with return code 0.

001 |   6           0 LOAD_DEREF               0 (abc)
002 |               2 STORE_DEREF              1 (x)
003 |               4 LOAD_CONST               0 (None)
004 |               6 RETURN_VALUE
hollow patrol
#

!e

import dis
def f():
  x, abc = 1, 2
  def g():
    nonlocal x, abc
    x = abc
  return g
print(*map(hex, f().__code__.co_code))
#dis.dis(f())
night quarryBOT
#

@hollow patrol :white_check_mark: Your eval job has completed with return code 0.

0x88 0x0 0x89 0x1 0x64 0x0 0x53 0x0
hollow patrol
#

I think it's 0x89

#

STORE_DEREF is 0x89

formal sandal
hollow patrol
#
LOAD_DEREF 0x88
LOAD_FAST 0x74
#

alright

#

so

#
LOAD_DEREF 0x88
LOAD_FAST 0x74
STORE_DEREF 0x89
#

I think STORE_FAST is 0x75

#

so

#
def parent_scope(f):
  f.__code__ = f.__code__.replace(co_code=f.__code__.co_code.replace(b'\x74', b'\x88').replace(b'\x75', b'\x89'))
  return f
formal sandal
#

!e

import dis
print(dis.opmap)
night quarryBOT
#

@formal sandal :white_check_mark: Your eval job has completed with return code 0.

{'POP_TOP': 1, 'ROT_TWO': 2, 'ROT_THREE': 3, 'DUP_TOP': 4, 'DUP_TOP_TWO': 5, 'ROT_FOUR': 6, 'NOP': 9, 'UNARY_POSITIVE': 10, 'UNARY_NEGATIVE': 11, 'UNARY_NOT': 12, 'UNARY_INVERT': 15, 'BINARY_MATRIX_MULTIPLY': 16, 'INPLACE_MATRIX_MULTIPLY': 17, 'BINARY_POWER': 19, 'BINARY_MULTIPLY': 20, 'BINARY_MODULO': 22, 'BINARY_ADD': 23, 'BINARY_SUBTRACT': 24, 'BINARY_SUBSCR': 25, 'BINARY_FLOOR_DIVIDE': 26, 'BINARY_TRUE_DIVIDE': 27, 'INPLACE_FLOOR_DIVIDE': 28, 'INPLACE_TRUE_DIVIDE': 29, 'GET_AITER': 50, 'GET_ANEXT': 51, 'BEFORE_ASYNC_WITH': 52, 'BEGIN_FINALLY': 53, 'END_ASYNC_FOR': 54, 'INPLACE_ADD': 55, 'INPLACE_SUBTRACT': 56, 'INPLACE_MULTIPLY': 57, 'INPLACE_MODULO': 59, 'STORE_SUBSCR': 60, 'DELETE_SUBSCR': 61, 'BINARY_LSHIFT': 62, 'BINARY_RSHIFT': 63, 'BINARY_AND': 64, 'BINARY_XOR': 65, 'BINARY_OR': 66, 'INPLACE_POWER': 67, 'GET_ITER': 68, 'GET_YIELD_FROM_ITER': 69, 'PRINT_EXPR': 70, 'LOAD_BUILD_CLASS': 71, 'YIELD_FROM': 72, 'GET_AWAITABLE': 73, 'INPLACE_LSHIFT': 75, 'INPLACE_RSHIFT': 76, 'INPLAC
... (truncated - too long)

Full output: too long to upload

hollow patrol
#

!e

def parent_scope(f):
  f.__code__ = f.__code__.replace(co_code=f.__code__.co_code.replace(b'\x74', b'\x88').replace(b'\x75', b'\x89'))
  return f

def outer():
  x = 3
  @parent_scope
  def inner():
    x = 4
  inner()
  print(x)
night quarryBOT
#

@hollow patrol :warning: Your eval job has completed with return code 0.

[No output]
hollow patrol
#

what?

#

why is that failing

formal sandal
#

you didn't call outer

hollow patrol
#

!e
!e

def parent_scope(f):
  f.__code__ = f.__code__.replace(co_code=f.__code__.co_code.replace(b'\x74', b'\x88').replace(b'\x75', b'\x89'))
  return f

def outer():
  x = 3
  @parent_scope
  def inner():
    x = 4
  inner()
  print(x)
outer()
night quarryBOT
#

@hollow patrol :x: Your eval job has completed with return code 1.

001 |   File "<string>", line 1
002 |     !e
003 |     ^
004 | SyntaxError: invalid syntax
formal sandal
#

!e

def parent_scope(f):
  f.__code__ = f.__code__.replace(co_code=f.__code__.co_code.replace(b'\x74', b'\x88').replace(b'\x75', b'\x89'))
  return f

def outer():
  x = 3
  @parent_scope
  def inner():
    x = 4
  inner()
  print(x)

outer()
night quarryBOT
#

@formal sandal :white_check_mark: Your eval job has completed with return code 0.

3
hollow patrol
#

what?

#

!e

def parent_scope(f):
  f.__code__ = f.__code__.replace(co_code=f.__code__.co_code.replace(b'\x74', b'\x88').replace(b'\x75', b'\x89'))
  return f

def outer():
  x = 3
  @parent_scope
  def inner():
    x = 4
  inner()
  print(x)
outer()
night quarryBOT
#

@hollow patrol :white_check_mark: Your eval job has completed with return code 0.

3
hollow patrol
#

but I replaced the instructions?

#

!e

import dis

def parent_scope(f):
  f.__code__ = f.__code__.replace(co_code=f.__code__.co_code.replace(b'\x74', b'\x88').replace(b'\x75', b'\x89'))
  return f

def outer():
  x = 3
  @parent_scope
  def inner():
    x = 4
  dis.dis(inner)
outer()
night quarryBOT
#

@hollow patrol :white_check_mark: Your eval job has completed with return code 0.

001 |  11           0 LOAD_CONST               1 (4)
002 |               2 STORE_FAST               0 (x)
003 |               4 LOAD_CONST               0 (None)
004 |               6 RETURN_VALUE
hollow patrol
#

what is going on?

#

!e

import dis

def parent_scope(f):
  print(dis.dis(f))
  f.__code__ = f.__code__.replace(co_code=f.__code__.co_code.replace(b'\x74', b'\x88').replace(b'\x75', b'\x89'))
  print(dis.dis(f))
  return f

def outer():
  x = 3
  @parent_scope
  def inner():
    x = 4
outer()
night quarryBOT
#

@hollow patrol :white_check_mark: Your eval job has completed with return code 0.

001 |  13           0 LOAD_CONST               1 (4)
002 |               2 STORE_FAST               0 (x)
003 |               4 LOAD_CONST               0 (None)
004 |               6 RETURN_VALUE
005 | None
006 |  13           0 LOAD_CONST               1 (4)
007 |               2 STORE_FAST               0 (x)
008 |               4 LOAD_CONST               0 (None)
009 |               6 RETURN_VALUE
010 | None
hollow patrol
#

nothing changed

#

!e

import dis

def parent_scope(f):
  print(dis.dis(f))
  f.__code__ = f.__code__.replace(co_code=f.__code__.co_code.replace(b'\x74', b'\x88').replace(b'\x75', b'\x89'))
  print(dis.dis(f))
  return f

def outer():
  x = 3
  @parent_scope
  def inner():
    print(x)
outer()
night quarryBOT
#

@hollow patrol :white_check_mark: Your eval job has completed with return code 0.

001 |  13           0 LOAD_GLOBAL              0 (print)
002 |               2 LOAD_DEREF               0 (x)
003 |               4 CALL_FUNCTION            1
004 |               6 POP_TOP
005 |               8 LOAD_CONST               0 (None)
006 |              10 RETURN_VALUE
007 | None
008 |  13           0 LOAD_DEREF               0 (x)
009 |               2 LOAD_DEREF               0 (x)
010 |               4 CALL_FUNCTION            1
011 |               6 POP_TOP
... (truncated - too many lines)

Full output: https://paste.pythondiscord.com/resubutehi

formal sandal
#

wtf

hollow patrol
#

hold on

#

nothing changed

#

except it switched to LOAD_DEREF?

#
import dis

def outer():
  x = 3
  @parent_scope
  def inner():
    nonlocal x
    y = x
    x = 3
outer()
#
import dis

def outer():
  x = 3
  def inner():
    nonlocal x
    y = x
    x = 3
  return inner
dis.dis(outer())
#

!e

import dis

def outer():
  x = 3
  def inner():
    nonlocal x
    y = x
    x = 3
  return inner
dis.dis(outer())
night quarryBOT
#

@hollow patrol :white_check_mark: Your eval job has completed with return code 0.

001 |   7           0 LOAD_DEREF               0 (x)
002 |               2 STORE_FAST               0 (y)
003 | 
004 |   8           4 LOAD_CONST               1 (3)
005 |               6 STORE_DEREF              0 (x)
006 |               8 LOAD_CONST               0 (None)
007 |              10 RETURN_VALUE
formal sandal
#
001 |  13           0 LOAD_GLOBAL              0 (print)
002 |               2 LOAD_DEREF               0 (x)
003 |               4 CALL_FUNCTION            1
004 |               6 POP_TOP
005 |               8 LOAD_CONST               0 (None)
006 |              10 RETURN_VALUE
007 | None
008 |  13           0 LOAD_DEREF               0 (x)
009 |               2 LOAD_DEREF               0 (x)
010 |               4 CALL_FUNCTION            1
011 |               6 POP_TOP

Well, it used to load a global constant by the name 0 where 0 refers to the index in co_const (where 0 => print ), and now it loads a nonlocal variable by the name 0

hollow patrol
#

I wish dis.dis showed you the bytecodes

#

I replaced LOAD_FAST not LOAD_GLOBAL though

#

!e

import dis

def outer():
  x = 3
  def inner():
    nonlocal x
    y = x
    x = 3
    z = y
  return inner
dis.dis(outer())
night quarryBOT
#

@hollow patrol :white_check_mark: Your eval job has completed with return code 0.

001 |   7           0 LOAD_DEREF               0 (x)
002 |               2 STORE_FAST               0 (y)
003 | 
004 |   8           4 LOAD_CONST               1 (3)
005 |               6 STORE_DEREF              0 (x)
006 | 
007 |   9           8 LOAD_FAST                0 (y)
008 |              10 STORE_FAST               1 (z)
009 |              12 LOAD_CONST               0 (None)
010 |              14 RETURN_VALUE
hollow patrol
#

so that has all of our targets

#

LOAD_FAST, STORE_FAST, LOAD_CONST, STORE_CONST

#

not STORE_CONST

#

LOAD_FAST, LOAD_DEFER, STORE_FAST, STORE_DEREF

formal sandal
#

yes, STORE_CONST would be a strange instruction...

hollow patrol
#

!e

import dis

def outer():
  x = 3
  def inner():
    nonlocal x
    y = x
    x = 3
    z = y
  return inner
f = outer()
print(*map(lambda i: (hex(i), dis.op_map[int(hex(i), 16)]), f().__code__.co_code))
night quarryBOT
#

@hollow patrol :x: Your eval job has completed with return code 1.

001 | Traceback (most recent call last):
002 |   File "<string>", line 12, in <module>
003 | AttributeError: 'NoneType' object has no attribute '__code__'
hollow patrol
#

!e

import dis

def outer():
  x = 3
  def inner():
    nonlocal x
    y = x
    x = 3
    z = y
  return inner
f = outer()
print(f)
print(*map(lambda i: (hex(i), dis.op_map[int(hex(i), 16)]), f().__code__.co_code))
night quarryBOT
#

@hollow patrol :x: Your eval job has completed with return code 1.

001 | <function outer.<locals>.inner at 0x7f35468a1940>
002 | Traceback (most recent call last):
003 |   File "<string>", line 13, in <module>
004 | AttributeError: 'NoneType' object has no attribute '__code__'
hollow patrol
#

!e

import dis

def outer():
  x = 3
  def inner():
    nonlocal x
    y = x
    x = 3
    z = y
  return inner
f = outer()
def instruction(x):
  name = dis.opmap[int(hex(x), 16)]
  ashex = hex(x)
  return name, ashex
print(map(instruction, f.__code__.co_code))
night quarryBOT
#

@hollow patrol :white_check_mark: Your eval job has completed with return code 0.

<map object at 0x7f36eaa08df0>
hollow patrol
#

!e

import dis

def outer():
  x = 3
  def inner():
    nonlocal x
    y = x
    x = 3
    z = y
  return inner
f = outer()
def instruction(x):
  name = dis.opmap[int(hex(x), 16)]
  ashex = hex(x)
  return name, ashex
print(list(map(instruction, f.__code__.co_code)))
night quarryBOT
#

@hollow patrol :x: Your eval job has completed with return code 1.

001 | Traceback (most recent call last):
002 |   File "<string>", line 16, in <module>
003 |   File "<string>", line 13, in instruction
004 | KeyError: 136
real galleon
#

!e

msg = bytes([(True << (True ^ True << True) ^ True << (True ^ True << (True << True)) ^ True << (True << True ^ True << (True << True))), (True ^ True << (True << True) ^ True << (True ^ True << (True << True)) ^ True << (True << True ^ True << (True << True))), (True << (True << True) ^ True << (True ^ True << True) ^ True << (True ^ True << (True << True)) ^ True << (True << True ^ True << (True << True))), (True << (True << True) ^ True << (True ^ True << True) ^ True << (True ^ True << (True << True)) ^ True << (True << True ^ True << (True << True))), (True ^ True << True ^ True << (True << True) ^ True << (True ^ True << True) ^ True << (True ^ True << (True << True)) ^ True << (True << True ^ True << (True << True)))]);import hashlib;msg=hashlib.md5(msg);msg=msg.hexdigest();output = lambda a, b, c, d, e, f: (a * b - c ^ e << (d * f)) if msg == "5d41402abc4b2a76b9719d911017c592" else 'no';c=print;_4883=str;output_ = c(_4883(output(1, 5, 6, 4, 3, 2)) if output == "<function <lambda> at 0x000001C135F25E18>" else "no"
night quarryBOT
#

@real galleon :x: Your eval job has completed with return code 1.

001 |   File "<string>", line 1
002 |     msg = bytes([(True << (True ^ True << True) ^ True << (True ^ True << (True << True)) ^ True << (True << True ^ True << (True << True))), (True ^ True << (True << True) ^ True << (True ^ True << (True << True)) ^ True << (True << True ^ True << (True << True))), (True << (True << True) ^ True << (True ^ True << True) ^ True << (True ^ True << (True << True)) ^ True << (True << True ^ True << (True << True))), (True << (True << True) ^ True << (True ^ True << True) ^ True << (True ^ True << (True << True)) ^ True << (True << True ^ True << (True << True))), (True ^ True << True ^ True << (True << True) ^ True << (True ^ True << True) ^ True << (True ^ True << (True << True)) ^ True << (True << True ^ True << (True << True)))]);import hashlib;msg=hashlib.md5(msg);msg=msg.hexdigest();output = lambda a, b, c, d, e, f: (a * b - c ^ e << (d * f)) if msg == "5d41402abc4b2a76b9719d911017c592" else 'no';c=print;_4883=str;output_ = c(_4883(output(1, 5, 6
... (truncated - too long)

Full output: too long to upload

hollow patrol
#

!e

import dis

def outer():
  x = 3
  def inner():
    nonlocal x
    y = x
    x = 3
    z = y
  return inner
f = outer()
def instruction(x):
  print(hex(x), int(hex(x), 16))
  name = dis.opmap[int(hex(x), 16)]
  ashex = hex(x)
  return name, ashex
print(list(map(instruction, f.__code__.co_code)))
night quarryBOT
#

@hollow patrol :x: Your eval job has completed with return code 1.

001 | 0x88 136
002 | Traceback (most recent call last):
003 |   File "<string>", line 17, in <module>
004 |   File "<string>", line 14, in instruction
005 | KeyError: 136
hollow patrol
#

import dis

def outer():
x = 3
def inner():
nonlocal x
y = x
x = 3
z = y
return inner
f = outer()
def instruction(x):
print(hex(x), int(hex(x), 10))
name = dis.opmap[int(hex(x), 10)]
ashex = hex(x)
return name, ashex
print(list(map(instruction, f.code.co_code)))

#

!e

import dis

def outer():
  x = 3
  def inner():
    nonlocal x
    y = x
    x = 3
    z = y
  return inner
f = outer()
def instruction(x):
  print(hex(x), int(hex(x), 10))
  name = dis.opmap[int(hex(x), 10)]
  ashex = hex(x)
  return name, ashex
print(list(map(instruction, f.__code__.co_code)))
night quarryBOT
#

@hollow patrol :x: Your eval job has completed with return code 1.

001 | Traceback (most recent call last):
002 |   File "<string>", line 17, in <module>
003 |   File "<string>", line 13, in instruction
004 | ValueError: invalid literal for int() with base 10: '0x88'
hollow patrol
#

!e

import dis

def outer():
  x = 3
  def inner():
    nonlocal x
    y = x
    x = 3
    z = y
  return inner
f = outer()
def instruction(x):
  print(hex(x), int(hex(x), 16))
  name = dis.opmap[int(hex(x), 16)]
  ashex = hex(x)
  return name, ashex
print(list(map(instruction, f.__code__.co_code)))
night quarryBOT
#

@hollow patrol :x: Your eval job has completed with return code 1.

001 | 0x88 136
002 | Traceback (most recent call last):
003 |   File "<string>", line 17, in <module>
004 |   File "<string>", line 14, in instruction
005 | KeyError: 136
hollow patrol
#

!e

import dis

def outer():
  x = 3
  def inner():
    nonlocal x
    y = x
    x = 3
    z = y
  return inner
f = outer()
def instruction(x):
  print(hex(x), int(hex(x), 16))
  name = dis.opmap.get(int(hex(x), 16), "INVALID")
  ashex = hex(x)
  return name, ashex
print(list(map(instruction, f.__code__.co_code)))
real galleon
#

!e

msg = bytes([(True << (True ^ True << True) ^ True << (True ^ True << (True << True)) ^ True << (True << True ^ True << (True << True))), (True ^ True << (True << True) ^ True << (True ^ True << (True << True)) ^ True << (True << True ^ True << (True << True))), (True << (True << True) ^ True << (True ^ True << True) ^ True << (True ^ True << (True << True)) ^ True << (True << True ^ True << (True << True))), (True << (True << True) ^ True << (True ^ True << True) ^ True << (True ^ True << (True << True)) ^ True << (True << True ^ True << (True << True))), (True ^ True << True ^ True << (True << True) ^ True << (True ^ True << True) ^ True << (True ^ True << (True << True)) ^ True << (True << True ^ True << (True << True)))]);import hashlib;msg=hashlib.md5(msg);msg=msg.hexdigest();output = lambda a, b, c, d, e, f: (a * b - c ^ e << (d * f)) if msg == "5d41402abc4b2a76b9719d911017c592" else 'no';c=print;_4883=str;output_ = c(_4883(output(1, 5, 6, 4, 3, 2)) if output == "<function <lambda> at 0x000001C135F25E18>" else "no";
night quarryBOT
#

@hollow patrol :white_check_mark: Your eval job has completed with return code 0.

001 | 0x88 136
002 | 0x0 0
003 | 0x7d 125
004 | 0x0 0
005 | 0x64 100
006 | 0x1 1
007 | 0x89 137
008 | 0x0 0
009 | 0x7c 124
010 | 0x0 0
011 | 0x7d 125
... (truncated - too many lines)

Full output: https://paste.pythondiscord.com/ehuyovameb

hollow patrol
#

!e

import dis

def outer():
  x = 3
  def inner():
    nonlocal x
    y = x
    x = 3
    z = y
  return inner
f = outer()
def instruction(x):
  name = dis.opmap.get(int(hex(x), 16), "INVALID")
  ashex = hex(x)
  print(name, ashex)
  return name, ashex
print(list(map(instruction, f.__code__.co_code)))
night quarryBOT
#

@hollow patrol :white_check_mark: Your eval job has completed with return code 0.

001 | INVALID 0x88
002 | INVALID 0x0
003 | INVALID 0x7d
004 | INVALID 0x0
005 | INVALID 0x64
006 | INVALID 0x1
007 | INVALID 0x89
008 | INVALID 0x0
009 | INVALID 0x7c
010 | INVALID 0x0
011 | INVALID 0x7d
... (truncated - too many lines)

Full output: https://paste.pythondiscord.com/apipulitav

hollow patrol
#

huh?

haughty halo
#

guys, let's try to not flood this chat with evals

hollow patrol
#

alright

#

I'll use a repl then

haughty halo
#

thanks, either that or #bot-commands is okay

hollow patrol
#

np

#
LOAD_DEREF 0x88
STORE_FAST 0x7d
LOAD_CONST 0x64
POP_TOP 0x1
STORE_DEREF 0x89
LOAD_FAST 0x7c
STORE_FAST 0x7d
POP_TOP 0x1
LOAD_CONST 0x64
RETURN_VALUE 0x53```
#

I got it good

#
LOAD_DEREF 0x88
STORE_FAST 0x7d
STORE_DEREF 0x89
LOAD_FAST 0x7c
#

these are what we need

#

@formal sandal I think I know why I'm wrong now

#

we replaced the wrong codes

#

or I did

#

and it wasn't 0x74 but 0x7c

#

and not 0x75 but 0x7d

formal sandal
#

oh

hollow patrol
#

so if we try it now it should work

formal sandal
#

you really should use dis.opmap

hollow patrol
#

I did

#
import dis

opmap = dis.opmap

opmap = dict(zip(opmap.values(), opmap.keys()))

def outer():
  x = 3
  def inner():
    nonlocal x
    y = x
    x = 3
    z = y
  return inner
f = outer()
def instruction(x):
  name = opmap.get(int(hex(x), 16), "INVALID")
  ashex = hex(x)
  if name != "INVALID":
    print(name, ashex)
  return name, ashex
print(list(map(instruction, f.__code__.co_code)))
#

I should've used None over "INVALID" but it doesn't matter

#

!e

def parent_scope(f):
  f.__code__ = f.__code__.replace(co_code=f.__code__.co_code.replace(b'\x7c', b'\x88').replace(b'\x7d', b'\x89'))
  return f

def outer():
  x = 3
  @parent_scope
  def inner():
    x = 4
  inner()
  print(x)

outer()
night quarryBOT
#

@hollow patrol :warning: Your eval job has completed with return code 139 (SIGSEGV).

[No output]
hollow patrol
#

uh

#

that's weird

#

the reason is something to do with setting STORE_FAST to STORE_DEFER

#

actually no

#

it's something to do with the fact that i'm replacing bytecode i guess

#

I'm getting an IndexError: tuple index out of range

hollow patrol
#

!e

import dis
opmap = dis.opmap

def func_replace(**instructions):
  def inner(f):
    co_code = f.__code__.co_code
    for k, v in instructions.items():
      print(co_code)
      print(bytes([opmap[k]]), bytes([opmap[v]]))
      co_code = co_code.replace(bytes([opmap[k]]), bytes([opmap[v]]))
    print()
    f.__code__.replace(co_code = co_code)
    print('GENERATED CO_CODE', co_code)
    print('NEW CO_CODE', f.__code__.co_code)
    return f
  return inner

def outer():
  x = 4
  @func_replace(LOAD_FAST = 'LOAD_DEREF', STORE_FAST = 'STORE_DEREF')
  def inner():
    x = 24
  dis.dis(inner)
  inner()
  print()
  print('x =', x)

outer()
night quarryBOT
#

@hollow patrol :white_check_mark: Your eval job has completed with return code 0.

001 | b'd\x01}\x00d\x00S\x00'
002 | b'|' b'\x88'
003 | b'd\x01}\x00d\x00S\x00'
004 | b'}' b'\x89'
005 | 
006 | GENERATED CO_CODE b'd\x01\x89\x00d\x00S\x00'
007 | NEW CO_CODE b'd\x01}\x00d\x00S\x00'
008 |  22           0 LOAD_CONST               1 (24)
009 |               2 STORE_FAST               0 (x)
010 |               4 LOAD_CONST               0 (None)
011 |               6 RETURN_VALUE
... (truncated - too many lines)

Full output: https://paste.pythondiscord.com/ewejuyusem

hollow patrol
#

@formal sandal for some reason, .replace(co_code = new_co_code) won't work

#

I think I'm going to have to either set a new code object, or generate a new function

formal sandal
#

oh

#

code objects are immutable

#

so ```py
f.code = f.code.replace(co_code = co_code)

hollow patrol
#

oh

#
import dis
opmap = dis.opmap

def func_replace(**instructions):
  def inner(f):
    co_code = f.__code__.co_code
    for k, v in instructions.items():
      print(co_code)
      print(bytes([opmap[k]]), bytes([opmap[v]]))
      co_code = co_code.replace(bytes([opmap[k]]), bytes([opmap[v]]))
    print()
    f.__code__ = f.__code__.replace(co_code = co_code)
    print('GENERATED CO_CODE', co_code)
    print('NEW CO_CODE', f.__code__.co_code)
    return f
  return inner

def outer():
  x = 4
  @func_replace(LOAD_FAST = 'LOAD_DEREF', STORE_FAST = 'STORE_FAST')
  def inner():
    print('yay')
    print(x)
  #dis.dis(inner)
  print('its k time')
  #inner()
  print()
  print('x =', x)

outer()
#

what is going on?

#

for some reason

#

the nonlocal version

#

and the co_code replaced version

#

even though they have the same co_code

#

they still execute differently

formal sandal
#

they have different co_code and execute differently

hollow patrol
#
import dis
opmap = dis.opmap

def func_replace(**instructions):
  def inner(f):
    co_code = f.__code__.co_code
    for k, v in instructions.items():
      #print(co_code)
      #print(bytes([opmap[k]]), bytes([opmap[v]]))
      co_code = co_code.replace(bytes([opmap[k]]), bytes([opmap[v]]))
    #print()
    #print('GENERATED CO_CODE', co_code)
    #print('OLD       CO_CODE', f.__code__.co_code)
    #print("WANTED    CO_CODE", b'd\x01\x89\x00d\x00S\x00')
    f.__code__ = f.__code__.replace(co_code = co_code)
    return f
  return inner

def outer():
  x = 4
  @func_replace(STORE_FAST = 'STORE_DEREF')
  def inner():
    x = 3
  def other():
    nonlocal x
    x = 3 
  print(inner.__code__.co_code)
  print(other.__code__.co_code)
  #inner()
  print()
  print('x =', x)

outer()
#

not on my side

#

inner is the decorated

#

other isn't

#

and they both have the same co_code

#

other executes without error

formal sandal
#

Oh, wait

hollow patrol
#

inner has an error

formal sandal
#

of course they have the same code

hollow patrol
#

then why does only one work

formal sandal
#

the original function already accesses the nonlocal x

stark fable
#

there are other things on the code object other than co_code

hollow patrol
#

they're two different functions with the same code except one is replaced

#

yes, but I'm only changing the co_code

stark fable
#
>>> (lambda:x).__code__.co_code
b't\x00S\x00'
>>> (lambda:y).__code__.co_code
b't\x00S\x00'``` look, same code, why are they different??
hollow patrol
#

they access dif variables

#

but this code

#

they access the same variables

#
  @func_replace(STORE_FAST = 'STORE_DEREF')
  def inner():
    x = 3
  def other():
    nonlocal x
    x = 3 
#

and have the same co_code

#

dis.dis handles the second one just fine

#

but the first one raises an IndexError

stark fable
#

yeah of course it does, because there are things on the code object other than co_code and dis needs them to interpret the instructions into something human-readable

hollow patrol
#

but I'm not accessing anything else

stark fable
#

what

hollow patrol
#

everything else on the code object stays the same

#

except the co_code

stark fable
#

yeah exactly

#

you've changed the co_code and you haven't changed the rest of the code object to match it

hollow patrol
#

what would I change

stark fable
#

STORE_FAST accesses something in co_varnames, but STORE_DEREF accesses something in co_freevars

#

i think

#

other also has a closure

hollow patrol
#

alright

formal sandal
#

oh

#

that makes total sense.

#

Because otherwise where would it take closure variable names from.

hollow patrol
#

f.__code__ = f.__code__.replace(co_code = co_code, co_freevars = f.__code__.co_varnames)

#

This doesn't seem to work?

stark fable
#

well you still need the closure

rugged sparrow
#

@hollow patrol are you still trying to do try/except with maintained scope?

hollow patrol
#

@rugged sparrow yep

rugged sparrow
#

i might be able to help

hollow patrol
#

by modifying bytecode

#

my goal is to have a function

rugged sparrow
#

you dont need to mod bytecode

hollow patrol
#
def func_replace(**instructions):
  def inner(f):
    co_code = f.__code__.co_code
    for k, v in instructions.items():
      #print(co_code)
      #print(bytes([opmap[k]]), bytes([opmap[v]]))
      co_code = co_code.replace(bytes([opmap[k]]), bytes([opmap[v]]))
    #print()
    #print('GENERATED CO_CODE', co_code)
    #print('OLD       CO_CODE', f.__code__.co_code)
    #print("WANTED    CO_CODE", b'd\x01\x89\x00d\x00S\x00')
    f.__code__ = f.__code__.replace(co_code = co_code)
    return f
  return inner
#

then how?

#

I also don't want it to be version specific

#

and my goal is for a function parent_scope(FUNCTION)

rugged sparrow
#
_try = lambda t, *a, f=lambda a:a, e=Exception, **k,:(r:={}).pop(
    'r',
    type(
        '',
        (__import__('contextlib').ContextDecorator,),
        {
            '__enter__':int,
            '__exit__':lambda s,*a:isinstance(
                a[1], e
            ) and [r.update(
                r=f(a)
            )]
        }
    )()(t)(*a, **k)
)``` would this not work?
hollow patrol
#

that doesn't keep the parent scope

#

so I can't set variables in the parent scope

#

and I don't want to use a dict

rugged sparrow
#

!e ```py
_try = lambda t, *a, f=lambda a:a, e=Exception, **k,:(r:={}).pop(
'r',
type(
'',
(import('contextlib').ContextDecorator,),
{
'enter':int,
'exit':lambda s,*a:isinstance(
a[1], e
) and [r.update(
r=f(a)
)]
}
)()(t)(*a, **k)
)

x = lambda:((a:=1),_try(lambda:(a:=2)),a)
print(x())```

night quarryBOT
#

@rugged sparrow :white_check_mark: Your eval job has completed with return code 0.

(1, 2, 1)
rugged sparrow
#

ah damn

#

if you make the generated code handle its own scope you could do it

hollow patrol
#

nope, I'd like to use existing scopes

#

that way it can use := without managing a dict

rugged sparrow
#

thats gonna be way more difficult tho

hollow patrol
#

so what?

rugged sparrow
#

its also gonna make the produced code much more unstable

hollow patrol
#

how so?

#

and this is a one-linerizer, this code isn't meant to be too "stable"

rugged sparrow
#

wouldn't the goal be for the produced code to behave exactly as the original code did?

hollow patrol
#

yep

#

but a secondary goal is to keep it somewhat readable if you prettify it

rugged sparrow
#

which modding bytecode would not do lol

hollow patrol
#

how?

#

@rugged sparrow well then, is there any other way to maintain scope

#

the only idea I have is

rugged sparrow
#

use a scope dictionary

hollow patrol
#

other then that

#
[
  (
    ...
  )
  for error in catch_errors(FUNCTION)
]
#

but that just pushes it back

rugged sparrow
#

{'parent':{},'vars':{}} that sort of layout

hollow patrol
#

that would be less readable when prettifying

#

right now you can get stuff like

(
    (
        do_while := (
            lambda cond, c=0: (
                (((yield c), (yield from do_while(cond, (c + 1)))) if cond() else None),
            )
        )
    ),
    (x := 1),
    (y := 2),
    print((x + y)),
    None,
)[(-1)]
``` as an output
#

not as readable as python, but decent

rugged sparrow
#

you could yield exceptions pretty well using a context dec

hollow patrol
#

hold on

#

I have an idea

#

What if I emulate try using the decorator

#

but instead of handling execution in its body

#

I'll send out the context generator exception to the main scope

#

With some sort of generator

rugged sparrow
#

that should work. one sec, imma write a quick catch_errors

hollow patrol
#

however that gives me a new problem

#

how do I separate the context-decorator's exception yields from yields in the try or except blocks

#

like

try:
  x = '5' + 5
except:
  yield 3
rugged sparrow
#

one sec

hollow patrol
#

btw after we add try-except

#

try-except-else-finally

#

this makes adding returns, continues, and breaks possible

#
def x():
  try:
    try:
      for i in range(5):
        try:
          print(i)
        except ContinueError:
          pass
    except BreakError:
      pass
    return 5
  except ReturnError as e:
    return e.value```
rugged sparrow
#

!e ```py
catch_errors = lambda f, e=Exception:lambda *a,**k:(yield (r:={}).get(
'r',
type(
'',
(import('contextlib').ContextDecorator,),
{
'enter':int,
'exit':lambda s,*a:isinstance(
a[1], e
) and [r.update(
r=a[1]
)]
}
)()(f)(*a, **k))
)

print(*catch_errors(lambda:1/0)())```

night quarryBOT
#

@rugged sparrow :white_check_mark: Your eval job has completed with return code 0.

division by zero
rugged sparrow
#

that yields the exception or the func result

undone blaze
#

Can I ask a question about web scraping using Pandas?

rugged sparrow
#

wrong channel

undone blaze
#

Which channel should I use?

hollow patrol
#

!e

catch_errors = lambda f, e=Exception:lambda *a,**k:(yield (r:={}).get(
    'r',
    type(
        '',
        (__import__('contextlib').ContextDecorator,),
        {
            '__enter__':int,
            '__exit__':lambda s,*a:isinstance(
                a[1], e
            ) and [r.update(
                r=a[1]
            )]
        }
    )()(f)(*a, **k))
)()
night quarryBOT
#

@hollow patrol :warning: Your eval job has completed with return code 0.

[No output]
rugged sparrow
#

@hollow patrol that func takes in the try func, and a tuple of Exception types to catch

hollow patrol
#

oh

#

you used unpacking

#

@rugged sparrow how can you make it yield any exception?

rugged sparrow
#

remove the isinstance(a[1],e) and

hollow patrol
#

oh yeah

#

that doesn't avoid my scoping issue

rugged sparrow
#

ยฏ_(ใƒ„)_/ยฏ

hollow patrol
#

that handles exceptios

rugged sparrow
#

i dont really know how to best fix scoping

#

also youre not gonna want your try func to catch everything

hollow patrol
#

I do want it to

rugged sparrow
#

cause nested try/excepts

hollow patrol
#

that way it yields it

#

@rugged sparrow it catches everything that is in the criteria

#

and handles each thing differently depending on instance

#

then raising again otherwise if nothing detected it

rugged sparrow
#

scoping is always going to be an issue cause lambdas dont provide a good way to handle scoping

hollow patrol
#

all I want is a workaround to avoid scoping

#

like for whiles I avoided scoping by using a do_while generator

rugged sparrow
#

i dont know if there is a workaround

hollow patrol
#

varlist.__setitem__('x', 3) is so much less readable then x := 3

rugged sparrow
#

scope.update({'x',3}) or scope.setdefault({'x',3})

#

or create a simple scope cls with set and get

latent bronze
#

!e
x = 4

night quarryBOT
#

@latent bronze :warning: Your eval job has completed with return code 0.

[No output]
latent bronze
#

!e
print(f'coronavirus')

night quarryBOT
#

@latent bronze :white_check_mark: Your eval job has completed with return code 0.

coronavirus
latent bronze
#

!e return print('ok')

night quarryBOT
#

@latent bronze :x: Your eval job has completed with return code 1.

001 |   File "<string>", line 1
002 | SyntaxError: 'return' outside function
rugged sparrow
#

use #bot-commands

hollow patrol
#

@rugged sparrow the reason I'm so hesitant to create a custom scope is that it would mean I have to recursively look at every expression in the AST

#

just to find a name

#

and then convert the name to a dictionary attribute

rugged sparrow
#

that shouldnt be too bad

hollow patrol
#

and it'll look a lot more ugly

#

mapping.__setitem__('x', 1) isn't as nice to look at as x := 1

rugged sparrow
#

why are you doing mapping.__setitem__ instead of .setdefault

#

oh wait

#

setv, getv = (d:={}).__setitem__, d.get

#

just do that

#

obv needs more to do nested scoping

#

but you get it

hollow patrol
#

alright

gentle pagoda
#

can anyone explain why this happens? ```py

def foo(): print("hello world!")
...
foo2 = types.FunctionType(foo.code, {})
foo2()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 1, in foo
NameError: name 'print' is not defined
exec(foo2.code)
hello world!

#

oh i get it ```py

foo2 = types.FunctionType(foo.code, {"builtins": globals()["builtins"]})
foo2()
hello world!

formal sandal
#

You're welcome lemon_pleased

#

You can also mutate the function if you want.

foo.__code__ = foo.__code__.replace(...)
rugged sparrow
#
import inspect

def name(val):
    frame = inspect.currentframe()
    while (frame := frame.f_back):
        for k, v in frame.f_locals.items():
            if val is v:
                return k
formal sandal
#

Hm, I agree that this usage of := is probably clearer than

frame = inspect.currentframe()
for frame in iter(lambda: frame.f_back, None):
rugged sparrow
#

yea i really like := for loops like that

rugged sparrow
#

@zealous widget want to help me add switch to python? im gonna try to use a __build_class__ hook or a metaclass

zealous widget
#

i have a close solution already kind of, it was something else though

rugged sparrow
#

what was your solution?

zealous widget
#

i used a metaclass to bind functions to properties in a class def --- you could just change it from properties to something else

#
In [304]: def observer(instance, name, old, new):
     ...:     print(f'{name} from {instance} changed from {old} to {new}')
     ...: class Relay(Dispatcher):
     ...:     property_: observer

In [305]: Relay().property_ = 10
property_ from Relay(<property_=10, [observer]>) changed from None to 10

looks kinda like this

rugged sparrow
#

i mean like ```py
switch(val):
case 1:
<code>
break

zealous widget
#

yeah, you could do:

class Switch(switchcase):
    case_1: func1
    case_2: func2
rugged sparrow
#

that would be too easy

#
val = 1
class switch(val):
    case:1
    ##code
    'break'```
#

maybe like that

zealous widget
#

you could do it with a kwarg

#

class switch(case, val=val):

rugged sparrow
#

switches need multiple cases

zealous widget
#

yes, but you need to inherit from some class to get all the metaclass hacks

#

you can define the cases in the class body

rugged sparrow
#

im gonna hook __build_class__ and alter bytecode

#

replace LOAD_CONST 'break' with RETURN_VALUE and STORE_NAME 'ret' with RETURN_VALUE as well

#

i think it should work

zealous widget
#

i spent most of the day working on continuous range dict implementation

rugged sparrow
#

noice

crystal mica
#

Interesting!

rugged sparrow
#

bet i got basic switch working

#
>>> class switch(val):
...     case: 1
...     print(val + 1)
...     case: 2
...     print(val + 2)
...     ret = val
...     case: 'default'
...     ret = None
...
2
3
>>> switch
1
>>>```
#

fall thru works

#

and ret = {val} stores val into switch

snow beacon
#

Can you not use the return keyword in there?

rugged sparrow
#

it wont compile so sadly no

snow beacon
#

It might look cleaner to do switch = ... instead of ret.

rugged sparrow
#

true

hollow patrol
#

why not use []

#

hook into a metaclass with __getitem__

#

then do

#

or actually

#

make a switch class that takes in a single argument that hooks into __getitem__

#

and do

#
switch (value, none = lambda: print('nothing found')) [
  1: lambda: print('we got a 1'),
  2: lambda: print('we also got a two')
]
rugged sparrow
#

how would you specify to fall thru or return?

earnest wing
#

What about context managers? If you also use __iter__(), you can break seamlessly.

for s in switch(val):
  with s.case(1):
    ...
  with s.case(2):
    ...
    break
rugged sparrow
#

ohhhhhhh thats clever

earnest wing
#

It might not be possible to skip execution of a with block, though. Maybe by raising from within __enter__?

hollow patrol
#

@earnest wing It is, I've done it before

#

I made some code that turns a function into a context manager that receives a body

#

I think you have to use sys.settrace to raise an exception and catch it in __exit__

earnest wing
#

That is probably necessary, because __exit__ only suppresses exceptions raised during the body.

hollow patrol
#

yep

#

that's the only way

#

other then raising in the with

zealous widget
#
from collections import ChainMap

_name_to_cases = {}
class SwitchMeta(type):
    def __call__(cls, value):
        return _name_to_cases[cls.__name__][value]()

    def __prepare__(name, *args):
        cases = {}
        _name_to_cases[name] = cases
        def case(val):
            def deco(func):
                cases[val] = func
                return func
            return deco

        return ChainMap({}, {'case': case})

    def __new__(meta, name, bases, methods):
        methods = methods.maps[0]
        return super().__new__(meta, name, bases, methods)


class switch(metaclass=SwitchMeta): pass


class myswitch(switch):
    @case(1)
    def _():
        print(1)

    @case(2)
    def _():
        print(2)

    @case('a')
    def _():
        print('a')
In [425]: myswitch(1)
1

In [426]: myswitch(2)
2

In [427]: myswitch('a')
a
rugged sparrow
#

switches have fall thru tho

zealous widget
#

fall through what

#

change the __call__ to use get

rugged sparrow
#

like case 1: case 2: print(12) 1 and 2 both run print(12)

zealous widget
#

oh, you can double decorate

#
class myswitch(switch):
    @case(1)
    @case(2)
    def _():
        print(1)
rugged sparrow
#

like case 1: print(1) case 2: print(12) 1 and 2 both run print(12) while 1 runs both prints

zealous widget
#

oh, well dicts are ordered so that's not a problem either

#
class SwitchMeta(type):
    def __call__(cls, value):
        funcs = _name_to_cases[cls.__name__].get(value, (lambda: None, ))
        for func in funcs:
            func()

    def __prepare__(name, *args):
        cases = {}
        _name_to_cases[name] = cases

        def case(val):
            def deco(func):
                cases[val] = []
                for case in cases:
                    cases[case].append(func)
                return func
            return deco

        return ChainMap({}, {'case': case})
rugged sparrow
#

@earnest wing i liked your idea ```py
class switch:
def init(self, val):
self.val = val
self.cascading = False
self.default = True

def case(self, val):
    if val == self.val or self.cascading:
        self.cascading = True
        return True
    return False

def __iter__(self):
    yield self

for s in switch(3):
if s.case(2):
print(2)

if s.case(3):
    print(3)

if s.case(4):
    print(4)
    break

if s.default:
    print('default')
#

rn it can fall thru into default but that can be changed pretty easily

rugged sparrow
#

wait are you silencing exceptions with sys.settrace

brazen geyser
#

more or less

#

the heavy lifting is done by returning True in __exit__

rugged sparrow
#

thats clever tho

brazen geyser
#

it's based on an old troll implementation of goto iirc

zealous widget
#

i use yield:

    class myswitch(switch):
        @case(1)
        def _():
            print(1)
            yield

        @case(3)
        def _():
            print(2)

        @case('a')
        def _():
            print('a')
rugged sparrow
#

as a break?

zealous widget
#

yeah

rugged sparrow
#

nice

#

but can you return from within yours?

brazen geyser
#

it's not so much sys.settrace moreso than setting f_trace for individual frames btw

zealous widget
#

we could return

brazen geyser
#

though you need something in sys.settrace for that to work

rugged sparrow
#

frame.f_trace = self.skip yah im reading thru it rn

brazen geyser
#

there's another version that uses with case(b == 2): rather than with case(lambda a, b, c: b == 2):

#

just checking the bool value at the end

#

cant find it

#

been a while

#

vaguely remember there was one by @grave rover which i really liked and thought was really pretty

rugged sparrow
#

i wonder if it would be possible to actually add switch val: without modding cpython

zealous widget
brazen geyser
#

what does the value of yield do

#

oh i see

#

cool cool

zealous widget
#

i was working on the continuous range dicts, but now i could apply it to continous range cases

thin trout
#

Oh god not the nested metaclasses again haha

marsh void
#

I donโ€™t get why people are going with doing all of this if there is a simpler and cleaner way haha

#
# coding: cases

n = 13
switch n:
    case 1:
    case 2:
        n += 10
        break
    case 13:
        n = 0``` with some thought can be transformed to ```py
n = 13
while True:
    if n == 1 or n == 2:
        n += 10
        break
    if n == 13:
        n = 0
    break```
#

Solutions for cases I have seen are indeed fun, but this one to me seems to have the smallest overhead

proper vault
#

there is a lot of noise in the second snippet

marsh void
#

indeed there is, and it can be optimized

#

How does default work in switch though?

#

it runs if no cases were run, right?

proper vault
#

it is the label it jumps to if no case matches

marsh void
#

okay this one would be harder

#

simplest solution would be to say default = False in every case snippet

#

what I meant is on user end, switch will look nice and work just as expected

#

too bad tokens don't match expressions haha

earnest wing
#

@marsh void Because coding circumvents the fun of abusing the Python interpreter. Why else would #esoteric-python exist?

#

Oh, I think I've misunderstood. Still, this point applies.

marsh void
#

To me, this is what abusing python is

#
# cases.pth
import cases  # add encoding
import sys
sys.stdin.close()
sys.stdin = open(0, encoding="cases")``` @bitter iris showed me this and I was amazed, haha
grave rover
#

@brazen geyser sup

#

I remember using the current frame info to basically use jumps lol

proud glade
#

Python VM languages?

proper vault
#

Hy, dogelang and such I would assume

bitter iris
pine edge
#

if we had jump offset and jump bytecodes

#

you could make a jumptable in python bytecode

#

and then switches could be O(1) in some cases

#

but you can also implement that behavior with a list of lambdas

sick hound
#

@marsh void if you want a switch implementation here's one i made

def switch(s): 
    return lambda **a: a.get(s, a.get("default", bool))() or s != "default" and switch([*a][[*a].index(s) + 1])(**a) 

it allows for multiple case executions and default

pine edge
#

or import defaultdict

#

i don't know how you do multiple case executon

sick hound
#

recursion

#

(i also have an iterative version)

pine edge
#

how exactly do you stop multiple case execution

sick hound
#

boolean test on the case

#

you use it like that

test = "a" 
switch(test)( 
  b = lambda: "no", 
  a = lambda: print("hi"), 
  c = lambda: print("hello"), 
  d = lambda: not print("stop"), 
  default = lambda: print("default") 
)
``` or with functions, they can return a boolean or not
pine edge
#

makes sense

sick hound
#

(this will print hi, hello and stop)

pine edge
#

python goto when

sick hound
#

there is

#

goto module

pine edge
#

well fuck

#

that would make this look and feel like switches

sick hound
#

yes but i wanted to use no module, my iterative version uses itertools.takewhile tho, for performance reasons

pine edge
#

goto theoretically has no overhead

sick hound
#

there are some other way to optimize it already tho, like adding a counter but ye goto would be the better way

#

wanted to do it on one line too ^^

pine edge
#

this goto module rewrites bytecode

#

so it's basically undefined behavior across future versions and implementations

#

sad

#

nonetheless

#

since it's bytecode manipulation instead of c extension

#

you don't need a module

#

just write a goto

#

</s>

sick hound
#

i think a c extension exists

thin trout
#

That's all I have to say haha

#

On a more serious note, a goto in an higher language will have some overhead for sure, because of context switching mainly

stark robin
#

How does that introduce a context switch?

thin trout
#

If you leak the previous locals into the goto target you'll segfault at the speed of light

rugged sparrow
#

@pine edge those byte code instructions exist. We have JUMP_ABSOLUTE and JUMP_FORWARD

pine edge
#

very good

#

are there any circumstances under which those byte code are actually generated by the interpreter

#

or are they purely for shenanigans

rugged sparrow
#

jmp_absolute is used for while loops and maybe some for loops

#

I've never seen a jmp_forward generated, but I also don't disassemble every func I write

#

!e ```
import dis

dis.dis('while 1:pass')

night quarryBOT
#

@rugged sparrow :white_check_mark: Your eval job has completed with return code 0.

001 |   1     >>    0 JUMP_ABSOLUTE            0
002 |               2 LOAD_CONST               0 (None)
003 |               4 RETURN_VALUE
hollow patrol
#

also if I use a dict

#

then it won't show the vars in globals

#

so it won't work for importing it

thin trout
#

I've never seen a jmp_forward generated, but I also don't disassemble every func I write
disappointing haha

rugged sparrow
#

Where does jmp_forward typically show up?

proper vault
#
In [38]: dis.dis("if a: print(4)\nelse: print(5)")
  1           0 LOAD_NAME                0 (a)
              2 POP_JUMP_IF_FALSE       14
              4 LOAD_NAME                1 (print)
              6 LOAD_CONST               0 (4)
              8 CALL_FUNCTION            1
             10 POP_TOP
             12 JUMP_FORWARD             8 (to 22)

  2     >>   14 LOAD_NAME                1 (print)
             16 LOAD_CONST               1 (5)
             18 CALL_FUNCTION            1
             20 POP_TOP
        >>   22 LOAD_CONST               2 (None)
             24 RETURN_VALUE
```seems like skipping else branches of ifs
formal sandal
#

Maybe it would be a fun project to make a simple VM runtime in C.

#

Or in other low-level language like Go. But it's probably going to be less fun, since you won't get segfaults.

#

In general, SIGSEGV is much more fun to debug. A high-level language will give you a more or less helpful message on what went wrong. But with C, you'll have to conspire with an external tool like valgrind to start a long investigation.

#

And it's very rewarding to finally fix that null pointer dereferencing or off-by-one error.

brisk zenith
#

programming in rust is more fun than debugging segfaults unless the segfaults are from ctypes fuckery.

formal sandal
#

I refuse to believe that there's something more fun than a segfault.

edgy kelp
#

Fatal system errors produced by your program?

formal sandal
#

You might have a point there.

#

Segfault is like a punchline in a long joke. You've been working hard on your problem, and now you're ready to launch your masterpiece. But the act of you programming in C is just a part of a cruel irony set up by the computer. Filled with hope, you run your successfully compiled program. After running for a few seconds, it breaks down and displays a short error message, saying: "Haha, you failed".

#

The quarantine must have impacted me in a wrong way.

rugged sparrow
#

nah the most fun is when you segfault another program

brisk zenith
#

these are all lies

#

the most fun i've had is getting python to cause a SIGBUS from doing print("hello world!")

rugged sparrow
#

how did you manage to raise a SIGBUS?

#

with hello world

brisk zenith
#

i actually don't know, but it was after i did some messing around with memory-related stuff in ctypes

#

so perhaps the hello world was just the tipping point of stability

rugged sparrow
#

i bet if you interned "hello world!" and then derefed it

brisk zenith
#

well wouldn't that just be a segfault?

#

since even though it's dereferenced, it's still an addressable part of memory (otherwise how would it have been interned there in the first place)

rugged sparrow
#

Tbh I forget what causes a sigbus

#

ohhh so i need to change the interned string to point at the wrong addr

brisk zenith
#

not just a wrong address, but an address that doesn't physically exist

rugged sparrow
#

makes sense

formal sandal
#

On the last staff meeting I attended, I consistently received SIGBUS in my browser when pressing Ctrl+C

rugged sparrow
#

wut

formal sandal
#

I have no idea

#

Every time I pressed Ctrl+C, my tab would freeze. When I reloaded a tab, it displayed an error message complaining about SIGBUS.

rugged sparrow
#

thats bizzare