#esoteric-python
1 messages · Page 78 of 1
i feel like there's a more elegant way to do parenthesis but i haven't thought about it much
hmm, like scope += symbol == "("
that looks dope
For each index, you can get it's nesting depth by counting number of "(" - number of ")" before it in the string.
Idk is my method like that bad? lul
@marsh void [math] > print(__builtins__['exec']) <built-in function exec>
?
are you suggesting that as a possible hack/circumvention or a way of solving that problem or...?
To remove that thing lel
So basically I am trying to sanitize the input, right?
You have shown me that you can get access to functions from __builtins__, so I think there could be a line saying globals().pop('__builtins__') in the executor string
hmm
[math] > __builtins__['exec']
Invalid expression provided.
NameError: name '__builtins__' is not defined``` that does the trick, so uhm
try object.__subclasses__()[64].acquire.__globals__['__builtins__']['exec']
okay
and in 3.7 it's 75
!e ```python
print(1 .class.mro[1].subclasses()[75])
@distant wave :white_check_mark: Your eval job has completed with return code 0.
<class '_frozen_importlib._ModuleLock'>
yep
this feels like trying to prevent leaks from a sieve instead of using a funnel.
sanitizing the input would be modifying it to make sure it can't get where it shouldn't, you're just restricting what it can do
and there's a lot of restricting to do
nvm, doesn't work with operators
>>> ast.literal_eval('pi')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "C:\Users\Aaay\AppData\Local\Programs\Python\Python36\lib\ast.py", line 85, in literal_eval
return _convert(node_or_string)
File "C:\Users\Aaay\AppData\Local\Programs\Python\Python36\lib\ast.py", line 84, in _convert
raise ValueError('malformed node or string: ' + repr(node))
ValueError: malformed node or string: <_ast.Name object at 0x0000016778DD8470>```
exit.__setattr__("__code__",compile("exec('import __hello__')","","eval")),exit()```
Hm
quit does work though
oh right
which is the same thing
shouldn't you always account for the possibility that you missed something or someone can overcome your sanitization through some unforeseen exploit? aka the only sane way of doing this is full on sandboxing
doesn't matter how thorough you make the sanitization
I found an article talking about it when I was looking up a way to safely eval. I don't remember the url
[math] > __builtins__['__import__']('sys')._getframe(1).f_globals.__setitem__('get_dis', lambda _: '')
[math] > raise BaseException
Traceback (most recent call last):
File "calc.py", line 63, in <module>
main()
File "calc.py", line 52, in main
safe_exec(input('[math] > '))
File "calc.py", line 45, in safe_exec
f()
File "<string>", line 1, in _zH7JggrMBe
BaseException```
Okay so
I have just made it much more strict
Having __import__ in code, in any way or form is causing the error to be raised
As well as exec and eval; quit and exit are mocked with the same lambda that exit had
[math] > ().__class__.__base__.__subclasses__()[64].acquire.__globals__['__builtins__']['__imp' + (lambda: '')() + 'ort__']('sys')._getframe(1).f_globals.__setitem__('get_dis', lambda _: '')
[math] > raise ().__class__.__base__.__subclasses__()[64].acquire.__globals__['__builtins__']['BaseException']
Traceback (most recent call last):
File "calc.py", line 54, in <module>
main()
File "calc.py", line 44, in main
safe_exec(input('[math] > '))
File "calc.py", line 39, in safe_exec
f()
File "<string>", line 1, in _JOikomAtqn
BaseException```
Hahaha
Damn you are smart 
Is what we are doing idk, entertaining or it is getting tiring? I could continue for some more time, heh
'__imp' + (lambda: '')() + 'ort__'
also this is definitely entertaining (for us at least)
'__tropmi__'[::-1]
I could restrict __subclasses__ though

