#esoteric-python
1 messages · Page 75 of 1
basically i have some bytecode i generated and a list of constants (thats all i need in this case), but im struggling with how to save that to a pyc
because i dont really get what order its serialised in
Pretty much the same way they're represented in memory i.e. what ceval.c says they're structured like
is there a way of just running the bytecode? i want to check if my bytecode is even correct before i worry about the pyc files
i tried making a codeobject but it segfaults, so either my code is really wrong or i messed up one of the args 😅
exec or eval have the option of running bytecode iirc
@tropic night
Here's your reminder: d do 136174338633105408 flowerbed puzzle
getting a start on bytecode :D https://totally-not.a-sketchy.site/5bxUQdp.png
@pure dew @gentle pagoda if you want you can help out with https://github.com/martmists/bytepatches
Hello world
I want to show something unpythonic
@properties(name=
{'read': ['module', 'anywhere'],
'change': ['module'],
'remove': []
})
class hello:
def __init__(self, name):
self.name = name
def greet(self):
print(f"Hello, {self.name}!")
x = hello('john')
x.greet()
x.name = 'johnny'
x.greet()
from one import hello
x = hello('john')
x.greet()
#x.name = 'johnny'
del x.name
print(x.name)
calling two.py
Hello, john #From Importing One
Hello, johnny #From Importing One
Hello, john
AttributeError: attribute 'name' cannot be removed in the scope.```
Yay!
p = print
p; p (
'h' 'e' 'l'
'l' 'o' ' ' 'w'
'o' 'r' 'l'
'd' '!'
)``` this is a valid hello world program
Yep, why not
class A:
foo = bar()
how easy would it be for bar() to know that is being used inside A at the time it's called?
im guessing it'd be possible to investigate the frame to tell that a class definition is going on but A itself wont be accessible at that point right? since it wouldnt even completely exist yet
maybe if you stick it in an __init__ or __new__
2nd frame in the stack
In [7]: def foo():
...: print(inspect.stack()[1].code_context)
...:
In [8]: class A:
...: a = foo()
...:
[' a = foo()\n']
neat™
>>> import inspect
>>> def bar():
print(inspect.stack()[1].code_context)
>>> class A:
foo = bar()
None
>>>
guess inspect is crapping out in the repl
inspect.stack()[-2] should work @brazen geyser
Then you can get .frame.f_code to get the code object for the class
!e
import inspect
def bar():
stack = inspect.stack()
if stack[1].function == "<module>":
print("not inside anything")
else:
print("inside function:", stack[1].function)
bar()
class A:
foo = bar()
@formal sandal Your eval job has completed with return code 0.
001 | not inside anything
002 | inside function: A
But that doesn't tell whether it's a class or not...
However, the convention is that classes are in CamelCase and functions are in snake_case.
I have an idea.
i dont like where this is going 
You can get the code object of an outer stack frame (inspect.stack().frame.f_back.f_code) and the line number (inspect.stack().lineno).
Then you can iterate over the code and see where the line at lineno fits.
And then search for the LOAD_BUILD_CLASS instruction.
oh thats slightly more sane
Perhaps
!e ```python
import inspect
def bar():
stack = inspect.stack()
if stack[1].function == "<module>":
print("not inside anything")
else:
print("inside function:", stack[1])
bar()
class A:
foo = bar()
@distant wave Your eval job has completed with return code 0.
001 | not inside anything
002 | inside function: FrameInfo(frame=<frame at 0x7f101f51e390, file '<string>', line 13, code A>, filename='<string>', lineno=13, function='A', code_context=None, index=None)
!e ```python
import inspect
def bar():
stack = inspect.stack()
if stack[1].function == "<module>":
print("not inside anything", stack[1])
else:
print("inside function:", stack[1])
bar()
class A:
foo = bar()
def b():
foo = bar()
@distant wave Your eval job has completed with return code 0.
001 | not inside anything FrameInfo(frame=<frame at 0x564ae52d1560, file '<string>', line 10, code <module>>, filename='<string>', lineno=10, function='<module>', code_context=None, index=None)
002 | inside function: FrameInfo(frame=<frame at 0x7f89da8ce390, file '<string>', line 13, code A>, filename='<string>', lineno=13, function='A', code_context=None, index=None)
!e ```python
import inspect
def bar():
stack = inspect.stack()
if stack[1].function == "<module>":
print("not inside anything", stack[1])
else:
print("inside function:", stack[1])
bar()
class A:
foo = bar()
def b():
foo = bar()
b()
def c():
class B:
foo = bar()
c()
@distant wave Your eval job has completed with return code 0.
001 | not inside anything FrameInfo(frame=<frame at 0x5607f45c0d40, file '<string>', line 10, code <module>>, filename='<string>', lineno=10, function='<module>', code_context=None, index=None)
002 | inside function: FrameInfo(frame=<frame at 0x7f7ddb7d0390, file '<string>', line 13, code A>, filename='<string>', lineno=13, function='A', code_context=None, index=None)
003 | inside function: FrameInfo(frame=<frame at 0x7f7ddb729530, file '<string>', line 16, code b>, filename='<string>', lineno=16, function='b', code_context=None, index=None)
004 | inside function: FrameInfo(frame=<frame at 0x7f7ddb7296d0, file '<string>', line 22, code B>, filename='<string>', lineno=22, function='B', code_context=None, index=None)
See code_context, when not run in repl:
code_context=['class C:\n']
The following code gives:
import inspect
def a():
for frame in inspect.stack(context=1)[1:]:
print(frame.code_context[0].strip(), end=", ")
del frame
print()
a()
def b():
a()
b()
class C:
v = a()
def n():
a()
C.n()
def x():
class F:
v = a()
x()
a(),
a(), b(),
v = a(), class C:,
a(), C.n(),
v = a(), class F:, x(),
Note that the first stack frame is the call inside a(), the second the call to a() and the third is the containing scope (None for a bare call, the class initializer line in a class, and the function call if defined within a functino)
So, to figure out if you're inside a growing class definition, inspect.stack(context=1)[-2].code_context.lstrip().startswith('class')
Friendly reminder that this only works for code in files and that del is a useless statement in that snippet and just adds 2 opcodes to it that practically do nothing
I have a weird challenge, now the GPT-2 has been released. GPT-2 is a neural network that tries to predict what the next word in some text will be. Fortunately for us, a lot of its training data came from GitHub, so it knows some Python. The task is to go to https://talktotransformer.com/ (or any other website that implements GPT-2), input #!/usr/bin/python3 (or anything else that will get it to autocomplete with python code), then fix whatever comes out until you have a working program. (It might not generate proper code the first time, so you can regenerate as many times as you want.) Scoring will be based on how proud of yourself you feel afterwards.
this is at least python
Here's my attempt at debugging GPT2's code. I had to fix all the whitespace, and a few logic errors, but it's possible for it to get to the end without getting stuck in an infinite loop or crashing.```python
#!/usr/bin/python3
import sys # A human wrote this line of code, not the robot
if len(sys.argv) > 2:
sys.exit(1)
argv = sys.argv # More human code
for line in sys.argv:
argv[:1] = line
if not sys.argv[1:]:
sys.exit(1)
print('')
raw_input = lambda string:eval(input(string)) # Human here; this line of code was written by me
while True:
r = raw_input('')
if r:
print(r)
else:break # Line written by me, your friendly neighbourhood human
def main():
print('')
for line in sys.argv:
print('')
print(main) # Guess who wrote this line? It sure wasn't GPT-2!```
GPT2 has been released ages ago lol....
And the majority of its training data came from Reddit not GitHub iirc
Didn't they release a larger (better) version of it only recently?
The texts don't come directly from Reddit, they come from the links that are on Reddit. GitHub is somewhere in the top five or ten websites it crawled.
they released a larger, pre trained version everyone who has enough money and a guy who can understand their original paper couldve build this when the paper got released
they just tried to make it so not every idiot can use it
I'm included in 'every idiot' then.
!e
print("lmao"
Sorry, but you may only use this command within #bot-commands.
It, uh, gave me this beauty: (os.path.dirname(os.path.realpath(os.path.extname(os.path.realpath(os.path.realpath(os.path.realpath(os.path.realpath(os.path.realpath())))))))
What in the name of ... esoteric is that
IFcoltransG's GPT-2 challenge
Hmm, is that the os that came with stdlib?
I got an error
AttributeError: module 'ntpath' has no attribute 'extname'```
I don't think it runs, but I'm just amazed by the structure it produced
pathlib for the win!
(lambda x:print(x))(lambda x:'+')(lambda x:print(x))(lambda e: print(lambda x:print(x)(lambda x, e':print(lambda e:print(e))(lambda x, e':print(lambda e:print(e)(lambda x, e':print(lambda e:print(e))(lambda x, e':print(lambda e:print(e))))))
I just got this
don't think that runs but it's pretty nonsensical
at least the amount of lambdas is right for this channel 😄
it won't run
(lambda x:print(x))(lambda x:'+') will print a lambda and return None
so then it gets called
none isn't callable
actually no
e':print(lambda e:print(e))(lambda x, e'
this is invalid syntax
e':print(lambda e:print(e))(lambda x, e'
so's this
wait that's the same thing
it says that twice, and both times it's invalid syntax
there's an answer on stackexchange that says that this
?"""?'''?
can't appear anywhere in a python program that doesn't error
(with a leading newline)
would there be some crazy way to make it so this doesn't error using ctypes or something
Like that sequence of chars in the code or """ ''' ?
probably not, if it's a syntax-error thing
@edgy kelp a newline followed by that sequence of characters
also I feel like it might be possible
maybe you could do something like overwriting the SyntaxError class or something (although i've never used ctypes)
not if the code can't run because it's invalid syntax
!e ```python
#?"""?'''?
@distant wave Your eval job has completed with return code 0.
[No output]
Checkmate, stackoverflow :P
a newline followed by that sequence of characters
Hm
!e py try: ?"""?'''? except: pass
@wind maple Your eval job has completed with return code 1.
001 | File "<string>", line 2
002 | ?"""?'''?
003 | ^
004 | SyntaxError: invalid syntax
if only 😄
Syntax is scanned before the code is run ;-;
not much you can do with that
both """ and ''' which can go through newlines you put above are closed in there, exposing one of the chars you can't assign to
Yeah, I don't think it's possible to make that work without loading it from another module
print('hi)
you could make yourself an interpreter where you can assign every character 😄
You could hook into importlib's loader machinery and fix it, but it can't be done in the script containing the sequence
hm'
I was wondering if you could place an __future__.py file in the local namespace, and hijack the __future__ mechanic which does come before syntax checking, but it seems that if it does exist it triggers the regular import process and does a syntax scan
say what now
from __future__ import [feature] occurs before syntax checking
If you have an __future__.py file, it's imported instead. But the import does not come before a syntax check
hmmMMMmm
Well, I did it
The following file runs on python 3.7, and contains those chars
Hm.
# -*- coding: cp037 -*-
£M
?"""?'''?
]
Discord doesn't like it
It's the following bytestring:
# -*- coding: cp037 -*-\n\x97\x99\x89\x95£M\x7f\n?"""?\'\'\'?\n\x7f]
Here's a better one
b'# -*- coding: cp037 -*-\n\xc2\x97\xc2\x99\xc2\x89\xc2\x95\xc2\xa3M\x7f\n?"""?\'\'\'?\n\x7f]%\x97\x99\x89\x95\xa3M}\xc8\x85\x93\x93\x96@\xe6\x96\x99\x93\x84}]'
$ python enctest.py
Hello World
$ cat enctest.py
# -*- coding: cp037 -*-
£M
?"""?'''?
]%�����M}ȅ���@料��}]
how does that work?
It abuses the ability to set a character encoding at the top of your script, which translates the offending syntax error into strange binary characters that the interpreter is happy to skip
also could you paste a tio.run link for that, I can't figure out how to get those bytes into a file/on my clipboard
a = open("enc.py", "wb")
a.write(b'# -*- coding: cp037 -*-\n\xc2\x97\xc2\x99\xc2\x89\xc2\x95\xc2\xa3M\x7f\n?"""?\'\'\'?\n\x7f]%\x97\x99\x89\x95\xa3M}\xc8\x85\x93\x93\x96@\xe6\x96\x99\x93\x84}]')
a.close()
It does not appear to run on tio, there's some encoding strangeness going on that breaks the characters
You can pretty clearly see that it's not sending the actual bytes in the text box, but what looks like unicode replacement characters instead
Mojibake
However, we're lucky, and the goal of the challenge can be completed on tio.run, just without the extra hello world flair
The answer I was referencing says 'not cpython'
and it doesn't work on Python (PyPy)
but does work on Python (Stackless)
which is kinda weird
Interesting. Does pypy not support cp037?
i don't think so, you can try it on TIO
File ".code.tio", line 1
Ä?ÀÑ>ÅÄøBpBrBiBnBt("")
^
SyntaxError: invalid character in identifier
oh ok
which is strange
I mean the concept of encoding abuse is totally usable here and maybe another encoding is valid for pypy
it also doesn't work in Python 2
Traceback (most recent call last):
File ".code.tio", line 2, in <module>
£M
NameError: name 'BpBrBiBnBt' is not defined
i'm just going off of TIO
It doesn't work for any of the five python 2 implementations on there
turns out there was actually a crack on that original SE answer
and that used a latin encoding instead of cp037
nice
Yeah, not sure why python2/pypy are not behaving well when they attempt to run cp037 encoded py files. The repeated "B" indicates that perhaps they're not translating between utf16 and ascii properly
out of curiousity, how did you convert between the encodings?
to get the thing that you made
.encode("cp037")
oh wow i'm dumb
cya
Is there a list of accepted source code encodings somewhere? My Google Fu is failing me.
could be the same as https://docs.python.org/3.7/library/codecs.html#standard-encodings
The PEP said something about utf-16 not working, because you can't encode the file up to that point in utf-16 and have it still pass the utf-8 coding: check.
It might also be implementation dependant up to a point.
Is there a way to set python's __debug__ to False? So asserts wouldn’t do their job
@marsh void like -o
This looks like a job for... ctypes!
>>> import dis
>>> dis.dis('__debug__')
1 0 LOAD_CONST 0 (True)
2 RETURN_VALUE```
hmm
>>> assert = lambda *args, **kwargs: None
File "<stdin>", line 1
assert = lambda *args, **kwargs: None
^
SyntaxError: invalid syntax```
yep
The goal was to overwrite __debug__ though
But it's impossible iirc
actually hmm
It's classified as a constant like None, True and False. Probably for the specific reason that it ensures you can strip those branches safely in the "optimised" compile.
Though all four are in builtins like the other names.
>>> from ctypes import py_object, sizeof, c_size_t
>>> py_object.from_address(id(__debug__)+sizeof(c_size_t)).value = False
>>> bool(__debug__)
segmentation fault
``` lol
you changed the type of __debug__ to False
Oh yeah that's gonna cause issues lmao
Make a type that has bool as it's base but make it always be false
bool cannot be subclassed
Yeah I just noticed that
f"{(lambda f:lambda n: 1 if n==0 else n*f(f)(n-1))(lambda f: lambda n: 1 if n==0 else n*f(f)(n-1))(4)}"
one line factorial function without a self-reference, taken from this excellent talk on lambda calculus : https://www.youtube.com/watch?v=pkCLMl0e_0k
"Speaker: David Beazley These days, programming style guides are all the rage. However, what if your style guide was so restrictive that it only gave you sin...
Haha yeah my dumb
Y = lambda f:(lambda x: f(lambda z:x(x)(z)))(lambda x:f(lambda z:x(x)(z)))
R = lambda f:lambda n: 1 if n==0 else n*f(n-1)
Y(R)(3)
6
looks like this with the Y-combinator
or fibonacci:
R1 = lambda f: lambda n: 1 if n <= 2 else f(n-1) + f(n-2)
Y(R1)(6)
8
Y(R1)(7)
13
Y(R1)(8)
21
There is a great book called "Introduction to Lambda Calculus"
by Henk Barendregt and Erik Barendsen. it's available as a pdf.
here's my notes from the talk https://gist.github.com/salt-die/1b40b695cc17ffcf2a7d2cbbbffe0474
the real take away is how tf do i get my python environment to do what his does: use actual λ for lambda and . for :
If you want to experiment with lambda calculus, you could use some online lambda-reduction service.
@zealous widget
By the way, you might want to check this out:
https://repl.it/@int6h/GlorifiedLambdaCalculus
neat
Oh, it's a lisp, isn't it.
Well, the syntax is borrowed from lisp (almost)
Lots of Incredibly Silly Parentheses
Some would argue it's better than using indentation.
Isn't processing a tree easier for humans if it's in 2D rather than in 1D?
Or are you talking about indentation in python?
i think indentation is easier to parse, but i like how lisp looks anyway
if i have multiple decorators, what order are they taken? can i have multiple decorates even?
seems like another fun way to build up lambda functions
Yes, you can apply multiple decorators. They are applied in an upwards direction.
- I added barendregt numerals example (EXAMPLES folder)
In [224]: @SUCCESSOR
...: def THREE(f):
...: return lambda x: f(f(x)) #Definition of TWO
...:
In [225]: show(THREE)
3
can decorate with SUCCESSOR
This decorator will seem inappropriate out of context...
No worries, succ is a standard name for a successor function, no need to change it :)
In [227]: @SUCCESSOR
...: @SUCCESSOR
...: @SUCCESSOR
...: def THREE(f):
...: return lambda x: x #ZERO
...:
In [228]: show(THREE)
3
this actually worked
black_hole = []
def explode(*args, **kwargs):
global black_hole
for function in black_hole:
try:
function(*args, **kwargs)
except BaseException:
pass
def SUCC(func):
global black_hole
black_hole.append(func)
return explode
that looks dangerous
Well, who said that black holes are safe?
File "<stdin>", line 5 in explode
File "<stdin>", line 5 in explode
File "<stdin>", line 5 in explode
File "<stdin>", line 5 in explode
File "<stdin>", line 5 in explode
File "<stdin>", line 5 in explode
File "<stdin>", line 5 in explode
File "<stdin>", line 5 in explode
File "<stdin>", line 5 in explode
File "<stdin>", line 5 in explode
File "<stdin>", line 5 in explode
File "<stdin>", line 5 in explode
...
Aborted (core dumped)
it was fine until I try to call the functions
!e ```python
black_hole = []
def explode(*args, **kwargs):
for function in black_hole:
try:function(*args, **kwargs)
except BaseException:pass
def SUCC(func):
global black_hole
black_hole.append(func)
return explode
@SUCC
def hello_world(name, *args, **kwargs):
print("Hello,", name)
@SUCC
def hello_underworld(name, *args, **kwargs):
black_hole.append(hello_underworld)
print("Hello,", name, ">:)")
hello_world("Python")
hello_world("Python")
hello_world("Python")
@formal sandal Your eval job has completed with return code 139 (SIGSEGV).
001 | Hello, Python
002 | Hello, Python >:)
003 | Hello, Python
004 | Hello, Python >:)
005 | Hello, Python
006 | Hello, Python >:)
007 | Hello, Python
008 | Hello, Python >:)
009 | Hello, Python
010 | Hello, Python >:)
... (truncated - too many lines)
Full output: too long to upload
i gave it some lambda functions at first and it didn't explode
i thought i was safe
Sorry if it damaged your functions :(
no worries, i opened a separate terminal for it
Have you tried my lambda interpreter? Is it usable?
oh, i don't know, i just poked around the files, i don't know how to use it
If you want, you can skim through the tutorial (but press preview!)
The program is read from 'program.lambda', as the doctring in main.py says.
took me a few tries:
fib = (fn <n> => (if (lt n 3) 1 (add (fib (sub n 2)) (fib (sub n 1)))))
main = (fib 7)
i vaguely remember lisp, but i haven't played with it in forever
@zealous widget look at plam or lci if you want an actual lambda calculus reducer
i don't even know what that is or why i would want one
This is not lisp at all, it just looks kinda like lisp, and the (func arg1 arg2 ...) syntax is preserved.
I think modifying grammar.lark is enough to make it look more like haskell or something.
I haven't used it for anything complex or ambiguous yet.
the guy who's talk i linked had his interpreter actually using λxy.x(y) or whatever
which is dope
are you sure that was python and not an actual lambda calculus reducer?
@formal sandal that GLC looks pretty impressive
hmm, this exists https://docs.python.org/3/library/custominterp.html
Cool
Maybe one could make it switch modes like a Julia interpreter.
@pure dew I'm happy that you liked it.
But I'm totally clueless about how to make it optimize tail recursion.
@formal sandal Or even better, optimize closuring.
It is possible to turn this:
λb.(a+b) with closure: a = 1
into this
λb.(1+b)
lisp is why
(why (is lisp))
@grave rover Is there a quick and easy explanation of the marshal format anywhere?
Uhhh
1 byte identifier (see ceval.c to see what it represents) and then a variable number of arts based on what it needs
i.e. strings have <id><length (4 bytes?)><string in utf8>
@pure dew hope that explains ish
@formal sandal thanks for the note on closurevars, would make a nice addition to my optimizer decorator
oh i was looking at marshal.c
>>> import marshal
>>> marshal.dumps("abcdef")
b'\xda\x06abcdef'
>>> import struct
>>> string_dmp = marshal.dumps("abcdef")
>>> id, size = struct.unpack("BB", string_dmp[:2])
>>> struct.unpack(f"{size}s", string_dmp[2:])
(b'abcdef',)```
im just looking for ideas for an efficient bytecode format
What purpose?
my toylang
Hm
For numbers I recommend 2s complement
Decimals as Floating Point
Mantissa and Exponent would ideally follow IEEE
but im also considering an llvm backend
Hm
or both, like ghc(i)
I personally would recommend seeing if it can easily be transpiled to ASM and then compiled by GCC
you want me to write a lazy list impl in asm?
Not like it hasn't been done before
People can write brainfuck to machine code compilers in asm
Well, I got more.r
I got more.
This time, it's an alternative to asyncio
My custom tasks + anony = asyncio alternative
anony allows functions which can be stepped
tasks allows running those functions concurrently
and the syntax looks like this
this = TaskHandler(
function (
iterate('x', range(25)) (
anony.print(var('x'))
)
),
function (
iterate('x', range(25)) (
anony.print(var('x'))
)
),
function (
iterate('x', range(25)) (
anony.print(var('x'))
)
),
)
this.run()```
fully in python
Do you see any threads?
making an event loop is a tad easier than communicating with the os for threads
tbf i dont see any event loop either
Maybe you could use pdb and step through normal functions?
is that in stdlib?
@pure dew How is it a threading alternative over asyncio
TaskHandler is essentially an asyncio event loop
@formal sandal Pdb makes it step through interactive input, not actual python
neat
Yeah, Ø is a letter whereas \infty isn't.
>>> @new_method(object)
... def assign(self, var):
... globals()[var] = self
``` 🤔
What have you done to my favourite language?
(Well, second favourite. But this is more a hack than a scheme.)
new_method = lambda cls,name=None:lambda func,c=__import__('ctypes'):c.py_object.from_address(id(cls.__dict__)+c.sizeof(c.c_size_t)*2).value.__setitem__(name or func.__name__,func)``` @marsh void this is my onelined @ new_method. how does yours look?
Almost like yours
I mean, exactly like yours
But I didn’t use sizeof though, gotta add it
project idea: forbiddenfruit that doesn't rely on implementation details
or does but just autodetects the impl
trying to come up with the fastest method for merging multiple dicts and applying a function to every value
so far nothing seems as performant as ```python
{x: mut(y) for x, y in {**foo, **bar}.items()}
which feels inherently wrong since i'm having to construct a dict twice in order to get the final value
i though about using itertools.chain but that turned out to be slower
{x: mut(y) for x, y in chain(foo.items(), bar.items())}
The 1st is the fastest
{x: mut(y) for i in (foo.items(), bar.items()) for x, y in i}```?
or py {x: mut(y) for d in (foo, bar) for x, y in d.items()}
both of these will be about 2x slower for small dicts
for larger dicts (10s of thousands of elements) they are roughly the same speed
maybe if you get to 100ks they'll be faster
but at that point python dict is probably not what you want in the first place
you think it's faster to update then apply a function?
I wanted to test it but couldn't figure out a feasible test env
the answer is "maybe"
but like there's really no point in micro-optimizing this
i.e.
(x:f(x) for x in my_dict.update(my_dict2))
that would try to iterate None
update is in-place
for big dicts it doesn't matter because the iteration and applying the functions takes most of the time
right, #psuedo
for small dicts it doesn't matter because it's already so fast, and you probably didn't even micro-benchmark that the dict combining is actually a significant portion of your performance loss
my_dict.update(my_dict2)
arr = np.array([*my_dict.values()])
f(arr)
I improved the code
this = TaskHandler()
out = this.run_until_complete(gather(
function (
anony.print('1'),
anony.print('2'),
result(4)
), function (
anony.print('1'),
anony.print('2'),
result(5)
)
))
>>> 1
>>> 1
>>> 2
>>> 2
print(out)
>>> OrderedDict([(<function anonymous_function>, 4), (<function anonymous_function>, 5)])
Yeah it's really splitting hairs for most purposes. I got into it because I'm implementing a subclass of dict that does some processing on the values and wanted to see where I could optimize the instantiation.
arguably the most expensive piece is actually the applied function, which recurses on containers
Solve the equation x^3 -7x^2 +5x -3=0 ? help please
Is that related to python? looks like a normal equation that's neither python or esoteric related
from numpy import roots
def solve(coeff):
solution = roots(coeff)
for v in solution:
print(f"({v:.2f}, 0.00)", end=" ")
print()
solve([1,-7,5,-3])
>>> (6.28+0.00j, 0.00) (0.36+0.59j, 0.00) (0.36-0.59j, 0.00)
@dusty hearth
@grizzled cloak thank u
If you need an exact anwser, you could use sympy.
@hollow patrol Does this thing support functional programming?
The one I made with the tasks, @formal sandal ?
I would say, yes.
It supports a lot of functional programming
Exception Handling
Conditionals
Iteration
While Loops
And etc
So it definently does support some functional programming
Also, variables too
Well, variables, iteration, exception handling and while loops are probably the opposite of functional programming...
Do you have some kind of lazy evaluation?
true = function(x, y){return x}
false = function(x, y){return y}
iszero = function(n){
if (n == 0){
return true
}else{
return false
}
}
factorial = function(f, n, a){
return f(n)(a, factorial(n-1, n*a))
}
real_factorial = function(n){return factorial(is_zero, n, 1)}
Can you make a thing like this that wouldn't go into infinite recursion?
i'd hazard a guess at no if its pure python
It is not python lol
I was talking about anony.
Well, it doesn't have to replicate python exactly.
It is python
I was under the impression he build it on top of python
Yes, that's true.
function (
anony.print('1'),
anony.print('2'),
result(5)
)```
And I do have lazy evaluation
how'd you do that?
A method on a var('x') object returns an anony_operation
oh
so var('x') + 5 returns an anony_operation
var('x') == 5 returns an anony_operation
which is called when the condition is to be checked
not bad
also
So you reduce from the left?
I.e. if you have an expression like call(function, arguments), you evaluate function first?
I think
I'm wondering how to implement pure laziness in my toylang
Anony functions have to be executed like this
output = list(anony_function())[-1].output```
Each iteration of an anony function is a step
Calling an anony function with arguments returns a generator
Each iteration of the generator is one step of anony
And a return value of anony function is a ReturnResult object
The ReturnResult's output attribute is well... its output.
Is it possible to treat anony_function as a callable?
I mean, in the context of another anony_function.
Like
Like, call an argument.
anony_func_two() calls anony_func_one() inside of it?
You'd have to use anony iteration to do that probably
What do you mean call an argument?
def call_me(f, x):
return f(x)
Oh right
Anony can take in other anony functions as arguments
But unfortunately, you wouldn't be able to call one like that since anony uses a special calling system
When I implement anony's new system you'll be able to do something like
call_me = function('f', 'x') (
result(var('f').call())
)```
var is an anony.anonymous object, so it has to use its own call method to manage its arguments
However, a call() method like that might be added
Which would return an anony_operation
@formal sandal so yes, that will be added
Also
Note that anony_operation and anony_part objects are turned into regular objects lazily when they are used as arguments
reminds me of when i implemented my own programming language entirely in python syntax
automatically ran too, didn't need to do any sort of other stuff to get it to work
yeah
anony also allows for concurrency
anony_handler = TaskHandler()
anony_handler.run_until_complete(gather(
anony_func_one,
anony_func_two
))```
Maybe we could collect all of our toy languages, randomly form them into pairs (A, B) where A != B and make transpilers from A to B 🤔
🙂
I have another toylang
but it's not in python syntax
one more thing
in anony
you have to fix a module/class/function to use it in an anonymous function
anony.print is equal to anony.fix(print)
but it's a shorthand
anony.sleep is essentially equal to anony.fix(time.sleep)
import esolang
PROGRAM [
INCLUDE: "core",
PUSH: FUNCTION [
SHOULD (ARGS != 1) [
PUSH: "factorial only takes one argument",
ERROR,
],
POP: number,
# return 1 if we've reached the end
SHOULD (number <= 1) [
PUSH: 1,
FINISH,
],
# else, do the factorial recursion
OTHERWISE [
PUSH: factorial,
PUSH: number - 1,
CALL: 1,
PUSH: number * POP,
FINISH,
]
],
POP: factorial,
# main part of the program...
PUSH: FUNCTION[
PUSH: core.print,
PUSH: "Result:",
PUSH: factorial,
PUSH: core.int,
PUSH: core.input,
PUSH: "Enter a number: ",
CALL: 1,
CALL: 1,
CALL: 1,
CALL: 2,
],
CALL: 0,
]
this was my programming language
of course, the esolang module imported at the top is what makes it work
it's not altering the syntax at all
python won't give you a syntax error with that
so the import esolang code is allowed to run
Don't you have to from esolang import *?
nope
esolang executes the rest of the program and then exits before it gets actually ran as python
indeed it does
How do you get the globalscode from the importing module?
the esolang module works by fetching the script it was imported from, then converting it into valid working python, then running it
you don't
oh
for getting the code, probably inspect?
i guess sys._getframe will get you the module and then you can inspect.whateveritwas on it and get the code
nope i don't think so
how do you do it then
import __main__
from esolang.compiler import compile_source
if __name__ == "__main__":
print("This script must be imported! :(")
exit()
# read the source of the file that imported this script
with open(__main__.__file__) as file:
source = file.read().replace("import esolang", "").strip()
py_source = compile_source(source)
exec(py_source, vars(__main__))
# stop the rest of the script.
exit(0)
I would think you could get __code__ off of it, and parse that into an Ast, but
oh
i mean
__main__.__file__
look for yourself: https://gitlab.com/kingdom5500/esolang/tree/master/
oh
So you're using __getitem__ and interpret the item as a program?
no, there's no __getitem__ involved
Neat, didn't think of that
yeah, no __getitem__ at all
it just so happens that my syntax exploits the __getitem__ syntax for defining blocks of its code
Since you only use __file__, and that's defined at the beginning, you don't get an unresolvable import loop
big brain 
@formal sandal the important thing to notice is that the python interpreter never actually reaches the first line of that funky syntax. the import esolang reads the script, translates it to python, runs it, then exits.
Yes, I understand that.
Maybe I could transform my toylang to do that...
Since there are only 5 syntactic elements.
Not counting comments.
here yall are talking about syntax abuse while I just switched my impl to Rust
Maybe it would be even cooler if you made a functional language.
Like
factorial(n)[n<2] == 1
factorial(n) == (n * factorial(n - 1))
This is valid python...
you're either gonna have to do some insanely crazy runtime hacks or just use ast
Well, of course it will use ast.
But factorial(n) = 1 isn't.
So... no ast.
However, factorial(n)[:] = 1 is.
Or factorial(n)[True] = 1
Also this:
factorial(n) is 1
but it's super weird.
factorial(n)[n<2] @ 1
factorial(n) @ n * factorial(n - 1)
valid
and for static types https://docs.python.org/3/library/typing.html#callable
looks a touch odd, but not too bad and is better than putting an empty slice after default branches
# this looks ugly too, but still works
factorial = lambda n=[n<2]: 1
I'm used to Haskell's pattern matching, so that just seems weird to me
i'm dumb
ast.parse
That's a syntax error, ast will not tolerate it.
with sum([]):
0
with sum([x | xs]):
x + sum(xs)
the bare 0?
Maybe you could replace all the def or fn tokens with with, and only then give it to ast.
Yes
An expression can be a statement.
OH
this is valid line-by-line and as a whole
factorial : Callable[[int], int]
factorial(n)[n<2] @ 1
factorial(n) @ n * factorial(n - 1)
haskell in python
So it should be transformed into something like this:
def factorial(n: int) -> Callable[[int], int]:
if not isinstance(n, int):
raise TypeError
if n < 2:
return 1
else:
return n * factorial(n - 1)
That makes sense.
We would need to implement infinite lists as well.
But it's not that hard.
(not as hard as making a whole haskell compiler)
I'll get back to you on infinite lists once i get it done for my toylang
err, ranges/generators would be infinite, not so much lists, yea?
Maybe it's just a range, but start and end are allowed to be infinite.
yea
a list would be a literal, basically
haskell lists and ranges are more or less the same tho
aight good talk, i gotta get back to work
we can hack on this later
make it an #esoteric-python group project or smth
Yay, it works!
my toylang | python
Actually...
I don't need to make built-in lists and strings.
I can just transform the syntactic sugar of a list while transpiling!
(strings will be linked lists, such a great idea!
hello = (fn<index> => (if (eq index 0) 'h' (if (eq index 1) 'e' (if (eq index 2) 'l' (if (eq index 3) 'l' (if (eq index 4) 'o' 0))))))```
This is worse than a linked list!
Now you can do laziness in python!
don't know if anyone else cares but was curious about something ```py
import sys
module = type(sys)
class M(module):
... @property
... def prop(self):
... print('access')
... return 42
...
sys.modules['m']=M('m')
from m import prop
access
from m import prop as a, prop as b
access
access```
You can do this in 3.7 with a module-level __getattr__ :-)
Yeah but not on <3.7
Theme: get a True. Go wild!
bool((lambda x:x/x==x/x)(__import__('sys').float_info.max*10)^1)
@formal sandal https://totally-not.a-sketchy.site/VFx17HB.png
Would a bitwise OR not work?
oh
Instead of the @, I mean
hm
I think it would.
Because there is no other operator to mess up the evaluation order.
I don't know Haskell, but from memory that's how they do it in... ML? Something similar to ML.
They use a pipe.
Pipe.
factorial : Callable[[int], int]
factorial(n)[n<2] | 1
factorial(n) | n * factorial(n - 1)
``` is valid ast too
Maybe we could make a piped language!
Oh dear
It would be functional too, but it would consist of a single pipe!
that snippet looks like my lark grammar files
A single pipe from I to O.
Is Lark (or EBNF in general) turing-complete by the way?
Well, it's built on top of LALR (if you choose LALR).
And it's a finite state machine, so there is a chance it's turing complete.
the parser is, yes
but the actual grammar is just like json
i thought you meant the grammar since you said ebnf too
Yes.
But a grammar can produce a finite state machine, so...
The difficult thing is: what is the output?
Stdout?
an ast
Oh
at that point its not longer handled by lark
Maybe we could allow making a transformer that is only allowed to add a single character per rule to a string?
what do you mean?
Can it substitute the other characters?
I mean, there is some string. And when a (a method of) lark.Transformer sees some rule, it can add a predefined character to that string.
But the point is to kinda restrict it.
@snow beacon Actually this makes more sense.
Makes it more like an actual Turing machine.
With a tape.
# Flatten subscript_list node
@v_args(tree=True)
def index(self, tree):
tree.children = [
tree.children[0],
*tree.children[1].children
]
return tree
``` here's one of my transformer methods
o wait i think i misunderstood
you mean manipulating a global variable each time the transformer hits a node?
Something like this.
Or you could define an attribute of a transformer object to avoid globals.
Like
@v_args(inline=True)
def rule(self, *args):
self.accumulator += "z"
Or maybe make it substitute characters in the initial string.
You could do this using the propagate_positions optional argument for lark.Lark.
or
But it's still not a turing machine.
you can interpret a language entirely using the transformer
simpler ones are easier tho
you don't need propagate_positions tho, you can just edit the ast node directly
unless you're trying to have the program edit its own source code
Well, that's too easy. You could store some state in a transformer, and when you hit $END (I guess that's possible to detect?), call a real interpreter/compiler.
But that's probably cheating.
Or do you mean interpret while transforming?
one sec, lemme find his example
It would be easier with a stack-based language, where a program can be described as a sequence of single-token operations.
single token? no you have access to the whole tree
his is a little simplistic, but you really can just edit the tree in place and reduce it down to a literal
You could parse a lambda-term like this 🤔
the transformer goes bottom up btw
or s-expressions
oh man
although, with lambda terms, you'd have to watch out for conflicting names
You could work around that, I think.
that kinda makes me wanna breakout my py-lci parser and rework it around a transformer
Well, the notation lambda x -> (lambda x -> x) is ambiguous, isn't it? So it's incorrect.
The transformer can probably use scoping rules to differentiate names.
Does it work with name collision?
https://repl.it/@int6h/GlorifiedLambdaCalculus -> core.py
It is what it says it is, so...
This is roughly how it works:
There is a global scope (not needed if doing pure lambda calculus with a single term).
A scope is just a mapping (name => object)
Each expression is either a prototype or a concrete expression.
Prototypes are subexpressions of functions.
A concrete expression is a prototype with a Scope attached to it:
Like:
# here (add x 1) is a prototype
add_one = (fn <x> => (add x 1))
number = (add_one 7)
when you reduce number, it will be:
number = (add x 1) ~> {"x": 1} ~> global
And if you have nested scopes, it will be like this:
term = (complicated_expression) ~> {closure} ~> {closure} ~> ... ~> global
Name resolution works like in most dynamic languages: it searches through the scopes from the innermost one to the outermost (global) one. So if global also has an "x", it doesn't screw things up.
You could then optimize the evaluation, but I didn't to allow people to examine what actually happened (and because I'm lazy).
Well, it's a superset of lambda calculus.
I think if you disallow multiple arguments (or convert functions using them to nested single-argument functions) and self-reference by name, you can then remove the scopes one by one and get to a single huge lambda-term.
Hm...
If you think about it, Scope (not counting the global scope) just represents the result of an application.
So you can just pick the names from the scopes, find them in a non-reduced version of a term and substitute them.
// lambda calculus lark grammar
start : expr
expr : ident
| "(" ident ")"
| abstract
| application
abstract : ("λ" | "\\") ident "." expr
application : abstract expr
hvar : NAME
ident : NAME
NAME: /[^\.\\\\λ]/
%import common.WS
%ignore WS
λx.a b
start
expr
application
abstract
ident x
expr
ident a
expr
ident b
Shouldn't it be an abstraction of an application instead?
it doesnt support the sugar for currying or anything
no
the application is (λx.a) b
the abstraction is λx.a
idk, my terms may be backwards
These names are weird. I would say "consumes everything to the right [until a parenthesis]" or "right-consuming".
Alright, I gotta sleep
It's 1:21 here
got it
// lambda calculus lark grammar
start : expr
expr : ident
| "(" ident ")"
| abstract
| application
abstract : ("λ" | "\\") ident "." expr
application : expr expr
hvar : NAME
ident : NAME
NAME: /[^\.\\\s\λ]/
%import common.WS
%ignore WS
λx.a b
start
expr
abstract
ident x
expr
application
expr
ident a
expr
ident b
hello world
import javar
class test:
def main():
for x in range(3):
print(x)
>>> 0
>>> 1
>>> 2```
I'm in a quest to make Python more like java
Because Why Not?
@hollow patrol anyway, this makes a totally valid python ast
factorial : Callable[[int], int]
factorial(n)[n<2] | 1
factorial(n) | n * factorial(n - 1)
but looks extremely similar to haskell
each line is a valid python statement
(syntactically, they don't mean anything reasonable)
the plan was just to take the ast and rebuild it into a different ast
with strict type checking
yea that code would error if you tried to execute it as python, but syntactically its valid
(meaning we can just skip on the responsibility of parsing and tree-building :D)
neat
So this is valid too:
test : Callable[[Int], Int]
test(n)[n%2==0] | n ** 2
test(3) | 19
test(n)[n>5] | n / 2
test (_) | 3
@hollow patrol :D
I just found something awesome
peachpy is a thing to write python as assembly
so
let's make a decorator that turns a function into asm
To write python.. as assembly?!
yea
# These two lines are not needed for PeachPy, but will help you get autocompletion in good code editors
from peachpy import *
from peachpy.x86_64 import *
# Lets write a function float DotProduct(const float* x, const float* y)
# If you want maximum cross-platform compatibility, arguments must have names
x = Argument(ptr(const_float_), name="x")
# If name is not specified, it is auto-detected
y = Argument(ptr(const_float_))
# Everything inside the `with` statement is function body
with Function("DotProduct", (x, y), float_,
# Enable instructions up to SSE4.2
# PeachPy will report error if you accidentially use a newer instruction
target=uarch.default + isa.sse4_2):
# Request two 64-bit general-purpose registers. No need to specify exact names.
reg_x, reg_y = GeneralPurposeRegister64(), GeneralPurposeRegister64()
# This is a cross-platform way to load arguments. PeachPy will map it to something proper later.
LOAD.ARGUMENT(reg_x, x)
LOAD.ARGUMENT(reg_y, y)
# Also request a virtual 128-bit SIMD register...
xmm_x = XMMRegister()
# ...and fill it with data
MOVAPS(xmm_x, [reg_x])
# It is fine to mix virtual and physical (xmm0-xmm15) registers in the same code
MOVAPS(xmm2, [reg_y])
# Execute dot product instruction, put result into xmm_x
DPPS(xmm_x, xmm2, 0xF1)
# This is a cross-platform way to return results. PeachPy will take care of ABI specifics.
RETURN(xmm_x)```
Reminds me of Web Assembly Text, which is like assembly, but Lisp. And also made of javascript.
can one subclass function --- or is there a way to override () so that my_func()() would call my_func twice
@zealous widget You can't subclass function
But you can give an instance a __call__ method
that's interesting
class a:
def __call__(self):
print(555)
this = a()
this()
>>> 555```
@zealous widget like that
is it __new__ that lets me return something
You could always return the same function. Something like:
that's a bit how i've approached this problem
this is a codewarrior challenge that seems a bit esoteric to me, but i think i've cracked it
__call__ was enough to really do it
@zealous widget Yes, __new__ allows you to return something and can work a bit like that a function of Xavi there.
!e
class A:
def __new__(cls, *args, **kwargs):
print("from __new__")
return cls
A()()()()()()
@nocturne saddle Your eval job has completed with return code 0.
001 | from __new__
002 | from __new__
003 | from __new__
004 | from __new__
005 | from __new__
006 | from __new__
this is the problem statement:
We want to create a function that will add numbers together when called in succession.
add(1)(2);
// returns 3
We also want to be able to continue to add numbers to our chain.
add(1)(2)(3); // 6
add(1)(2)(3)(4); // 10
add(1)(2)(3)(4)(5); // 15
and so on.
A single call should return the number passed in.
add(1); // 1
We should be able to store the returned values and reuse them.
var addTwo = add(2);
addTwo; // 2
addTwo + 5; // 7
addTwo(3); // 5
addTwo(3)(5); // 10
We can assume any number being passed in will be valid whole number.
this definitely took me a bit of time
Ah, yeah, that is an interesting coding puzzle
the solution is nice, but i think there are enough hints now, and i don't want to spoil it if anyone wants to give it a go
could have it return a class
def add(x):
v = x
print(v)
def inner(y):
nonlocal v
v += y
print(v)
return inner
return inner
>>> add(2)
2
<function add.<locals>.inner at 0x7f1aad61fef0>
>>> add(1)(2)(3)
1
3
6
<function add.<locals>.inner at 0x7f1aad61ff80>
>>> addTwo = add(2)
2
>>> addTwo(6)
8
<function add.<locals>.inner at 0x7f1aad622050>
cleaner solution: ```py
class add:
def init(self, x):
self.v = x
def __call__(self, y):
return add(self.v + y)
def __repr__(self):
return str(self.v)
@grave rover Needs the __add__ too:
addTwo + 5; // 7```
thonk
@grizzled cloak
nic
e
ah.
dont know if you need it but i added the __new__ method at some point.
class add:
def __init__(self, other):
self.value = other
def __call__(self, other):
return add(self.value + other)
def __new__(cls, *args, **kwargs):
return super(add, cls).__new__(cls)
def __repr__(self):
return str(self.value)
def __add__(self, other):
return self.value + other```
but other than that its the same as yours
That new does absolutely nothing lmao
that's close to my solution, but you can shorten it by subclassing
yeah that's why i said you probably dont need it.
i also have a solution that remembers the value across multiple calls because i misread the question the first time around haha
id really love some more speed/optimization challenges.
the last code jam's qualifier was my favorite so far. just so many esoteric things you could do with it.
hmm?
map(chr, (*range(x, y), *range(a, b), ...))
also i kinda feel like my solution is wrong because __repr__ returns a string not a number
Or who was it?
you mean for the code jam challenge?
dont really get how that works. what is in the ...?
some more ranges
what are x,y a,b
some digits
ahh the ascii codes right?
They like (I think she?) took all the ord values of characters and made some ranges
yeah
so x,y will be all upper case etc
i think ord maps ascii by default.
But yeah you can say ascii for simple stuff
I mean, that char implementation is different on different languages
Like, same codes may map to different characters
but how does map(chr, (*range(x, y), *range(a, b), ...)) make it random?
It just takes all the characters
it should only return abcdefg...ABCDE...0123...
ahh.
i did something similar, i used a translation table to convert a large random byte array to chars.
because generating random bytes is a lot faster than numbers
Oh, yep, makes sense
I didn’t know about random.choices() though
So I used for ... : random.choice()
most of the random lib is reaaalllly slow
hello guys
have you ever tried ctypes in python3?
is it worth to learn
i will also learn Clang with it
uh
ctypes isn't the c language
it just lets you mess with c types in python
for low level hijinks with the interpreter
so
i cannot use my python codes in C, also cannot use C in python?
are there any library for it?
ctypes allows you to call your own dlls but that just feels like overcomplicating stuff
not at all
but you just don't really use ctypes
Are you wanting to write C and python?
or you have something in C you need to access in python?
yeah, you dont need __repr__ at all, in fact, you only need 3 lines to solve the challenge
This is what I'd do:```python
class add(int):
def call(self, other=0):
return add(self + other)
Alternatively, python class add(int):__call__=lambda self, other=0:add(self + other)
add=type("",(int,),{"__call__":lambda self,other=0:add(self + other)})```
Not actually smaller lol
You can remove the whitespace around the +
lol
tfw monospace
If you want to make it even uglier you could also change the parameter names.
Try not to use Ms or Ws. They're wide.
accepted big brain variable names:
I, i, l, j, s, r
you don't need a default other=0
a single call will just __init__
or whatever ints do
i suppose something else since they're immutable
well that's just esoteric
You could probably extend it to sum whatever you put in the *args
like a + without a second argument
+a is valid python...
i feel like this type of class has a good use somewhere, but where, i don't know
esoteric idea time
It reminds me of hashlib md5 updates
Every time you call hash.update with something it changes the hash
it's my favorite thing i've seen in python in the last few months
Have you seen flail? It's similar to that.
that and defaultdicts, i have no idea how they eluded me for so long
Flail as in the module
someone find something wacky to do with call, matmul, and getitem/setitem
start chaining square brackets and parenthesis and @'s
Backstory: I've been working on implementing my toylang in Rust. I never used Rust that much before, so I'm learning a bit as I do this. I just wrote a macro to generate an enum definition and converter function (where i typed out an if-else for each variant) from a list of variant names. (enum_with_converter!(Return Constant Negate Add Subtract);)
Info: Rust macros affect the AST, unlike C macros which change the source code. Rust macros must be valid Rust syntax and must evaluate to a valid Rust AST node. See TLBORM (https://danielkeep.github.io/tlborm/book/index.html)
Idea: Using the ast module, create a system for AST-affecting macros in Python. Macros should be valid Python syntax and manipulate the AST, not the source code. Features, syntax, and implementation are entirely up to you
@brisk zenith I think this may be good enough for the challenge repo
You've described Hy pretty succinctly.
thx
challenge (I don't know if this is possible): make it so when you add an int and a tuple, it doesn't error and actually adds the length of the tuple to the int
eg:5 + (6, 7, 2) would be 8
In [151]: class weird(tuple):
...: def __add__(self, other):
...: return len(self) + other
...:
In [152]: weird((5,6,7)) + 6
Out[152]: 9
caveats here though, weird has to come first
or just implement a __radd__
fair enough
weird.__radd__ = weird.__add__
🤔
Why y’all using ` ` if you can escape with backslashes?
@marsh void because it looks more readable than normal text
In [157]: class bro:
...: def __matmul__(self, other):
...: print("bro")
...:
In [158]: dont = bro()
In [159]: me = bro()
In [160]: dont@me
bro
Hahaha
I know I've got a good idea for a Python program when line two is python class String(int):
lol
how about
Creating __iter__ and __len__ for int?
list(123) -> [1, 2, 3]; len(123) -> 3
It's for a devious programming language. (It won't be interpreted, but misinterpreted.) Strings are long curly things, with a length, so it makes sense for their length to be the important feature. That's why they're the numeric type of the language.
Bit will represent a bit of text, of course.
(The implementation will probably be perfectly normal Python so you won't see much of it in this channel.)
@gilded orchid
>>> 5 + (1)
6
>>> 5 + (1,2)
7
>>> 5 + (1,2,3)
8
>>> ```
but normal addition still works:
>>> 5+5
10```
The first one isn't a tuple, by the way.
what I'd like to see more is + on tuples creating a new tuple that includes what you try to add, (item, item) + (item,) looks bad 😄
imagine that isn't terribly hard to do
could you elaborate?
say you have a tuple (1, 2) and want to add 3 to it, you have to create a new tuple and then add that in
yep
What happens if you have ```python
((1, 2), (2, 3)) + (4, 5)
>>> ((1, 2), (2, 3)) + (4, 5)
((1, 2), (2, 3), (4, 5))```
So it overrides the original code.
what should the result be?
>>> ((1, 2), (2, 3)) + (4, 5)
((1, 2), (2, 3), 4, 5)
in a normal environment
Maybe you could also do
(1, 2, 3) * 4 == ((1, 4), (2, 4), (3, 4))
new and improved:
>>> (1,2)+3
(1, 2, 3)
>>> ((1, 2), (2, 3)) + (4, 5)
((1, 2), (2, 3), 4, 5)
>>> ```
what if you want to add the tuple to it though
((1, 2), (2, 3)) + ((4, 5),) ?
nice.
stupid question: why is the comma required there? i've come across something similar with tuples of length one befor ebut never thought about it much
!e
x = (1)
print(type(x), x)
y = (1,)
print(type(y), y)```
@formal sandal Your eval job has completed with return code 0.
001 | <class 'int'> 1
002 | <class 'tuple'> (1,)
Because the ( and ) don't have anything to do with creating a tuple actually.
Tuples are created with commas.
just helps to show it is a tuple
Ah, got it. Makes sense, ty.
the trailing comma may be a bit too inconspicuous
>>> x = 1,
>>> print(x)
(1,)```
>>> 5,7,
(5, 7)
>>> 5,7,,
SyntaxError: invalid syntax
>>>
challenge: makr it so the second one doesn't error
(but has the same result as the first one)
oh yeah nvm i'm dumb
challenge: make a code-art quine (so a quine that also works for the code-art challenge)
@pure dew Did you know that you could multiply transformers in lark-parser?
Where can it be useful?
# in Transformer class
def __mul__(self, other):
return TransformerChain(self, other)
...
class TransformerChain(object):
def __init__(self, *transformers):
self.transformers = transformers
def transform(self, tree):
for t in self.transformers:
tree = t.transform(tree)
return tree
def __mul__(self, other):
return TransformerChain(*self.transformers + (other,))
Challenge: make it so built ins like map and range return lists instead of generators
def map(whatever the actual signature is):
return builtins.map(whatever the actual signature is)
>>> __builtins__.map = (lambda map: lambda *a: list(map(*a)))(__builtins__.map)
>>> __builtins__.range = (lambda range: lambda *a: list(range(*a)))(__builtins__.range)
>>> map(int, '12345')
[1, 2, 3, 4, 5]
>>> range(3, 10)
[3, 4, 5, 6, 7, 8, 9]```
Challenge: make it so any error (in a REPL, not including syntax errors) doesn't get outputted
uhh
>>> import sys
>>> def hook(*_): pass
...
>>> sys.excepthook = hook
>>> raise ValueError
>>> raise BaseException
>>> import sys
>>> sys.excepthook = lambda *a: None
>>> 1/0
>>> raise BaseException
>>> )
>>>``` this kind of works but it includes syntax errors too
could just use some handling for syntaxerrors but that's not something horribly difficult
anyone know a better way of achieving this?
# i would like mapping to map from items' index to a customized no-arg function
mapping = {}
my_items = [1, 4, 21, 19]
def do_a_thing(item):
print("I am doing stuff for", item)
for index, item in enumerate(my_items):
# bind n to i early in the function parameters
def custom_func(n=item):
do_a_thing(n)
mapping[index] = custom_func
mapping[2]()
# this don't work :(
#for index, item in enumerate(my_items):
# mapping[index] = lambda: do_a_thing(item)
instead of py def custom_func(n=item): do_a_thing(n) mapping[index] = custom_func you could do py mapping[index] = (lambda n: lambda: do_a_thing(n))(item)
i'm not sure if that's better but it's more esoteric and you did ask in #esoteric-python :P
maybe wrong channel, but yeah I guess I was looking for a less esoteric looking way
anything that doesn't look like a hack until you stare at it for 30 seconds, 5cm away from your monitor
ok I guess partial is a way
mapping[index] = partial(do_a_thing, item)
oh yeah that works
clever lambda'ing though 😖
lambda is cool
functions > functions
🤔
expressions > statements
numbers > numerals
Lambda arguments > variables
One line > more than one line
Abusing ctypes and getting seg faults > anything else
What's the shortest way to decrement every item in a list?
numpy? 😛
so guessing not in place when you're going with map
Shorter: [x-1for x in l]
yes but why
code golf
Does anyone know of a way to make a < b < c automatically behave like (a < b) < c instead of (a < b) and (b < c)?
Context: I'm working on implementing generics: ```py
if name == "main":
@generic("A", "B")
class Pair:
x: "A"
y: "B"
def __init__(self, x, y):
self.x = x
self.y = y
def __iter__(self):
return iter([self.x, self.y])
p = Pair<(int, int)>(10, 5)
```but above here it's comparing Pair < (int, int) but also (int, int) > (10, 5) instead of using the custom class the former returns
p1 = Pair[int, int](10, 5)
p2 = Pair[int, str](100, "abc")
print(p1.__annotations__)
print(list(p1))
print(p2.__annotations__)
print(list(p2))
# == output ==
{'x': <class 'int'>, 'y': <class 'int'>}
[10, 5]
{'x': <class 'int'>, 'y': <class 'str'>}
[100, 'abc']
```here's the end result, not as clean as I'd hoped but it works
I mean
I can combine this with my function overloading library to enforce types 
if only there was a way to apply a decorator to all functions
@grave rover you can in classes
that'll eval as (Pair<int), (int>(5,6)) @pure dew
Using getatr I think.
because of equality order
it's an optimization python does
actually
it's just the chaining
a < b < c makes sense to be a < b && b < c
so thats what it does internally
Try that
Yeah on classes
I basically want to override behavior or function.__new__
Ah!
or wrap all functions with that
One sec
I can't curse the method because of how cpython internals work
same
@grave rover why cant you?
lets think about this