This is going to end at some point in time, right? haha
well actually we have to go now :(
but if you just spend some time trying to make a good sandbox, when we get back we can smash it to pieces in seconds try to break out of it
I'm still here for 15 minutes.
exit.__setattr__("__code__",compile("ex"+""[::]+"ec('im"+""[::]+"port __hello__')","","lave"[::-1])),exit()```Doesn't use `__subclasses__`
exit.__setattr__("__code__",compile(f"ex{''}ec('im{''}port __
hello__')","",f"ev{''}al")),exit()```Slightly clearer to read.
>>> 'icokwtmxhmbjptesnooyluparhordwttcihp'[::6]
'import'
it is more or less impossible to prevent all cases of string garbling
and that in itself should give you pause
"\N{LATIN SMALL LETTER I}mport"```
LOL
lol wtf is that
Escape sequence that evaluates Unicode names
You can also use more traditional hex escapes, binary escapes, that sort of thing
Y’all ever test your code? lol
Can you do it without using __? That's a possible ban case
block builtins and __ and I'm not sure how to break out
you can still do all kinds of garbled ways to get __
But if you can't use them in the code itself, it's harder to access attributes
INVALID_CODE = ('__', 'import_name'.upper(), 'raise_varargs'.upper(), 'exec', 'eval', 'breakpoint') ok so now we have this I think
Just block __ and builtins, honestly. That removes nearly everything..
Regardless, there are many things that aren't safe to allow, and you should use a tried and true well-built solution like snekbox
You can pip install from git
An example of stuff that seems innocous but would cause real problems:
bytearray(0x7FFFFFFF)
oh yep, that stuff
Yeah well, I’ve dropped my thing because obviously there are much better solutions
But it was fun while it lasted, lol
Oh this is interesting
what the H
!e ```python
it = 'abracadabra'
for _ in range(1000000):
it = filter(bool, it)
del it
print("Got here")
@distant wave :warning: Your eval job timed out or ran out of memory.
[No output]
!e ```python
it = 'abracadabra'
for _ in range(1000000):
print("s")
it = filter(bool, it)
del it
Odd
On my end it does this:
$ python3
Python 3.7.2 (default, Feb 12 2019, 08:16:38)
[Clang 10.0.0 (clang-1000.11.45.5)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>>
>>> it = 'abracadabra'
>>> for _ in range(1000000):
... it = filter(bool, it)
...
>>> del it
Segmentation fault: 11
Is that like the foo = foo.__call__ shenanigan?
It takes about 1.5 seconds to happen, so the 1s exec time limit on snekbox is probably ending it
Sortof
it's nastier
Iters within iters within iters
The deallocator overflows the stack
Put it in a function and watch people get confused when it goes out of scope.
ew.
just
ew
Speaking of segmentation faults, cefpython's javascript-python method binding structure is quite fragile. Give it a single, well-defined, locally-scoped function that dispatches, otherwise it gets very unhappy ;-;
I thought I could pass it lambdas. That turned out to be a poor decision ;-;
Can't you just compile Python to web assembly and bind to that?
@marsh void py [math] > getattr(getattr(getattr(getattr(getattr((), '_a_acalaaasasa_a_'[::2]), '_a_abaaasaea_a_'[::2]), '_a_asauabacalaaasasaeasa_a_'[::2])()[64].acquire, '_a_agalaoabaaalasa_a_'[::2])['_a_abauaialataianasa_a_'[::2]]['_a_aiamapaoarata_a_'[::2]]('sys')._getframe(1).f_globals, '_a_asaeataiataeama_a_'[::2])('get_dis', lambda _: '') [math] > raise ().__class__.__base__.__subclasses__()[64].acquire.__globals__['__builtins__']['BaseException'] Traceback (most recent call last): File "calc.py", line 54, in <module> main() File "calc.py", line 44, in main safe_exec(input('[math] > ')) File "calc.py", line 39, in safe_exec f() File "<string>", line 1, in _aNUDIMEQEh BaseException
:P
Is getattr in the scope?
yes
...apparently BaseException is too
[math] > getattr(getattr(getattr(getattr(getattr((), '_a_acalaaasasa_a_'[::2]), '_a_abaaasaea_a_'[::2]), '_a_asauabacalaaasasaeasa_a_'[::2])()[64].acquire, '_a_agalaoabaaalasa_a_'[::2])['_a_abauaialataianasa_a_'[::2]]['_a_aiamapaoarata_a_'[::2]]('sys')._getframe(1).f_globals, '_a_asaeataiataeama_a_'[::2])('get_dis', lambda _: '')
[math] > raise BaseException
Traceback (most recent call last):
File "calc.py", line 54, in <module>
main()
File "calc.py", line 44, in main
safe_exec(input('[math] > '))
File "calc.py", line 39, in safe_exec
f()
File "<string>", line 1, in _9orsK4obqI
BaseException```
(that very long first line disables the filtering so that we can do raise)
What's the point of env = {'abs': abs, 'sqrtre': sqrtre, 'sqrt': sqrt, 'e': e, 'pi': pi, 'i': sqrtre(-1), 'exit': exit_mock, 'quit': exit_mock} if you can access anything you want?
well you can't access exit and quit since they're shadowed
[math] > globals()['_a_abauaialataianasa_a_'[::2]]
Invalid expression provided.
KeyError: '__builtins__'``` and `__builtins__` is gone
But everything else is still there?
yes
That would have made it much easier to break if I'd known that.
yeah actually our method can be a bit shorter
[math] > getattr(getattr(getattr(object,'_a_asauabacalaaasasaeasa_a_'[::2])()[64].acquire,'_a_agalaoabaaalasa_a_'[::2])['_a_abauaialataianasa_a_'[::2]]['_a_aiamapaoarata_a_'[::2]]('sys')._getframe(1).f_globals,'_a_asaeataiataeama_a_'[::2])('get_dis',lambda _:'')
[math] > raise SystemExit```
and we could probably also do something better with the __ stuff
anyway gtg now bye
The solution to sanitise code like this is to ban iterable slicing. Then everything will be safe.
chr(65)+chr(66)
Come to think of it, why not just use ast.literal_eval from the beginning and then add the functions you want
A blacklist method just won't work
I prefer the custom bytecode interpreter idea, but there are a few gotchas with it.
Actually, why not just write a parser?
Refactoring my bytecode optimizer, any ideas on how I should handle jumps?
Right now I just remove opcodes
And I somehow broke it again reee
def f():
x = 1
b = 2
if x:
x = 2
y = 2
return y + 1
``` ```
40 0 LOAD_CONST 1 (1)
2 POP_JUMP_IF_FALSE 12
41 4 LOAD_CONST 2 (2)
6 LOAD_CONST 1 (1)
42 8 BINARY_ADD
10 RETURN_VALUE
43 >> 12 LOAD_CONST 0 (None)
14 RETURN_VALUE
making progress
fuck my optimizer doesn't check for usage in nested blocks
a = lambda: b
b = 6
a()```
Isn't dynamic scope great?
The downside is that the bytecode can differ depending on the context
At top level this would evaluate to using LOAD_CONST 6 STORE_NAME b
In a function body it'd be LOAD_CONST 6 STORE_FAST b
But in a function body with b defined at top level it'd be LOAD_CONST 6 STORE_NAME b again
Speaking of bytecode
I can now optimize every module by hijacking the import
And I just fixed varnames, sweet
did I kill this channel
idk
What is dead may never die.
season 8 disagrees
challenge for people. write Hello World to stdout without importing anything or print or input
del __builtins__.__import__
del __builtins__.print
del __builtins__.input```
Is site already imported?
whoops forgot about input
is that even possible without importing stuff
I'm guessing it involves some crazy dunder stuff or something
isnt there some vague way to get the sys module without importing?
it's stored in some builtin list somewhere
sys = next(
getattr(c, f).__globals__["sys"]
for c in ().__class__.__base__.__subclasses__()
for f in dir(c)
if isinstance(getattr(c, f, None), type(lambda: None))
and "sys" in getattr(c, f).__globals__
)
sys.stdout.write("Hahah")
yes there is
oh wow
nice
looping thru all subclasses of object and looking for non-builtin functions to grab the globals off them
:D
disclaimer: I did not originally write this
I just make it a nice single statement
how about just (lambda: None).__globals__['sys'].stdout.write('Hello World\n')
i tested it
i did too
challenge: make a hello world using the least unique characters, without using any of the chars in Hello, World!\n
oh right, shouldnt be in IDLE
what
i tested it in the IDLE REPL
oh
well, it seems to work outside of the REPL too
yea you gotta reach into a function that has it in scope
where did you test it
python 3.6.1 repl on windows 10
oh wait, im a moron. thought i commented out all lines in this file but there was one at the top in grey i didnt notice
can you guess the content of this line 🙂
bingo
@gilded orchid could you elaborate a bit more on what you mean by using the least unique characters?
oh. literally least number of unique characters.
no im just very tired 😅
@gilded orchid Does this count?
print("".join(map(lambda c:chr(ord(c)-13),"Uryy|9-d|\x7fyq.\x17")))
um
it looks like it does
though it does have a , and I said no chars from Hello, World! (if I'm being picky)
wasnt sure if your character restriction applied to the string or source
if its the whole source it definitely doesnt count
could fix that with hex obfuscation, but i'd rather play sniper elite
WHAT I WANT:
lambda: (
x = 0
while x < 6:
x += 1
yield x
)```
WHAT I GET:
```python
func(lambda v: (
setattr(v, x = 0),
(yield from during(lambda v: v.x < 6, lambda v: (
setattr(v, x = v.x + 1),
(yield v.x)
)))
))```
I got the 2nd one to work
The 1st one (sadly) isn't valid Python 😦
ayy bruh have you seen pyskell
nope
its alll valid python
lemme dig up a few examples
import demo
include %"to_import"
include [sys]
class Main(main):
from Imported import add3
from Sys import PYSKELL_VERSION
main : IO()
main | (
print( "Hello, World!"),
print("Pyskell version", PYSKELL_VERSION),
print( add3( 5))
)
Functor/fmap impl demo
def trait(Functor: f):
fmap : Func(a, b).f(a).f(b)
def data(Maybe: a):
Just(a),
Nothing
def instance(Functor: Maybe):
fmap(func, Just(val)) | Just( func( val))
fmap(func, Nothing) | Nothing
main | (
data := Just(5),
print( fmap( add( 3), data)),
)
It looks like valid Python to me
oh, syntax yea
I don't get how it doesn't have any import at the top
It needs some import to load the code and parse the AST and rewrite it
func(lambda x, y, z: '''while True:
print(x)
print(y)
print(z)
''')```
oh
but that seems even worse then my previous one
yea tbh
func(lambda v: (
during (lambda v: True, lambda v: (
print(v.x),
print(v.y),
print(v.z)
))
))```
that's what i have
so
i have two anonymous function choices
my anony
or my lambdatools
anony looks better, but can't support generators
lambdatools looks worse, but has more flexibility
@pure dew you're probably right
but i really wish we had better lambda support 😦
whenever i try myself i end up making #esoteric-python
python isn't really a functional language at all
I try to keep everything pythonic and I don't find myself missing good lambdas too much
but i do prefer functional languages
Haskell 😩
The main Scheme features I miss are tail-call elimination and not having to import foldr a.k.a. reduce.
Without those, my code barely functions.
maybe try writing python instead of scheme then /s
i think the reduce in functools is foldl
as for tco there's https://github.com/baruchel/tco but idk how well it works
and it looks kinda janky to work with
https://github.com/Bogdanp/tcopy this one looks easier to use but been ages since an update
I can rewrite my algorithms to work around python's flaw.
Trampolines, iteration etc
Dynamic programming is harder than tail calls, but it's probably for the best to use that too.
idk if it's very fair to characterize it as a flaw, rather than a different approach.
guido explains here at length why he considers it unpythonic: http://neopythonic.blogspot.com/2009/04/tail-recursion-elimination.html
the reasoning seems sound to me.
another thing i remembered: i think Stackless Python might have TCO and is currently up to 3.7 so you could check that out.
according to wiki: In practice, Stackless Python uses the C stack, but the stack is cleared between function calls.
sounds like TCO would be a natural consequence of this, but im not sure.
oh nice looks like they have a 3.8 beta release too
I could probably write TCO for python
it'd save a bunch of cycles because it's just a jump rather than PyObject_Call
what about non self calls tho
Is that the thing you are all playing at ? https://www.codingame.com/multiplayer/clashofcode
i mean howre you gonna do non self calls with just a jump
thats a self call
tail calls dont necessarily have to recurse
so that could be another function, y()
def x():
...
return y() # LOAD_NAME(y) CALL_FUNCTION```
just as long as you know you no longer need the stack for x, you can perform the optimization
thats not gonna be optimized
itll add another frame
no way to optimize that in just bytecode
unless you get the function at compile time and embed it
resulting in more memory usage
not necessarily. you could add all the frame cleanup bytecode right there. it would be messy and very involved. but doable.
there's one alternative which is literally moving the IP to the start of y but that requires a lot of ctypes hacking
@grave rover, it looks like you tried to attach a Python file - please use a code-pasting service such as https://paste.pythondiscord.com/ instead.
@brazen geyser @snow beacon would you guys mind testing some code with this? to enable it on imports: ```py
import sys
import dis
from importlib._bootstrap_external import FileFinder, SourceLoader
from bytecode_optimizer import optimize_code
class ByteOptimizer(SourceLoader):
def init(self, *args):
self.module, self.path = args
def get_filename(self, fullname):
return self.path
def get_data(self, path):
print(self.module, self.path)
with open(self.path, "rb") as fp:
return fp.read()
def source_to_code(self, data, path='<string>', **kwargs):
code = SourceLoader.source_to_code(self, data, path)
excluded_modules = ("six",)
if b"# no-optimize" not in data and not self.module.startswith("_") and self.module not in excluded_modules:
# Don't optimize python internals or files marked with `# no-optimize`
code = optimize_code(code)
return code
@classmethod
def enable(cls):
loader_opts = [cls, [".py"]]
sys.path_hooks.insert(0, FileFinder.path_hook(loader_opts))
for k, v in sys.path_importer_cache.copy().items():
if isinstance(v, FileFinder) and ("python3" not in v.path or "site-packages" in v.path):
# Don't modify stdlib
del sys.path_importer_cache[k]```
it's a negative check
wait no even I'm getting confused
wait no yes I was right
You should really prefer early returns >:(
how so
also it's not supposed to optimize itself since it only runs at application start
@wind maple my point was that this file contains # no-optimize, so it won't be optimized.
oh 
ive got both bytecode_optimizer.py and this ByteOptimizer class in separate files
now am i supposed to make a third file, import ByteOptimizer, call its enable method, then import a function from somewhere else?
@grave rover
uhhh
kinda
lol
structure wasn't well thought out
I use it like this:
# main.py
from import_optimizer import ByteOptimizer
ByteOptimizer.enable()
import entrypoint
entrypoint.main()
I recommend disabling the TCO flag though, it doesn't seem to like kwargs just yet
making a repo for this soon
i made a nick name maker, you just pit in your name and get a new one out, any ideas for improvement?
class BoopBoop():
def BorpBif(BepaBip, BupBup):
BapBif = BepaBip
Bip = ""
BopBip = Bip.join(BapBif)
BepBid = "urgle"
BufBip = (BopBip+" "+BupBup+BepBid)
print(BufBip)
def Bobbup(Blup):
BupBup = Blup
BefBip = {
"BabBab":"a", "BadBab":"b", "BabBap":"c", "BabBad":"d",
"BebBeb":"e", "BedBeb":"f", "BedBep":"g", "BebBed":"h",
"BibBib":"i", "BidBib":"j", "BidBip":"k", "BibBid":"l",
"BobBob":"m", "BodBob":"n", "BodBop":"o", "BobBod":"p",
"BubBub":"q", "BudBub":"r", "BudBup":"s", "BubBud":"t",
"BaabBaab":"u", "BaadBaab":"v", "BaadBaap":"w", "BaabBaad":"x",
"BoobBoob":"y", "BoodBoob":"z", "BoobBoop":" "
}
BepaBip = (BefBip["BoobBoob"],BefBip["BodBop"],BefBip["BaabBaab"],BefBip["BudBub"],BefBip["BoobBoop"],
BefBip["BodBob"],BefBip["BabBab"],BefBip["BobBob"],BefBip["BebBeb"],BefBip["BoobBoop"],BefBip["BibBib"],BefBip["BudBup"])
BoopBoop.BorpBif(BepaBip, BupBup)
def BipBop(BaapBip, Bup):
BupBeep = (BaapBip*Bup)
BepBep = (''.join(sorted(BupBeep)))
Blup = (BepBep[len("ba")]+BepBep[len("Boof")])
BoopBoop.Bobbup(Blup)
def BopBid():
Bup = len("Bap")
BoopBip = "BabBoop>>>"
BaapBip = input(BoopBip)
BoopBoop.BipBop(BaapBip, Bup)
if __name__ == '__main__':
BoopBoop.BopBid()
do you mean make-it-better improvement or make-it-more-esoteric improvement
if you want it to be actually better then don't ask here because this is not the right channel for that advice
if you want it to be more esoteric, then this is the perfect place to ask :)
lol it's like a 5 year old used text to speech to make the identifiers 😂
phonetic variables... someone needs to code that up, sound/click driven coding for the blind
im thinking i need to pay a singer to scat sing my code
and then i upload that to github and call it open source
but yes better ways too add on to its... esotericness?
def BoobBob(Bap,Bup,Beb=0):
if not((Beb*3-Beb<<1-Beb)or Bup):
return Beb
Boomb,*Brump=Bup
return BoopBoop.BoobBob(Bap,Brump,-(-Bep-1))```
Replace len with this.
that is amazing @formal sandal
haha
heres a challenge
make an esolang
that can be played as a (kinda) pleasant music file
or audio file
and also run as a thing
its not a proper challenge but sounds interesting
yeah velato basically just is that
So that in addition to the despair you feel when reading the code you wrote a few months ago you could also listen to black metal?
does someone have a example of what hello world sounds like?
Enjoy the videos and music you love, upload original content, and share it all with friends, family, and the world on YouTube.
It's linked to on the page.
I don't think it's related to Python though.
that needs a REPL
That doesn't seem very hard.
If you don't want to mutate the original decorated function it'd be slightly harder.
is it on GH/GL?
not yet
gonna clean up a bit
I posted a pastebin of an old version earlier this week tho
tf is .snekrc
Snekchek
Challenge: get this to work```python
a, b = var_length()
a, b, c = var_length()
a, = var_length()
whats var_length @snow beacon ?
It's a function for you to define
It should return an iterable, of course.
The length of the iterable is the important thing, because all three of the cases require a different length.
ohh variable length i see
without diving into real deep, i'll say this
you can unpack a variable length sequence/iterable by tacking a star on one of the assigners ex. a, b, c, *d = range(10)
also, it doesnt have to be on the end
a, *b, c, d = range(10) works just as well
little disappointing, but expected i suppose https://paste.pythondiscord.com/fikuqeforu.py
slice indexing is faster, but not as cool
I was hoping some devious coder could make a function that alters the length of its return value based on what the result is assigned to.
wew
that'd be some wacky stackframe shit
but what if you just return the function instead of assigning it
This is #esoteric-python after all...
should be doable
from dis import opmap, stack_effect
from functools import wraps
from inspect import stack
def var_length(func):
@wraps(func)
def inner(*args, **kwargs):
code = stack()[1].frame.f_code
pos = stack()[1].frame.f_lasti
ops = list(zip(code.co_code[::2], code.co_code[1::2]))
op = ops[int(pos / 2)+1]
try:
effect = stack_effect(op[0], op[1])
except ValueError:
try:
effect = stack_effect(op[0])
except ValueError:
effect = 1
if op[0] == opmap["UNPACK_SEQUENCE"]:
nargs = op[1]
elif effect < 0:
nargs = -effect
else:
nargs = 0
return func(nargs, *args, **kwargs)
return inner
there
@snow beacon how's this
note: mostly untested
@var_length
def zero(n):
if n > 1:
return [0] * n
if n == 1:
return 0
a = zero()
b, c = zero()
d, e, f = zero()
assert a is b is c is d is e is f is 0
``` this works
cc @brazen geyser @pure dew you guys would like this too
noice
alternatively:
def yielding(func):
iterable = func()
@wraps(func)
def inner(n):
buffer = []
while len(buffer) < n:
buffer.append(next(iterable))
if n > 1:
return buffer
if n == 1:
return buffer[0]
return var_length(inner)
@yielding
def some_generator():
x = 0
while True:
yield x
x += 1
a = some_generator()
b, c = some_generator()
d, e, f = some_generator()
assert (a, b, c, d, e, f) == (1, 2, 3, 4, 5, 6)
I feel like you could replace that buffer thing with islice
oooh
islice doesn't like generators though @wind maple
wdym
it's designed for iterators
>>> def gen():
... while True:
... yield 1
...
>>> g = gen()
>>>
>>> itertools.islice(g, 3)
<itertools.islice object at 0x000001F9AAFD07C8>
>>> list(_)
[1, 1, 1]```
where do you define stack and stack_effect tho
tldr if you need to work with opcodes, dis is your friend
i've never used it for more than pretty printed disassembly before
def is_even(n):
return eval('-'*n + '1') > 0```
yeah but this is #esoteric-python not #actually-useful-python
true
@sick hound
f = lambda n: bool(type(n).__neg__(True.__rand__(n))+True)
better?
yeah that's definitely more obfuscated and esoteric
even better now
__rand__ sounds like something to do with random numbers but it's actually just a version of &
yep
Nice work on the function, Martmists. It's surprisingly modularised even, despite most code this channel sees being golfed.
def is_even(num):
try:
eval("'"*int(str(num)[-1]))
return True
except:
return False``` @sick hound my personal favorite
bare except uwu
lol no else block
bruh
@snow beacon I could golf it some more (hell, I could just write manual bytecode) but this is clean and understandable
is_even=lambda i:not (lambda f,x,n: f(f,x,n))((lambda g,y,o: g(g,y-1,~o) if y else o),i,0)
Let’s make 2+2 return 5 
If you can assign 2.5 to 2, you’re golden
or just assign 5 to 4
Not sure if it would work
chronos@localhost ~ $ pip3 install forbiddenfruit
Requirement already satisfied: forbiddenfruit in /usr/local/lib/python3.8/site-packages (0.1.3)
chronos@localhost ~ $ python3
Python 3.8.0 (default, Oct 18 2019, 01:12:04)
[GCC 8.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from forbiddenfruit import curse
>>> curse(int, '__add__', lambda a,b:5)
>>> 2+2
5
>>> ``` @marsh void
Of course..
>>> from forbiddenfruit import curse
>>> curse(int, '__add__', lambda a,b: 5 if a == b and a == 2 else a + b)
>>> 2+2
5```
@marsh void ^
(Haven’t tried tbh)
thats calling add again
>>> from forbiddenfruit import curse
>>> intadd = int.__add__
>>> curse(int, '__add__', lambda a,b: 5 if a == b and a == 2 else intadd(a, b))
>>> 2+2
5```
Oh I know
Like this?
yeah
else a - (-b)
i was just about to post that

if a==b==2
fb.curse(int, '__add__', lambda a,b: 5 if a==b==2 else a.__radd__(b))
2+2
Out[5]: 5
2+3
Out[6]: 5
3+1
Out[7]: 4```
because no-one likes making variables
smart
dont think it gets any shorter:
fb.curse(int,'__add__',lambda a,b:5if a==b==2else a.__radd__(b))
who cares about speed
fb.curse(int,'__add__',lambda a,b:5if a|b==2else a--b)
1 char less hehe
uhoh
eheh
is there a way to put the original add function inside the function
lambda a,b: original_add(a,b) if a==b==2 else 5 in some form
yeah
original_add = int.__add__
before the curse
but then its nolonger one line
Hey I posted this stupid solution 😄
Guys, I want to do weird things. You know any resource to get started at being esoteric?
@thin trout there isnt really a resource
just look for unreadable code you've written and make it worse
Hun.
@grizzled cloak will that work? int.add is just a slot wrapper, are you sure it doesn't end up invoking the new one recursively?
Yes it creates a copy I guess
Curse actually replaces the function with some fancy c hooks
Another one liner (for the function):python (lambda original_add: lambda a,b: original_add(a,b) if not a==b==2 else 5)(int.__add__)
can you overwrite __eq__ with forbiddenfruit?
dont think so
If you do, make sure to also overwrite __hash__, otherwise Python will not work properly. Although, to be fair, you're already using forbiddenfruit, so that probably doesn't matter.
it spat error messages at me
this channel is a fever trip
Eval run in NsJail, trust me, you can't break out of this thing
Here is a little schema of the eval flow https://github.com/python-discord/snekbox#snekbox
I don't think anyone every break out of NsJail
I googled a bit and there was a technic, but it required very low level access that only C provide
fb does create C hooks, don't it?
Maybe, but the breach has been patched very quickly
fascinating
i still wouldnt trust it on my server tho
guess thats why they use docker
I mean, breaking out of a container is easy
They aren't designed to protect from inside attacks
As NsJail is done for it
Oh well, it is designed by google
I had a slight problem today...
There is a Coord class with fields width, height, and offset.
def __contains__(self, point):
(offset_x, offset_y) = self.offset
(x, y) = point
x_inside = (0 <= x-offset_x < self.width)
y_inside = (0 <= y-offset_y < self.height)
return (x_inside, y_inside)
Can you spot the bug? :-)
Why doesn't this throw an error?
||It's converting a tuple to a boolean. Since the boolean isn't ever empty, it's true.||
Well, yeah.
Huh thought it would type error or something. Guess it converts if it can. Just tried implementing __len__ as return True and yep it returns 1.
I don't understand why this is allowed.
However, returning a non-boolean value from __bool__ will throw an error.
That conversion made me remember Javascript again...
Well that's interesting and inconsistent
Have to try all the dunders now
I think this is a very bad thing for exactly the same reason it is bad in JS.
You find an element like <div id="#undefined">
And you have no idea where the error is
Test.__len__ = lambda s: True #fine
Test.__length_hint__ = lambda *_: True #fine
contains, fine
TypeError: __bool__ should return bool, returned int
TypeError: __str__ returned non-string (type int)
TypeError: __repr__ returned non-string (type int)
eq/lt/gt etc also can return anything but that's mentioned in docs and in comparisons bool() will be called anyway
it does sorta make sense, as every value is truthy or falsey in python and you may want to return a tuple, which, if empty, means false, else true
Seems way too implicit. (False, False) becoming True, especially in a contains method seems very unintuitive to me
how
any non-empty tuple is true
It would be even more confusing and more implicit if it did type checking and returned the result of any on an iterable
same for lists, sets, dicts
contains is the form of a verb that asks, I don't know the english word for it
It should just TypeError like the rest of the methods
As for the truthy falsy business, well I just don't like it in general (in any language). I always have to stop and think what counts as true, whereas the dev could just spend 2s explicitly saying what they're checking for
I agree
The list of things that are considered false are very intuitive
And this allows you to not write the same piece of code time and time again
Clearly naming is also a part of whether something is readable
Hmm not sure about that. Did a quick test e.g. bool(nan) is True, while in a different language, say JS it's false. Add to that the fact that you can define bool yourselves. Maybe you get used to it over time but when I was getting started it was definitely not an intuitive thing.
http://hyperpolyglot.org/ this is also interesting, there's a section on falsehoods. Seems every language has their own idea of it. Also another thing I thought of, return code 0 is success but 0 is falsy in just about every lang. Whole thing just seems so convoluted.
well the return codk is a posix thing
Sure, maybe not 100% relevant to bring up but just another little snag
what else could I make my library optimize 🤔
Inline short functions? Idk how doable that is and what you've already done
maybe replace things with generators whenever possible. It may not be viable though
The IEEE standard does not define a truthiness value for NaN
And it's also strictly not equal to any other numeric value, including 0
and since the truthiness in python for numerics are defined solely by zero
NaN being truthy is a fairly consistent choice
Technically it's an illegal conversion as there's no legal conversion to a numeric from NaN
because someone asked for it:
import math;f=lambda n:[print(x)for x in[' '.join([str(y*x).rjust(int(math.log10(n*n)+1))for y in range(1,n+1)])for x in range(1,n+1)]]```
multiplication table until n
f=lambda n:[print(x)for x in[' '.join([str(y*x).rjust(int(__import__('math').log10(n*n)+1))for y in range(1,n+1)])for x in range(1,n+1)]] at least make it a true one liner
Heheh
also, whu not do len(str(n*n))
Thats too simple
alright, how about this then (lambda z: (lambda f,v,a: f(f,v,a)) (lambda f,v,a: f(v//10,a+1) if v else a) )(n*n)
lambda x:[print(*[f'{i*n:>3}'for n in range(1,x)])for i in range(1,x)]
With walrus:
lambda x:[print(*[f'{i*n:>3}'for n in y:=range(1,x)])for i in y]
and to keep the spacing scaling:
lambda x:[print(*[f'{i*n:>{len(str(x*x))}}'for n in range(1,x+1)])for i in range(1, x+1)]
That has a bug
And fixed with -2chars
And again with +4, sigh
🙂
This seems right at least
:=
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
2 4 6 8 10 12 14 16 18 20 22 24 26 28 30
3 6 9 12 15 18 21 24 27 30 33 36 39 42 45
4 8 12 16 20 24 28 32 36 40 44 48 52 56 60
5 10 15 20 25 30 35 40 45 50 55 60 65 70 75
6 12 18 24 30 36 42 48 54 60 66 72 78 84 90
7 14 21 28 35 42 49 56 63 70 77 84 91 98 105
8 16 24 32 40 48 56 64 72 80 88 96 104 112 120
9 18 27 36 45 54 63 72 81 90 99 108 117 126 135
10 20 30 40 50 60 70 80 90 100 110 120 130 140 150
11 22 33 44 55 66 77 88 99 110 121 132 143 154 165
12 24 36 48 60 72 84 96 108 120 132 144 156 168 180
13 26 39 52 65 78 91 104 117 130 143 156 169 182 195
14 28 42 56 70 84 98 112 126 140 154 168 182 196 210
15 30 45 60 75 90 105 120 135 150 165 180 195 210 225
lambda x:[print(*[f'{i*n:>{len(str(x*x))}}'for n in y:=range(1,x+1)])for i in y]
There ye go
80 chars
lambda x:[print(*(f'{i*n:>{len(str(x*x))}}'for n in y:=range(1,x+1)))for i in y]
slightly reduced ram consumption :P , maybe. Now makes an intermediate generator instead of list
hm, I can't actually test on 3.8, that y and y:= might need to be swapped
idk
Sometimes I wish for a kind of "map" expression, that doesn't require handling lambdas
something like, map(f'{x}', [1, 2, 3])
can be made
oh?
You'd need to put it in a string, I'd bet. Either that or you'd need to do some sort of symbolic computation, which would get messy.
expression_map(1/isinstance(x, type(...)), [1, 2, "foo"]) would need to be coded pretty cleverly to work out of the box.
lambda x:[print(('{:4}'*x).format(*range(i,i*x+1,i))) for i in range(1, x+1)]
is this shorter?
@snow beacon whats with the 1?
@pure dew raise if isinstance return False (I think)
well it would yea
I'm wondering about the reason he did that
cus it would end up as 1/0
That's the point. If x isn't an Ellipsis it'll raise an error.
That sort of code would be difficult to support.
But the error depends on what list you give it.
what did you think it was @pure dew
I mean
It's python on the JVM
But better than Jython since we're planning on exposing jvm objects to it
async def nick(ctx,member: discord.Member,arg):
await member.nick(arg)```
Whats wrong with this?
It is #esoteric-python , not even #async-and-concurrency , not to mention that we have #discord-bots
Oh, I see you were kind of ignored in discord-py channel, so let me write it down here:
member.nick returns the nickname of a member, so what you have in your function will error, saying that string is not callable.
If you wish to change member's nickname, there is a method member.edit(*, reason=None, **fields. So, your code will look somewhat like:
async def nick(ctx, member: discord.Member, *, nickname):
await member.edit(nick=nickname)``` @sick hound
kek
grade = 'C'
# Instantiate a switchcase called case that iterates over cases in the order
# that they're inserted.
with Switch(grade) as case:
# Calling case.Break() stops other cases from being evaluated.
case['A'] = (lambda value: print(f"Good job, you got an {value}!"), case.Break())
case['B'] = case['A']
case['C'] = lambda value: (print(f"Not bad! You got an {value}!"), case.Break())
case['D'] = lambda value: (print(f"You received an {value}."), case.Break())
case['F'] = case['D']
# Case.default will run if it's defined and no other cases are ran.
case.default = lambda value: print(f"Error: Unknown grade {value}")```
Thoughts on this syntax for switch-cases? I think it should be pretty easy to program a class called Switch that has this behavior.
class Switch:
def __init__(self, value):
self.value: Hashable = value
self.conditions: Dict[Hashable, Callable] = OrderedDict()
self.default: Optional[Callable] = None
# Defining in __init__ should allow more interesting logic for
# nested switch cases?
class BreakException(Exception):
pass
class Break:
def __init__(self, *args):
raise BreakException(*args)
self.BreakException = BreakException
self.Break = Break
def __enter__(self):
return self
def __setitem__(self, condition: Hashable, func: Callable):
self.conditions[condition] = func
def __getitem__(self, condition: Hashable) -> Callable:
return self.conditions[condition]
def __exit__(self, exc_type, exc_val, exc_tb):
condition_met = False
try:
for case, func in self.conditions.items():
if self.value == case:
condition_met = True
func(self.value)
except self.BreakException:
return
if not condition_met and self.default is not None:
self.default(self.value)```
ah right comparisons... Hmm
maybe like
case[lambda value: value > 5]
from collections import OrderedDict
from typing import Hashable, Dict, Callable, Optional
class Switch:
class Expression:
def __init__(self, expression: Callable):
self.expression = expression
ex = Expression
def __init__(self, value):
self.value: Hashable = value
self.conditions: Dict[Hashable, Callable] = OrderedDict()
self.default: Optional[Callable] = None
# Defining in __init__ should allow more interesting logic for
# nested switch cases?
class BreakException(Exception):
pass
class Break:
def __init__(self, *args):
raise BreakException(*args)
self.BreakException = BreakException
self.Break = Break
def __enter__(self):
return self
def __setitem__(self, condition: Hashable, func: Callable):
self.conditions[condition] = func
def __getitem__(self, condition: Hashable) -> Callable:
return self.conditions[condition]
def __exit__(self, exc_type, exc_val, exc_tb):
condition_met = False
try:
for case, func in self.conditions.items():
if isinstance(case, self.Expression):
if case.expression(self.value):
condition_met = True
func(self.value)
elif self.value == case:
condition_met = True
func(self.value)
except self.BreakException:
return
if not condition_met and self.default is not None:
self.default(self.value)
there we go
grade = 'C'
# Instantiate a switchcase called case that iterates over cases in the order
# that they're inserted.
with Switch(grade) as case:
# Calling case.Break() stops other cases from being evaluated.
case[case.ex(lambda value: value in ['A', 'B', 'C'])] = lambda value: print("Good job you passed!")
case['A'] = lambda value: (print(f"Good job, you got an {value}!"), case.Break())
case['B'] = case['A']
case['C'] = lambda value: (print(f"Not bad! You got an {value}!"), case.Break())
case['D'] = lambda value: (print(f"You received an {value}."), case.Break())
case['F'] = case['D']
# Case.default will run if it's defined and no other cases are ran.
case.default = lambda value: print(f"Error: Unknown grade {value}")
I could allow a shorthand like...
case.ex[lambda v: v > 5] instead of case[case.ex(lambda v: v > 5)]
class Switch:
def __init__(self, value, default='default', dry=False):
self.value = value
self.cases = {}
self.default = default
self.dry = dry
@property
def choice(self):
condition = self.value
default = self.cases.get(self.default, None)
return self.cases.get(condition, default)
def __enter__(self):
return self
def __exit__(self, *_):
if not self.dry:
case = self.choice
condition = self.value
if case is not None:
case(condition)
return None
def case(self, *cases):
def decorate(func):
for case in cases:
self.cases[case] = func
return func
return decorate
mine has a pretty easy implementation
can even specify dry=True to stop the exit from running and use s.choice yourself
with Switch(grade) as s:
@s.case('A', 'B')
def good(value):
print(f'Good job, you got {value}!')
@s.case('C')
def notbad(value):
print(f'Not bad, you got {value}.') ```
example of the above in action (reposted from [#python-discussion](/guild/267624335836053506/channel/267624335836053506/))
ty 😄
that's pretty cool. Hmmm. So how does it work if you want to, say, break explicitly? I'm guessing that's the s.choice / dry thing?
Like, if I want two conditions to evaluate (only the second one breaks)... wat do
yuppp
and ill break with return value, if its False it breaks.
It might be difficult to implement, but case[case > 3] = lambda val: print("You got more than three") is valid Python.
Oh that's clever
ya'll gonna be like Procez over here
My proposed syntax could just have case implement a few comparison operators as continuations.
I saw a context manager that implemented __iter__ a while ago, so you could do with Switch(x) as case, default:
So those are some ideas.
Hmmm. Comparison overriding could get hairy fast. Not everything can be overridden -- like is
A special case (no pun intended) like case.is[None] = ... would suffice there.
Oh hmm, switch statements in other languages support modifying the value...
So like...
switch(x):
case 9:
x += 30
case 10:
x += 5
case 15:
x -= 6
so if x was 10 x would be 10, then 15, then 9, and I think only case 10 and case 15 would run

If you knew it were called x you could do globals()['x'] and locals()['x']
That would let you update the value.
Perhaps if you called it with the name of your variable. with Switch('x') as case:
globals
What channel are we in again?
#nintendo-switch
with Switch(grade) as s:
@s.case('A', 'B')
def good(value):
print(f'Good job, you passed!')
@s.case('C')
def notbad(value) -> Break:
print(f'Not bad, you got {value}.')
@s.case('D', 'F')
def bad(value):
print(f'You recieved an {value}')
Decided to abuse type annotations instead.

You gotta raise break
I think
orrr call a break function on s (which then raises break)
Yeah that should work.
I support the latter 'cause you can't raise in lambdas
but both approaches are valid
s.case('C')(lambda value: (print(f'Not bad, you got {value}.'), s.Break())```
functionally the same tho, yea?
yeah, just calling .Break() lets you do it in a lambda -- you can't use the raise keyword argument in one. Although, with the decorator approach, there's not a good reason to
I liked the returning False for break tho
What about None for not breaking, and any other value for breaking? That way, if your function doesn't return, it won't break.
breaking news
turns out
I don't understand how switches work
after the first one is true
all subsequent ones get evaluated without checking for the condition
.......................... fuck this LOL
Not too much of a change.
yeah but I'm suddenly horrified
Many languages automatically break after a case, which is simpler.
@rare juniper
>>> r = lambda e:(0for _ in()).throw(e)
>>>
>>> r(Exception)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 1, in <lambda>
File "<stdin>", line 1, in <genexpr>
Exception
>>> ```
cursed
i think imma try to rewrite my lambda try/except
3.8 broke the way it worked with no imports
import operator
no_value_given = object()
class UnfinishedCondition:
def __init__(self, op, init_val, switch):
self.op = op
self.init_val = init_val
self.switch = switch
self.called = False
def __call__(self, value):
if not self.called:
self.switch.add_case((self, value))
self.called = True
else:
return self.op(value, self.init_val)
def relational_op(operator):
def operate(self, value):
return UnfinishedCondition(operator, value, self)
return operate
class Switch():
def __init__(self, value=no_value_given, autobreak=False):
self.value = value
self.cases = []
self.autobreak = autobreak
def __enter__(self):
return self
def __exit__(self, *_):
if self.value is not no_value_given:
return self.eval(self.value)
def __iter__(self):
yield self
yield self.default
def eval(self, value=no_value_given):
match = False
for condition, callback in self.cases:
if condition(value) or match:
match = True
if callback(value) is not None or self.autobreak:
break
def add_case(self, case):
self.cases.append(case)
def __setitem__(self, key, callback):
if key == self.default:
new_case = (lambda v: True, callback)
else:
new_case = (lambda v: v == key, callback)
self.add_case(new_case)
__eq__ = relational_op(operator.eq)
__ne__ = relational_op(operator.ne)
__gt__ = relational_op(operator.gt)
__lt__ = relational_op(operator.lt)
__ge__ = relational_op(operator.ge)
__le__ = relational_op(operator.le)
__contains__ = relational_op(operator.contains)
is_ = relational_op(operator.is_)
is_not = relational_op(operator.is_not)
__call__ = eval
default = object()
Oh, that's more code than I thought it was.
Anyway, here's a demo:
number = int(input("number: "))
with Switch(number, autobreak=True) as (case, default):
case[42] = lambda x: print('neat!')
(case > 100000)(lambda x: print("wow! I can't count that high!"))
(case > 10)(lambda x: print(f"not 42, but {x} is still a big number."))
case[default] = lambda x: print(f"What sort of number is {x}?")
You can also delay the evaluation of the switch until later, or evaluate it multiple times.
class switch:
def __init__(self, *inputs, default=None):
self.inputs = inputs
self.default = default
def __call__(self, *cases):
for case, result in zip(*[iter(cases)]*2):
if callable(case):
if case(*self.inputs):
return result
elif self.inputs == case:
return result
else:
return self.default
x, y, z = 1, 1, 1
result = switch(x, y, z, default='lol')(
(1, 2, 3), 22,
(4, 5, 6), 12,
lambda a, b, c: a < b < c, y
)
keeping it simple
personally prefer an approach like https://discordapp.com/channels/267624335836053506/267624335836053506/594668209324687360
seems a way more pythonic and efficient way of doing something like this
then again this is #esoteric-python
default = lambda *args: True
class switch:
def __init__(self, *inputs):
self.inputs = inputs
def __call__(self, *cases):
for case, result in zip(*[iter(cases)]*2):
if callable(case):
if case(*self.inputs):
return result
elif self.inputs == case:
return result
x, y, z = 1, 1, 1
result = switch(x, y, z)(
(1, 2, 3), 22,
(4, 5, 6), 12,
lambda a, b, c: a < b < c, y,
default, 'lol',
)
slightly cleaner with a different way of specifying default
reminds me of https://github.com/superbird11/ranges
I'd swap __call__ and __init__ so you can create the case without applying it yet.
would have to jump through some hoops to implement the third case if thats done
specifically the fact that it returns y
would have to add some other way of specifying return the middle input or something like that
You could do the exact same thing, except you'd put the (x, y, z) after the call with all the cases.
the intention is that youd be returning the middle input regardless of what the inputs actually are
so if that case was to return one specific middle input for a given set of inputs, there wouldnt be much point to create the switch without applying it
this way it's more... idk. semantically consistent?
i did write a version with them swapped btw
default = lambda *args: True
class switch:
def __call__(self, *inputs):
for case, result in zip(*[iter(self.cases)]*2):
if callable(case):
if case(*inputs):
return result
elif inputs == case:
return result
def __init__(self, *cases):
self.cases = cases
x, y, z = 1, 1, 1
result = switch(
(1, 2, 3), 22,
(4, 5, 6), 12,
lambda a, b, c: a < b < c, y,
default, 'lol',
)(x, y, z)``` Here's my attempt
switcher_func = switch(
(1, 2, 3), 22,
(4, 5, 6), 12,
lambda a, b, c: a < b < c, y,
default, 'lol',
)
print(switcher_func(1, 11, 111))```
youre missing my point
the goal of the third case is to return the middle input
regardless of what it is
x, y, z are just example inputs
to demonstrate
not intended to be constants
I think the reverse from your implementation is more versatile, even if it doesn't work perfectly for the third case.
i disagree. and i think having the inputs first is more in line with the classic idea of what a switch statement is.
looks-wise
with switch(x):
with case(1):
...
with case(2):
...
with case(lambda x > 10):
...
```something like this should be doable too shouldn't it?
@contextmanager
def case(target):
value = case._value
if (iscallable(target) and target(value)) or (value == target):
yield
@contextmanager
def switch(value):
case._value = value
yield
case._value = None
``` something like this?
Wait no that won't work
hmm...
Oh found a nasty way to do it
Gimme a few mins
Aaa I'm so close to getting this
Why can't with block cancel
I could enable this behavior with a decorator
like ```py
@has_switch
def func():
with switch(x := 10):
with case(20):
...
with case(x > 3):
...
make it non-cpython-dependent so I can use it in kython
are people actually using kython now 
What's kython
Python interpreter in Kotlin
This is a lie btw, inspect.stack and sys.getframe don't show any difference here 
wdym
https://docs.python.org/3/library/contextvars.html @grave rover could this help?
This PEP proposes a new contextvars module and a set of new CPython C APIs to support context variables. This concept is similar to thread-local storage (TLS), but, unlike TLS, it also allows correctly keeping track of values per asynchronous task, e.g. asyncio.Task.
no
@wind maple https://paste.pythondiscord.com/abarabacon.py
got this far then realised exceptions raised in __enter__ wont get sent to __exit__ lel
looks like https://github.com/rfk/withhacks/blob/master/withhacks has a way of doing it
but probably outdated
This might be of interest to you demons https://twitter.com/tirkarthi/status/1198852129793798144
Python 3.9 will include a method to unparse the AST object back to source code.
import ast
print(ast.unparse(ast.parse('1+1')))
(1 + 1)
not that you couldn't do it before
could you?
well you could just manually write stuff to unparse it manually
what I meant with "you couldn't" is that the people here probably would have figured it out if they wanted to 
There's also a patch to clean up parenthesis
a, b, c = 1, 2, 3
with switch(a, b, c):
with case(lambda a, b, c: a < b < c):
print('ayy 0')
with switch(b, a, c):
with case(2, 1, 3):
print('nested switch!')
with case(1, 2, 3):
print('this wont be printed')
with case(1, 2, 3):
print('ayy 1')
with case(lambda a, b, c: b == 2):
print('holy shit a nested case!')
switch_break()
with case(1, 2, 3):
print('ayy 2')
should be thread/async safe
@grave rover what do you reckon
did i do it right
oh hmm, on second look, needs some more work for threadsafety. bit confused on how to work with contextvars correctly here.
>>> import contextvars
>>> import threading
>>> var = ContextVar('vat')
>>> var.set('hello')
<Token var=<ContextVar name='var' at 0x00000202707B5C48> at 0x00000202707E0728>
>>> var.get()
'hello'
>>> def test():
try:
print(var.get())
except LookupError:
print('var not set in this context')
var.set('12321')
>>> thread = threading.Thread(target=test)
>>> thread.start()
var not set in this context
>>>
nevermind, it's fine
@brazen geyser did you actually just abuse stackframes and settrace to skip the block
lOl
Is there anything that ... can be replaced with in this code to make the assertion true? ```py
def sig():
yield 0
def fn():
return (lambda a: ...)(sig())
for v in fn():
assert(v == 0)```
The normal way to write it being yield from sig(), this actually cropped up in an attempt at using asyncio in one line
iter(int,...)
... can be any value
probably not what you want though
a will probably do more along the lines of what you want
def sig():
yield 0
def fn():
return (lambda a: a)(sig())
for v in fn():
assert(v == 0)```
I keep looking at the name of this room in the sidebar like . . . Someday.
It is an arcane art steeped in mystery.
There is no paved path. You must find your own way here, as all do in the end.
All roads lead to #esoteric-python, just by different routes
Speaking of esoteric, here's my side project idea
an HTML/CSS framework for building terminal UIs
run electron in the bg and convert to terminal resolution and colors /s
Merge two strings:
def merge(a: str, b: str) -> str:
if len(a) != len(b):
raise ArgumentError("Strings must be same length")
c = [" "]*len(a)*2
c[::2] = a
c[1::2] = b
return ''.join(c)
>>> merge("123", "abc")
'1a2b3c'
>>> def merge(a, b):
... return "".join(f"{ca}{cb}" for (ca, cb) in zip(a, b))
...
>>> merge("123456","abcdef")
'1a2b3c4d5e6f'
doesn't care if strings are same length
merge=lambda a,b:''.join(sum(zip(a,b),()))```
woah wat
def merge(a, b):
c= ([" "]*len(a)*2)
return ''.join([[c for c[::2] in [a]], [c for c[1::2] in [b]]][1][0])
oh nice thats clever @sick hound
merge = lambda a, b, c=[]: ([None for c[:] in [[" "]*len(a)*2]]), ''.join([[c for c[::2] in [a]], [c for c[1::2] in [b]]][1][0]))[-1]
merge = lambda a, b, c=[]: ([None for c[:] in [[" "]*len(a)*2]], ''.join([[c for c[::2] in [a]], [c for c[1::2] in [b]]][1][0]))[-1]
merge = lambda a, b, c=[]: ''.join([c for c[:], c[::2], c[1::2] in [([*(" "*(len(a)<<-~False))],a, b)]][0])
I think I succeeded in making this pretty much unreadable
merge=lambda a,b,c=[]:''.join([c for c[:],c[::[]==[]+[]==[]],c[[]==[]::[]==[]]in[([" "]*(len(a)<<-~False),a,b)]][[]==[[]]])```
remove all spaces and numbers
Needs to have a - in front of the ~, typoed it
chr()
and str()
merge=lambda a,b,c=[]:str().join([c for c[:],c[::2],c[1::2]in[([*(chr(True<<5)*(len(a)<<-~False))],a,b)]].pop(False))
merge=lambda a,b,c=[]:str().join([c for c[:],c[::[]==[]+[]==[]],c[[]==[]::[]==[]]in[([(chr([]==[]<<5)]*(len(a)<<-~False),a,b)]][[]==[[]]])```
oh this is an esoteric challenge, not a golf challenge?
both
it could probably be golfed a ton
"Something that is clearly not a joke but will never be able to be clearly understood again"
I'm just trying to make it look as dumb as possible
I suppose you could call it the "Now only god knows" challenge
merge=lambda a,b,c=[]:str().join([c for c[:],c[::-~True],c[True::-~True]in[([*(chr(True<<5)*(len(a)<<-~False))],a,b)]].pop(False))
if you want to golf it
lambda a,b:''.join(sum(zip(a,b),()))```
(I have no clue how that works but it does)
zip yields a bunch of tuples
sum adds all their content together into one big tuple
join joins all the contents of this one big tuple
what's with the () in sum?
merge=lambda a,b,c=[]:str().join([c for c[:],c[False::-~True],c[True::-~True]in[([*(chr(True<<5)*(len(b)<<-~False))],a,b)]].pop(False))
but in this case it makes a tuple that gets appended to
lambda a,b:''.join(sum(zip(a,b),()))```
I wonder if this can be golfed anymore
lambda*s:''.join(sum(zip(*s),())) should work, possibly needing a space before the first *.
I think python lambda*s:`sum(zip(*s),())`[2::5] works in python 2
which is shorter but it's python 2
Unconventional challenge: make the most readable code for merge(*strings: str)
example:
merge('a', 'b', 'c')
'abc'
merge('abc', 'def', 'hijkl')
'adhbeicfjkl'
merge('abc', 'd', 'efg')
'adebfcg'
In [60]: strings = ('a','b','cde')
In [61]: "".join(strings)
Out[61]: 'abcde'
do note that sum may fail on non-numeric inputs according to the spec IIRC
sum(iterable, /, start=0)
Return the sum of a 'start' value (default: 0) plus an iterable of numbers
When the iterable is empty, return the start value.
This function is intended specifically for use with numeric values and may
reject non-numeric types.```
oh, merge shuffles
In [71]: from itertools import zip_longest
...: strings = ('abc', 'def', 'ghi')
...: "".join(letter for row in zip_longest(*strings) for letter in row)
Out[71]: 'adgbehcfi'
is this more readable?
In [73]: from itertools import zip_longest, chain
...: strings = ('abc', 'def', 'ghi')
...: "".join(chain(*zip_longest(*strings, fillvalue='')))
Out[73]: 'adgbehcfi'
zip_longest will need fillvalue='' to pass the tests
Otherwise it'll try to .join None's
(when strings have differing lengths)
fair
#if the goal is readable, a for loop works well
def merge(*strings: str):
out: str= ""
for i in range(max(map(len,strings))):
for string in strings:
if i < len(string):
out+=string[i]
return out
+= is real bad performance-wise though for strings
better appending to a list and joining at the end
https://discordapp.com/channels/267624335836053506/470884583684964352/649341673750396938 i'd consider this pretty readable
I think CPython optimizes it. The difference is marginal
sum is not supposed to work for non-numbers, and it is not the same as the above 2 snippets
well, it does
and you can allow more than two like https://discordapp.com/channels/267624335836053506/470884583684964352/649350767471493131
i thought *s doesn't work with lambdas anymore
that + some proper indentation and naming would be the nice goldilocks zone between readability and evil
imo
it does work
still not the same thing
oh ok, so we have strings of variable length
>>> from itertools import zip_longest
>>> def merge(*strings):
return ''.join(
character
for merged_characters in zip_longest(*strings)
for character in merged_characters
if character is not None
)
>>> merge('abc', 'def', 'hijkl')
'adhbeicfjkl'
>>>
how bout this
oh hold on thats not right lol fixd
oh salt already did this one anyway
i think we gotta agree on how to rank readability first
@wind maple define most readable
def merge(*string_list) -> str:
"""
Interleaves strings passed as arguments
together into one string,
by taking a character from each one in turn.
When the end of a string is reached, it is removed
from the round robin of characters.
Note: returns a str, not a generator.
"""
#fliter out empty strings
string_list = [string
for string in string_list
if len(string) > 0]
accumulator = ""
while len(string_list) > 0:
#iterate through every string until they're all gone
next_strings = []
for string in string_list:
#split string into first character,
#and a list of all other characters in it
first_char, *rest_of_string = string
#accumulator collects one character per string per cycle
accumulator += first_char
if len(rest_of_string) > 0:
#filter the string out of next iteration if it's now
#empty, otherwise, convert the list to a string, and
#append it to the strings still left to process
rest_as_string = "".join(rest_of_string)
next_strings.append(rest_as_string)
string_list = next_strings
return accumulator
tl;dr
But if you had read it, I'm sure it would be the most readable function you'd ever beheld.
readable like canterbury tales, there's a lot to read, but no one wants to
i prefer "grokkable"
Damn, disappointed you can't sum() strings
@distant wave :x: Your eval job has completed with return code 1.
001 | Traceback (most recent call last):
002 | File "<string>", line 1, in <module>
003 | TypeError: sum() can't sum strings [use ''.join(seq) instead]
Oh uh
It might be because the thing on my phone uses an old version of python
Yeah it uses 3.4, so that's probably why
doesn't work in 2.7 or 3.7
It's either the thing on my phone is buggy, or it worked in some versions between 2.7 and 3.7
sum = lambda x: __import__('functools').reduce(lambda a, b: a+b, x)```
Terrible replacement for sum that should work
Terrible r placement that was used before sum was added :D
sum = lambda a, b: (lambda f, a, l: f(f, a, l))((lambda f, a, l: f(f, a+l[0], l[1:]) if l else a), b, a)```
no imports
reduce used to not need importing
reduce = lambda op, a, b: (lambda f, a, l: f(f, a, l))((lambda f, a, l: f(f, op(a, l[0]), l[1:]) if l else a), b, a)```
I think I figured out a way to do it with the sum function.
I don't remember it now.
>>> class DummyString:
def __add__(self, other):
return other
>>> sum(('afsf', 'sfdsdf', 'sadfasdf'), DummyString())
'afsfsfdsdfsadfasdf'
>>>
I think that was it, yes. Except I called it AdditiveIdentity() to be descriptive.
It was in my multiplication code, from memory.
>>> sum(('34234', '4353', 'sdfasdf'), type('', (), {'__add__':lambda a,b: b})())
'342344353sdfasdf'
one-liner-ized :p
eval('"'+ '"+"'.join(strings) + '"')
!e ```python
strings = ["123", "123123123", "asdfasdf"]
print(
eval(''.join(map(repr, strings)))
)
@distant wave :white_check_mark: Your eval job has completed with return code 0.
123123123123asdfasdf
1 char shorter :P
neat
I don't think I'm winning any awards with this one:python lambda*s:print(*s,file=(f:=__import__('io').StringIO()),sep="",end="")or f.getvalue()
or as sequence of operations is Galaxy brain
lambda*s:(f:=__import__('io').StringIO()).getvalue(*filter(bool,(print(*s,file=f,sep="",end=""),)))
```I'm not sorry.
lambda*s:(lambda f,a,s:f(f,a,s))(lambda f,a,s:f(f,a+s[0],s[1:],'',s) if s else a) not tested
f=lambda s:s[0]+f(s[1:])if s else""
But that's cheating
!e
f=lambda x,*y:x+((y or'')and f(*y))
print(f("Hello", "World", "1", "31415"))
@formal sandal :white_check_mark: Your eval job has completed with return code 0.
HelloWorld131415
At least use walrus, so you can name it properly
What aboutpython merge=(lambda f:f(f))(lambda f:lambda x,*y:x+((y or'')and f(*y)) print(f("Hello", "World", "1", "31415")))
saddly that error message is actually part of the c code 😦 not something the string class evokes
/* reject string values for 'start' parameter */
if (PyObject_TypeCheck(result, &PyBaseString_Type)) {
PyErr_SetString(PyExc_TypeError,
"sum() can't sum strings [use ''.join(seq) instead]");
Py_DECREF(iter);
return NULL;
}```
from functools import reduce
add = lambda x, y: x + y
sum = lambda iterable, start=0: reduce(add, iterable, start)
That would probably be slower than the normal sum for numbers, though
Python is about versatility rather than speed.
Original sum is implemented in C, so short of delegating to it for non-strings...
I mean, if you start with 0, you can't add strings
His sum variant can do that too: sum(map(str, range (88)),'')
It... Doesn't work?
Traceback (most recent call last):
File "<string>", line 5, in <module>
File "<string>", line 3, in <lambda>
File "<string>", line 2, in <lambda>
TypeError: unsupported operand type(s) for +: 'int' and 'str'```
Did you set the starting value properly
add = lambda x, y: x + y
sum =lambda iterable:( lambda iterator: reduce(add, iterator, next(iterator)))(iter (iterable))```
You can do extra work to get rid of that initial
!e ```py
from functools import reduce
add = lambda x, y: x + y
sum = lambda iterable, start=0: reduce(add, iterable, '' if any(isinstance(x, str) for x in iterable) else start)
print(sum(map(str, range(88))))
print(sum(range(88)))
@crystal mica :white_check_mark: Your eval job has completed with return code 0.
001 | 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
002 | 3828
Or just use the first element as the initial value
That way it works for anything that defines add
It's different from the base sum if so.
It is
add = lambda x, y: x + y
sum =lambda iterable:( lambda iterator: reduce(add, iterator, next(iterator)))(iter (iterable))
print(sum(list(range(80)) for x in range(80)))```
whoa, i didn't know lambdas took default arguments
Hmm, interesting
print(sum([1, 2, 3, '4', 5, '6']))
# -------
TypeError: can only concatenate str (not "int") to str```
Time to fix add as well haha
!e ```py
from functools import reduce
add = lambda x, y: x + y if all(isinstance(i, int) for i in (x, y)) else f"{x}{y}"
sum = lambda iterable, start=0: reduce(add, iterable, '' if any(isinstance(x, str) for x in iterable) else start)
print(sum(map(str, range(88))))
print(sum(range(88)))
print(sum([1, 2, 3, '4', 5, '6']))```
@crystal mica :white_check_mark: Your eval job has completed with return code 0.
001 | 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
002 | 3828
003 | 123456
This is an abonimation
i found this in some forgotten folder the other day:
In [298]: my_list = [1,2,3,4]
...: accumulate = [j for j in [0] for i in my_list for j in [j+i]]
In [299]: accumulate
Out[299]: [1, 3, 6, 10]
what
Cool
sort of abusing comprehension to define a variable
wow damn, that is cool
You can do this ```python
lambda a, *, b: None
lambda a, /, c: None
you can use this method to assign things temporarily in lambdas, i think
You could do a sum by taking ...][0] of it
yep, well the other end of it
Touché
map(lambda *x:sum(x), *([0]*k+list_in[:(-k,None)[not k]] for k in range(len(list_in))))
i havent really been paying attention, but why shouldnt this work?
sum = lambda args: __import__("functools").reduce(lambda x,y: str(x)+str(y),args)```
or are we trying to avoid functools
That will not work for anything other than strings
why not?
In[2]: sum = lambda args: __import__("functools").reduce(lambda x,y: str(x)+str(y),args)
sum(["hey", 1, "there"])
Out[3]: 'hey1there'```
oh
i see
wont work for actual summing
Indeed. Shirus will work for multityped iterables as long as one of the types.is a.string, mine will work for lists of a single type that defines addition with itself
sum = lambda args: __import__("functools").reduce((lambda x,y: str(x)+str(y)) if any(map(lambda x: isinstance(x,str), args)) else (lambda x,y: x+y),args)
sum([1,2,3])
Out[17]: 6
sum([1,2,3,'h'])
Out[18]: '123h'```
whats the expected output for sum([1,2,3,'h'])?
is it '123h' or '6h'?
should be 123h, but 6h looks more fun!
sum all adjacent numbers and concatenate everything else
made it a bit shorter:
sum=lambda a:__import__("functools").reduce((lambda x,y:str(x)+str(y))if(str in map(lambda x:type(x),args))else(lambda x,y:x+y),args)```
