#internals-and-peps

1 messages ยท Page 99 of 1

unkempt rock
#

yeah it does, But also very helpful

flat gazelle
#

I mean, builtin modules are generally wrong, but what about some internal modules or vendoring your own version of some library

brave badger
#

I suppose -O0 is a thing but ehhhh

raven ridge
#

Sounds like exhaustive testing

#

Static analysis tells you problems that may be able to occur, before they've occurred.

flat gazelle
#

what would do this do other than check for non-parent imports? There isn't a whole lot you can actually warn about, due to how flexible the python runtime is

visual shadow
#

Yeah. I think that's the elephant in the room isn't it

flat gazelle
#

hell, even 1 is 3, which is a warning, isn't guaranteed to be wrong

brave badger
visual shadow
#

The reason why C compiler warnings may "feel" more well covered is because the language syntax and specifications of C literally enable it to. That is something fundamentally different from python

unkempt rock
#

There will be a lot of usages

visual shadow
#

So, variable declarations for example, python can't flag that because python literally doesn't have such a notion

flat gazelle
#

redefinitions are often deliberate, if 0 is often used to quickly disable an if for testing

unkempt rock
flat gazelle
#

that's what unit tests are for

#

not some magic internal warnings

raven ridge
#

Yeah. "Dynamic analysis" just sounds like testing.

flat gazelle
#

!e

1 is 3
fallen slateBOT
#

@flat gazelle :white_check_mark: Your eval job has completed with return code 0.

<string>:1: SyntaxWarning: "is" with a literal. Did you mean "=="?
flat gazelle
#

this is a useful one

#

since as far as the python language spec is concerned, this is always False

#

also, consider if 0 inside an exec

visual shadow
#

I mean, there can always be logical errors that no software can save me from. You just need to write tests in that case, and also be diligent about it

unkempt rock
brave badger
#

It's a totally valid expression, albeit useless

visual shadow
#

Why should it?

flat gazelle
#

yes, because you may want to use that to exemplify some behaviour or inside exec

unkempt rock
visual shadow
#

So what? It's a valid statement.

unkempt rock
brave badger
#

At best there's probably some hypothetical mechanism from inlining literals like that

visual shadow
#

I suppose okay.. Maybe I see what you're asking for. You want a "hey, this might be something dumb" kind of thing

#

I'd say that's not the job of a compiler or even an interpreter

unkempt rock
visual shadow
#

And I'd say such a tool would catch the easy issues and give you a false sense of security

#

Because as I said earlier, you can't catch all logical errors

flat gazelle
#

ye, it could be a warning perhaps, though I wouldn't like it all that much. Keep in mind that exec and eval are things that are useful for quite a few things, and could generate such expressions

unkempt rock
flat gazelle
#

the thing about 1 is 4 is that it is wrong even in exec

visual shadow
#

So I don't think this is a good idea. I just don't see the benefit.

raven ridge
#

The interpreter can't tell when code is dead in most cases. Consider ```py
x = True
def foo():
if x:
print("something")

The interpreter has no idea if x is ever True.
visual shadow
#

I'm taking a hit on performance for a tool that will basically not give me much more benefit

flat gazelle
#

in the end, no amount of static analysis you can fit into python will replace testing

raven ridge
#

And we're just criticizing it.

flat gazelle
#

in the end, I don't think the python interpreter should try to do a better than static analysis tools

visual shadow
#

Aye. Also, this tool does exist. It's called code review. And even that fails ๐Ÿ˜…

flat gazelle
#

what it already does is mostly for beginners to quickly spot their errors

gilded grotto
#

Hii,Any one who does coding on platform like hackerearth?

unkempt rock
visual shadow
#

I hope you didn't feel this was an attack. Just a discussion being fleshed out

raven ridge
flat gazelle
#

what I do want to see are better syntax error than unkown syntax with the new parser

unkempt rock
visual shadow
#

Neither did godly. Hmm.

#

Implementation aka.. The actual tool or whatever that would be built

unkempt rock
#

Not related to this channel but converting help channel names from chemical names to food names was a good idea

brave badger
#

I'm not sure of other ways aside from hooking into the interpreter to perform some sort of dynamic analysis e.g. coverage.py, so I assumed the discussion centered around that. Apologies if I misunderstood what you meant

unkempt rock
#

Hooking into python interpreter to catch awful mistakes is good for teachers, Some stupid stmt can only get caught at runtime

visual shadow
#

Nah pure, I think that's a very logical "direction" to take, because you'd definitely have to talk about how to implement such a thing to turn it from just an idea into something practical. And then see the shortcomings if any.

visual shadow
#

Coverage.. Is that the same as pytest-cov?

raven ridge
#

You either need to be executing the code, or tracing through it. And most of what we've talked about isn't easy to do by tracing through the code.

spark magnet
visual shadow
#

Ah I see. Very recently got introduced to that

unkempt rock
visual shadow
#

I assume it's using some kind of trace to figure out which lines ran

brave badger
#

I never really understood the sorcery behind it, just that the general idea that it did tracing by latching on to CPython or something similar

spark magnet
visual shadow
#

What surprised me was that it understood that 3 lines separated by brackets was 1 statement. How does that work?

spark magnet
#

can you show the code?

visual shadow
#

Hm, not atm since I'm on phone

unkempt rock
visual shadow
#

It was basically a function call

raven ridge
#

Just ```py
if (
1
+ 2
== 3)

visual shadow
#

In my case it was even simpler, just args spread across diff lines

visual shadow
spark magnet
unkempt rock
spark magnet
#

if there are questions not answered on that page, I can update it

unkempt rock
#

Anyway, Had a nice time with all of you (I have to go and do magic a bit), bye!

visual shadow
#

Luckily, compiled Python files (.pyc files) have a table of line numbers in them. Coverage.py reads this table to get the set of executable lines, with a little more source analysis to leave out things like docstrings.

#

Thanks Ned! That pretty much answered the question I had in my head

#

Even though I didn't know how to phrase it. I was misassuming it reads the source py file

brave badger
#

Thanks as well, I suppose I could apply one or two things there if I ever found the motivation to try and implement a toy language again

visual shadow
#

Yeah the tracing thing was something I had found out in a pycon talk video (I think?), and it's a bit scary how powerful it is

#

The talk was about ways to hack together python while debugging to get the answers you needed. Such as when trying to determine what all places were calling a function for example

#

Let me see if I can find it.

spark magnet
visual shadow
#

Nice, looking forward to checking it out

#

Oh gosh, it was literally you Ned. ๐Ÿ˜…

#

Unfortunately that video recoding did have a lot of problems, but it was super insightful

spark magnet
#

oh! that one too.

visual shadow
#

But.. Uh.. Yeah, that was the video I had seen recently. I suppose this wouldn't bring any new insights to you ๐Ÿ˜‰

spark magnet
#

that's the time i went 7 minutes over my 25-minute time limit ๐Ÿ˜ฆ

visual shadow
#

I'm sure there's people who wish you had kept going

grave jolt
#

!e
lemon_pleased

import json

def use_json(foo, *, json=json):
    return json.dumps({"bar": foo})

del json

print(use_json(42))
print(json)
fallen slateBOT
#

@grave jolt :x: Your eval job has completed with return code 1.

001 | {"bar": 42}
002 | Traceback (most recent call last):
003 |   File "<string>", line 9, in <module>
004 | NameError: name 'json' is not defined
brave badger
#

I have an idea

feral cedar
#

@grave jolt that's evil

undone hare
#

I'm assuming that it is because globals are resolved when the code object is created?

peak spoke
#

It uses json from the default arg, which is created at definition

visual shadow
#

So the default arg json gets tied to the function object

undone hare
#

Aaahhhh

#

I am blind

unkempt rock
#

def strStripAll(s,ss):
    return ''.join([c for c in s if c not in ss])
radiant fulcrum
unkempt rock
#

try it ๐Ÿ™‚

#

.replace replace one str with another ... not stripping

unkempt rock
#

so?

def strStripAll(s,ss):
    return ''.join([c for c in s if c not in ss])

s = 'q werty  1234567890'
ss4 = strStripAll(s,'97 w')
ss5 = s.replace('97 ','')
ss6 = s.replace('9','').replace('7','').replace(' ','').replace('w','')
deep crow
#

how to avoid PermissionError when using tempfile? I want to know how to do it with chmod.Please don't tell run as administrator because that is not a reliable solution. I m on windows . So I cannot use chmod. It would be some win32 api function

molten kayak
#

how tf does python calculate this: print(2**256) since that's 257 bit computing??? and quickly at that?

#

okay i tried print(2**(2**256)) which didnt produce an answer since i had to shutdown IDLE

#

3+Gb of ram usage lmao

sacred yew
molten kayak
#

what does that mean?

#

and how?..

sacred yew
#

iirc it stores integers as an array of int32s

#

arbitrary sized = there's no max val

raven ridge
#

Of which it uses 30 bits from each.

sacred yew
#

each int32s is basically a digit

molten kayak
#

does it use 32 bit integers for compatibility instead of 64?

raven ridge
#

In base 2**30

radiant fulcrum
grave jolt
#

I suppose that 32-bit ints are still faster to handle?..

#

(don't quote me)

radiant fulcrum
#

they are yeah

#

Not really a considerable amount though (compared to the rest of Python's overhead to worry about)

weary garden
#

64-bit ints might be faster on 64-bit CPUs, don't quote me on that

#

I might add an extension to my Python implementation to support native integers

flat gazelle
#

I think java devs measured this and it ends up so incredibly minor that there is very little reason not to use 64bit all the time

radiant fulcrum
#

pretty much

#

i hey! lets just use i128's all the time

raven ridge
#

32 bit CPUs handle 32 bit ints slightly, but not much, faster than 64 bit ints. 64 bit CPUs handle both about equally fast.

radiant fulcrum
#

As much as i like the fact python gives you the ability to have an arbitrary sized integer my god are they a pain for the interpreter implementation itself

#

Considering 99% of all python programs ran will never need anything bigger than a 64 bit int

spark magnet
#

but if you are going to implement arbitrary ints, then it just adds complexity to also have native-sized ints.

#

python 2 had both, and now python 3 only has arbitrary-size.

radiant fulcrum
#

True

#

Having both means you need to consider both possible types everytime you do something

spark magnet
#

right, and convert back and forth

grave jolt
#

imagine also typehinting that

radiant fulcrum
grave jolt
#

Haskell has both fixed-size and arbitrarily large integers. And it's so annoying to go back and forth, because different things return different integer types.

raven ridge
grave jolt
#

well, yes, not that bad

#

like AnyStr = Union[str, bytes] AnyStr = TypeVar("AnyStr", str, bytes)

raven ridge
#

right.

#

though - that's not what AnyStr is, fwiw

grave jolt
#

right

#

no

#

I'm wrong

#

it's TypeVar("AnyStr", str, bytes)

raven ridge
#

yeah. I realize you probably knew that, but it's a common bug I've had to correct my team on repeatedly...

#

using AnyStr where they meant Union[str, bytes] I mean.

grave jolt
#

seems like a bit of an unnecessary indirection tbh

#

like, you could just write

AnyStr = TypeVar("AnyStr", str, bytes)
#or:
S = TypeVar("S", str, bytes)
``` instead of ```py
from typing import AnyStr
oblique crystal
#

what is AnyStr?

weary garden
#

but with my architecture semantic concept folding will take care of converting between arbitrary and fixed sized ints

raven ridge
#

it's a type that can either be bytes or str, but needs to consistently be the same thing for every occurrence in the signature

#

so ```py
def concat(a: AnyStr, b: AnyStr) -> AnyStr:
return a + b

You can do `concat("a", "b")` or `concat(b"x", b"y")` but not `concat("x", b"y")`
raven ridge
weary garden
#

being slower and more complex may have been down to CPython's architecture more than anything else.

sacred yew
#

?

#

if you add conversions

#

it's going to be slower

raven ridge
#

At the level of arithmetic, there's nothing about CPython's architecture involved, beyond CPython's representation of an arbitrary sized integer.

weary garden
#

depends on when conversions happen

sacred yew
#

bc you'll need to check on every op if you need to convert

raven ridge
#

the conversions can't happen any sooner than the + operator is evaluated, because you can't know the sizes of the integers before that.

unkempt rock
#

they should go full BCD style !

raven ridge
#

there's decimal.Decimal for that.

weary garden
#

well if I add it as an extension I am effectively adding static typing to the language so I can do it before + is evaluated

sacred yew
#

um

#

idt that would work

unkempt rock
#

yes but it should be better integrated ...

grave jolt
#

are you going to do optimizations based on type hints?

weary garden
#

I have yet to research that aspect of Python

grave jolt
#

but you'are already planning to include static typing...

#

alright

#

nvm

raven ridge
#

no amount of static typing can tell you whether adding two specific int32 values together will give a result that fits in an int32.

sacred yew
#

^

grave jolt
#

also yes

weary garden
#

if you add two int32 then the result will always be int32 with possible overflow exception

raven ridge
#

then you've invented an entirely different language that behaves very differently than Python.

sacred yew
#

but then you'll need to check for overflow in order to convert to arbitrary sized ints

weary garden
#

I said it would be an "extension"

sacred yew
#

which makes it slower

weary garden
#

adding a check for overlow will be nowhere near as slow as the aribtrary sized integer stuff

raven ridge
#

I'm not certain that's true. Arbitrary sized integers that happen to fit in 2**30 should be only very slightly slower than regular 32 bit arithmetic.

grave jolt
#

well, arbitrary-sized ints already do that

#

otherwise, how do you know when to add a new chunk?

raven ridge
#

yeah. Exactly.

weary garden
#

except aribtrary sized integers neccessiate an extra level of indirection: a 32-bit int can be held in a register

grave jolt
#

that might be not that slow, given that IIRC rust does bound checking on integer operations, unless you explicitly say that they're overflowing

sacred yew
#

They're stores in a int array

grave jolt
#

No Python object can be stored in a register

weary garden
#

they are dynamic in nature so must have an extra level of indirection: you cannot get around this

raven ridge
#

you're right that there's an indirection, but indirected loads are as cheap as regular loads

#

they're both one cycle on a CISC architecture - even on most RISC architectures, I believe.

sacred yew
#

doesn't cpython use a vla to store the digits

spark magnet
weary garden
#

registers were just an example: you can also store a 32-bit integer directly in bytecode

raven ridge
sacred yew
#

wait so you're implementing them as "primitives"?

spark magnet
sacred yew
#

that's going to break if someone monkey patches the int class

grave jolt
spark magnet
#

luckily python doesn't let you monkeypatch the int class

weary garden
#

you assume I would be using the 'int' class

sacred yew
#

there's no int class???

spark magnet
sacred yew
#

um

grave jolt
#

!e
In CPython, constants are already stored in the function and not created from scratch, so not sure what you mean

import dis

def f(x):
    return x in {1, 2, 3}

dis.dis(f)
fallen slateBOT
#

@grave jolt :white_check_mark: Your eval job has completed with return code 0.

001 |   4           0 LOAD_FAST                0 (x)
002 |               2 LOAD_CONST               1 (frozenset({1, 2, 3}))
003 |               4 CONTAINS_OP              0
004 |               6 RETURN_VALUE
raven ridge
#

it's certainly possible to switch back and forth between variable length integers and fixed size integers. CPython used to do it.

weary garden
#

you assume I would be using the 'int' class FOR FIXED SIZE INTEGERS

raven ridge
#

It's not a question of whether this is possible, only one of whether it would be faster or slower.

#

most likely slower, which is why CPython stopped doing it.

sacred yew
#

ok

spark magnet
sacred yew
#

So if I understand you right, you have 2 classes, one is normal int, the other is int32?

spark magnet
#

@sacred yew there is no class yet.

sacred yew
#

*planned

weary garden
#

I might need this extension anyway to make interfacing with the ECS efficient

sacred yew
#

ecs?

weary garden
#

Entity-Component-System

raven ridge
sacred yew
#

idt his coerces though

#

implicitly at least

weary garden
#

but I am focusing on Python first; I will worry about adding any extensions to make it usuble as part of a 3D game engine later

raven ridge
#

you could choose to not coerce - once you've got the types, you could define different behavior for each.

#

I don't think any of this is a good idea, but there's absolutely no doubt that it's possible.

weary garden
#

but I never add things for the sake of it: there is always some rationale.

raven ridge
#
>>> numpy.uint32(2**32 - 1) + numpy.uint32(1)
<stdin>:1: RuntimeWarning: overflow encountered in uint_scalars
0
#

numpy has an unsigned 32 bit integer type with defined defined overflow behavior, for instance.

spark magnet
#

Yup, and it's still a full Python object, so occupies 28 bytes

oblique crystal
#

isn't it because of compatibility with C types?

weary garden
#

C types?

unkempt rock
#

we could go full symbolic with a super big addition 2darray ... :O)

#

I play long time ago with a 10x10 addition array and number as string .. in lisp ...

limpid marten
#

I'm not really sure what you mean.

spark magnet
#

I think @unkempt rock means adding "123" and "456" by looking up "3" + "6" in a 2d-array, etc.

radiant fulcrum
#

Thats not so mucb a type as an implementation of arrays

#

Also numpy โ„ข๏ธ

visual shadow
#

Yeah numpy can already do this no?

radiant fulcrum
#

In its sleep

unkempt rock
#

well int is 0,1,2 3 .... we just need an addition table 10x10 ans rule to form the summation along int ...

radiant fulcrum
#

Any sort matrixes operations etc... Might aswell be done with numpy

#

You're not gonna get anything making it an inbuilt other than compatibility issues bloblul

unkempt rock
#

pure symbolic, no need of adder ...

#

lol

sacred yew
#

@weary garden I'm also curious how you plan on supporting haskell

spark magnet
grave jolt
#

wait until python can be mixed with haskell

weary garden
#

@sacred yew the answer to that question is simple: a universal turing machine can compute anything computable; or to put it another way, I do not believe the problem to be intractable.

rich cradle
#

@weary garden How many langs do you know? And which ones?

weary garden
#

@rich cradle why do you ask?

rich cradle
#

I just want to know what you have going in to this project.

weary garden
#

the presumption behind that question then is that you think I lack sufficient knowledge/skill to do what I claim which is kind of insulting to be honest. Should I publish my entire CV in this channel to satisfy your curiosity as to my credibility? Do you want to do the same?

rich cradle
#

No, that's not what I'm saying. I just want to know what you want to do this with, because I think it may be useful to some people if you made this in multiple langs (the code behind it). I personally, would be interested in seeing that. In how you did it.

#

That is, if it's open source.

sacred yew
#

its on github

weary garden
#

also, I am implementing languages that I don't currently "know" such as Python. all that is required is the ability to learn new languages and I have that ability.

radiant fulcrum
#

Leigh is going with there neos system, im going with my web assembly

#

Round 1, fight!

weary garden
#

wasm? LOL. has it got a jmp statement yet? ๐Ÿ™‚

grave jolt
#

no, of course the rust compiler for wasm is implemented in pure movs

radiant fulcrum
#

Web assembly tbh is actually pretty pleasant to write raw

limpid marten
grave jolt
#

yes

#

maybe not that, but heard about it

spark magnet
surreal grove
weary garden
#

handwaving? more like a standard repsonse to someone saying something cannot be done when there is no techinical reason why it cannot be done.

spark magnet
grave jolt
#

nobody has written a Haskell compiler in brainfuck/pure turing machine yet, but it's technically possible

weary garden
#

adding a Haskell front end to LLVM is not impossible so my approach isn't impossible either.

surreal grove
#

if you proceed down this line doesn't this mean that you'll eventually write malware, even if unintended

weary garden
#

the neos schema in combination with semantic concept libraries is turing complete.

radiant fulcrum
#

Ngl i think we should just stick with a single language rn

#

Hands why do one language well when we can do many poorly

grave jolt
#

you can always do one poorly ๐Ÿ™‚

#

or zero, in undefined quality

radiant fulcrum
#

Tru

spark magnet
weary garden
#

Not really; I have a plan which I am currently executing and I see no technical hurdles too onerous to overcome; the biggest hurdle is simply one of available time.

spark magnet
#

i'm tempted to ask about mixing languages with very different semantics, like C/Python or Python/Haskell, but my experience in the past says that details aren't forthcoming. We're looking forward to the code.

weary garden
#

look at it this way, nedbat, Haskell has pure and impure (imperative) parts which cooperate in parallel. you are simply mistaken in your belief that what I am doing is impossible/intractable.

spark magnet
#

i didn't say it was impossible. I said i was curious about how you would deal with those difficulties.

weary garden
#

the code will speak for itself as and when I come to write it; it is sufficient to know at this point that what I am doing is not impossible/intractable.

spark magnet
#

ok, no details yet. Like i said, we are looking forward to the code.

weary garden
#

added a recurse directive to the neos schema which simplifies schema definitions somewhat; this is slices now:

spark magnet
#

@weary garden what do the two "expect" terms in a row (lines 722,723 and lines 728,729) mean?

weary garden
#

they are the expected tokens to be found when parsing the parent element

spark magnet
#

so it's a sequence? Both should occur?

weary garden
#

either can occur

#

but at least one must occur

spark magnet
#

i see. i'm trying to see how it works

weary garden
#

at first glance you might think it looks a lot more complicated than the PEG grammar but the PEG grammar isn't doing two things: handling whitespace and has no way to embed semantic concepts

#

for example here is the grammar for a universal number (not Python):

#

the symbols with dots in them, e.g. exponent.digit are semantic concepts; as are the symbols that can be found by prefixing them with parent.

#

universal number semantic concepts referenced from the grammar:

spark magnet
#

i'm curious about the "default: next" bits: it appears a lot

weary garden
#

it means any other non-matching token will be parsed as the next unrelated element

#

without that any other token would cause a syntax error during parsing

raven ridge
#

this appears to not allow a number to start with .

weary garden
#

I originally designed that grammar for Ada unversal numbers so either that is invalid for Ada or I forget it

raven ridge
#

that # there doesn't seem to apply to Python, either, if that's a literal #

weary garden
#

if you scrollback you will see that I stated that this wasn't for Python

raven ridge
#

ah.

weary garden
#

I was just showing you how the grammar looks for something non-trivial

#

I think @brave badger is writing a novel ๐Ÿ˜„

feral cedar
brave badger
# weary garden look at it this way, nedbat, Haskell has pure and impure (imperative) parts whic...

Well I wouldn't necessarily say in parallel; the primary abstraction for side effects that Haskell uses e.g. Monads are pure by definition, effects are only observable during runtime when IO is collapsed and observed. Likewise, there's alternative ways to model side effects purely, most of which intrinsically rely on compiler extensions and the type system. I agree that it's not impossible to create an implementation that mixes different effect semantics, but then again I don't want to undermine the past 30 years of research put into the Haskell ecosystem.

peak spoke
weary garden
#

@brave badger However I will be creating a Haskell implementation later this year so prepare for the coming storm! ๐Ÿ˜„

peak spoke
#

timing it seems to agree

In [16]: timeit 2**4096
4.15 ยตs ยฑ 61.9 ns per loop (mean ยฑ std. dev. of 7 runs, 100000 loops each)
In [17]: timeit 1<<4096
106 ns ยฑ 0.691 ns per loop (mean ยฑ std. dev. of 7 runs, 10000000 loops each)
feral cedar
#

o, nevermind then

peak spoke
#

still a fairly trivial op on reasonable numbers

limpid marten
weary garden
#

@brave badger so you will be able to use Haskell as the scripting language for my 2D/3D game engine and app toolkit

#

@brave badger this is what the GUI looks like:

brave badger
#

Well I'm not really as invested in game dev as much as I am with theory and such ๐Ÿ™‚, but I'm looking forward to it nonetheless

weary garden
#

it isn't just for games, it is for ordinary apps too; anything that has a GUI

feral cedar
#

strange choice of colors

weary garden
#

I think they look rather pleasant: gold is white and silver is black

#

although I need to make the silver look more silvery rather than whiteish

#

but obviously I will add the ability to customize colours, pieces and have a traditional default

weary garden
#

I think this is correct for slice ๐Ÿ™‚

grave jolt
#

the biggest difference is not that -- it's that haskell is lazy

sacred yew
#

plus the type system

grave jolt
#

well, yeah

sacred yew
#

and im pretty sure thats not what "pure" means

grave jolt
#

PureScript also separates pure code from impure code, but interoperates with JavaScript very smoothly

#

(because it's strict, not lazy)

limpid marten
weary garden
#

@grave jolt you mentioned Brainfuck yesterday: I will be providing a brainfuck implementation too: how that will interact with other languages will be interesting

silk pawn
#

would be cool

#

you might as well do it if you have the skill to build a universal turing machine

weary garden
#

@silk pawn no. I am writing brainfuck in neos

silk pawn
#

sad

#

question:
so python will constant fold this:

number_set = {0, 1, 2, 3}

but will it constant fold this?

number_set = set()
number_set.add(0)
number_set.add(1)
number_set.add(2)
number_set.add(3)

wondering if the peephole/ast optimizer is smart enough for the second example basically

nvm, forgot that it won't fold sets because they can be modified

flat gazelle
#

python will not constant fold the above

silk pawn
#

it won't fold either?

#

or it won't fold the second

#

oh wait im dumb

#

i used a set not a frozenset

#

smh me

#

ok sorry

grave jolt
#

!e
@silk pawn it will fold a set into a frozenset in certain cases (where it knows that it won't be changed)

import dis

def f(x):
    return x in {0, 1, 2, 3}

dis.dis(f)
fallen slateBOT
#

@grave jolt :white_check_mark: Your eval job has completed with return code 0.

001 |   4           0 LOAD_FAST                0 (x)
002 |               2 LOAD_CONST               1 (frozenset({0, 1, 2, 3}))
003 |               4 CONTAINS_OP              0
004 |               6 RETURN_VALUE
silk pawn
#

ohhhh

#

ok got it

weary garden
#

you got constant folding for free in neos as part of semantic concept folding

spark magnet
#

it's interesting that CPython "constant-fold" a set literal into a frozenset object.

grave jolt
#

yeah, I was surprised

flat gazelle
#

it also does this with list literals

grave jolt
#

!e

import dis

def f(x):
    return x in [0, 1, 2, 3]

dis.dis(f)
fallen slateBOT
#

@grave jolt :white_check_mark: Your eval job has completed with return code 0.

001 |   4           0 LOAD_FAST                0 (x)
002 |               2 LOAD_CONST               1 ((0, 1, 2, 3))
003 |               4 CONTAINS_OP              0
004 |               6 RETURN_VALUE
grave jolt
#

yep

spark magnet
#

cool

grave jolt
#

here it can't turn it into a frozenset, because here order of comparison is defined

spark magnet
grave jolt
flat gazelle
#

the comparison could have a side effect, however contrived such a case would be

spark magnet
#

@flat gazelle if the comparison could have a side effect, it wouldn't have been "folded" at all.

grave jolt
#

but CPython can't know if it has a side effect

#

because x doesn't have to be an integer

#

Also, if x is not hashable, searching in a set would raise an error.

spark magnet
#

i suppose that's true

#

both good points! ๐Ÿ™‚

flat gazelle
#

oh wait, the x can't be a custom object

grave jolt
#

wdym?

flat gazelle
#

since a global load is non-deterministic, and if it is a local, it can't be in a constant

#

and I don't think there is a third option

spark magnet
#

x is an argument to f, it could be anything.

grave jolt
#

I wonder how hard it is to make a pure-python bytecode optimizer that trusts typehints...

#

sending a value to a generator is faster than calling a Python function?

flat gazelle
#

makes sense

#

no need to create a new frame

grave jolt
#

right

#

well, there is a catch -- if the generator fails, you have to somehow restart it

#

alright, so that might be a... possible optimization lol

#

If a function takes a single positional-only argument

#

exception problem solved ๐Ÿ™‚

#

well, except when you pass double as an argument to be stored and called later...

severe lichen
#

Question - why Python doesn't utilise Ellipsis in its standard lib?

spark magnet
severe lichen
#

Just an example - functools.partial(func, 1, ... , 2)

spark magnet
severe lichen
#

Yes. That's from the top of my head, I haven't really thought it through.

#

It's just we have defined syntax, but It's not used. It's like if we had square brackets, but only used normal ones. Feels weird, like a placeholder for something.

spark magnet
#

@severe lichen there is syntax in Python specifically to be used by libraries like numpy. Ellipsis is one of them. Also @ for matrix multiplication.

grave jolt
#

@severe lichen ... is used in type annotations, e.g. Callable[..., int] or Tuple[str, ...]

raven ridge
#

that partial example sounds like a good idea - someone should propose it ๐Ÿ˜„

grave jolt
#

how would you them pass ... as an argument to a partial?

#

that's a breaking change

raven ridge
#

to a partial, or to partial?

grave jolt
#

to partial

#

partial(func, 1, ..., 2) now means (roughly) lambda *args, **kwargs: func(1, ..., 2, *args, **kwargs)

raven ridge
#

ever seen anyone do that?

grave jolt
#

Nope.

#

Well, I haven't seen a lot of code, so that's an argument from a false authority.

#

But still, it's a breaking change

#

not to say that it shouldn't be considered, of course

raven ridge
#

it is, but there are breaking changes all the time.

severe lichen
#

Hey, let's make an optional kwarg substitutes_ellipsis with default False, so it would be backwards compatible! What could go wrong?

uncut sage
#

If I have a function like this

def fn():
  x: int = 1
  return x
#

is there any way to inspect the function with typing and determine which hints have been applied to what names?

#

(aside from the function signature)

grave jolt
#

@uncut sage Only through ast, I suppose.

#

AFAIK the annotations are completely erased in function bodies at runtime

uncut sage
#

ast, that's what I thought.

#

I'm working on something that uses dis, so that may be too many steps down.

grave jolt
#

(otherwise, when would they be computed? when the function is created -- that's slightly confusing. when the function is called -- that's potentially a lot of overhead)

uncut sage
#

I'm actually contemplating a different method to do what I had in mind, but this is useful to know

#

I'm actually creating a decorator that takes in a function, disassembles the bytecode, and transforms that into assembly (sorta-kinda)

twilit garnet
#

i have encountered a moral dilemma (and a serious case of bikeshedding) that has bothered me for quite a long time :D i have a class which should implement the basic arithmetic operators (__add__, __sub__, __mul__, etc), some of which have very similar code in common. which of the following options seem like the best way to do this?

  1. defining __add__ and __sub__ separately using very very similar code in each one (with only difference being the use of - instead of + in their relatively lengthy definitions, for example).

  2. defining __sub__(self, other) by using the other defined operations to simplify it, such as self + (-1 ร— other). this would produce the correct result without duplicated code. however, the use of multiple operations (multiplication and addition) to define a single, simple operation isn't very intuitive or efficient. furthermore, if other does not support integer multiplication in that example, then __sub__ would raise a TypeError relating to the multiplication by -1 there, which isn't an intuitive error message.

  3. writing a helper method that does the common operations of code for the two similar methods. this would probably be called from each of the __add__ and __sub__ methods, and perhaps given a function in the operator module to define which operation should be done between the operands. i'm not sure if i explained this option well at all, but it seems like an "ideal" solution which also feels unnecessarily complex.

any thoughts would be nice, even if it's just to tell me to stop thinking about the bike shed here haha (also hello i haven't spoken here in a while hi!)

grave jolt
#

oh hi juainter

grave jolt
flat gazelle
#

this may be a usecase for exec

#
for op, meth in [('-', '__sub__'), ('+', '__add__')]:
    exec(
        f"""def {meth}(self, other):
        return self.val {op} other.val"""
    )
twilit garnet
#

this adds another direction to the moral dilemma hahaha

#

but it's certainly interesting, that's for sure.

raven ridge
#

I'd pick 3, I think.

spark magnet
#

i like 3 also

flat gazelle
#

3 is nice, yeah.

raven ridge
#

or define helpers methods such that the meat of the logic has been separated into the helper, and the + or - or * or / would remain in the __add__ or __sub__ or __mul__ or __div__

#

if the long function can be refactored into a bunch of stuff, then a call to a + b, then another bunch of stuff, you can refactor "a bunch of stuff" and "another bunch of stuff" into helper methods that are used by all operators.

twilit garnet
#

i think i will go for option 3 even though it seems a little overkill.

#

okay yeah, thanks for your thoughts everyone ^^

spark magnet
#

Definitely. in fact, it's been done: PyPy

#

PyPy has a JIT, so it can run much faster than traditional Python

grave jolt
#

average is said to be about 4x, but certain corner cases can be dozens of times faster (or a few times slower)

flat gazelle
#

JIT is a way to get the speed benefits of compilation in an interpreter

#

It essentially compiles some sections of code it detects as slow and then uses the compiled code instead of the interpreted code

radiant fulcrum
#

PyPy is a tracing Jit compiler

#

so it monitors / counts the amount of executions a piece of code goes through

unkempt rock
#

Anyone around here familiar with running pytest with parallelism?

#

My tests use a database, but I want to set it up once. My threads are setting everything up 10+ times and they're starting up like 20 docker containers at a time.

#

I just need one.

raven ridge
unkempt rock
#

I'll go there, thanks

proven sequoia
#

Hey i have learned the basics of python. Now I want to learn about django and flask. Can anyone suggest a good source from where i can start learning.

weary garden
#

tuple ๐Ÿ˜„

astral gazelle
proven sequoia
#

Thank you

grave jolt
weary garden
#

I believe so

#

lines 870 and 876

#

I cannot test the grammar until I have defined enough of it so that I can parse a simple program

#

if there are still undefined elements in the schema then compilation cannot proceed

spark magnet
#

i would have started with a subset and made it runnable before translating the entire grammar. isn't it kind of unsatifsying?

weary garden
#

the gammar isn't simple enough for me to do that; print("hello") requires lots of elements to be defined

grave jolt
#

string literals, names, function calls with positional arguments
for runtime -- name lookup, function calls and constants

spark magnet
#

sure, but not slices or list comprehensions

weary garden
#

slices and tuples are in the middle of the grammar required for print("hello") to work

#

I believe

grave jolt
#

wouldn't it be better if a tool that allows you to create a scripting language let you develop it incrementally?

raven ridge
weary garden
#

it depends how the grammar is defined

#

I want to make my grammar match the official python grammar as closely as possible

#

and I don't want to partially define elements either

#

so defining atom requires me to define everything in atom

#

I would rather just spend the time now fully specifying the entire grammar and then start defining the semantic concepts

spark magnet
#

you do you. i would have wanted to see a simple thing implemented from start to finish, to prove out the ideas.

weary garden
#

I can define the semantic concepts separately and I don't have to do all of them upfront to be able to parse a program

spark magnet
#

we each chose "partial", but different kinds of partial.

weary garden
#

prove out what ideas?

spark magnet
weary garden
#

I can do that with my reference langauge; I already have parsed complete non-trivial programs written in my reference language

spark magnet
#

yes, parsed.

#

i said, "everything beyond the parsing"

weary garden
raven ridge
#

right, Ned's point is that starting by parsing the full grammar is a breadth-first approach to the problem, where most people would instead choose a depth-first approach

spark magnet
#

yes, that is a cool idea. i would want to prove it out. You don't. I get it.

weary garden
#

prove what out? I already know semantic concept folding works.

raven ridge
#

Most people would pick a subset of Python's grammar, build an interpreter that can successfully execute that subset, and then expand to progressively wider subsets, until they've implemented the entire language.

weary garden
#

that isn't necessary with neos as I am not making a Python interpreter: the intrepreter is language agnsotic

raven ridge
#

that makes no difference. Most people would start by mapping a subset of the semantic concepts necessary to run a simple program through the language agnostic interpreter.

spark magnet
#

OK, forgot I brought it up. We have different approaches.

weary garden
#

What I need to do is define the grammar first, please stop questioning my methods: you simply don't get the neos architecture

strange heath
#

it doesn't cost much to be friendly to people

weary garden
#

and the subset of the Python grammar required to do print("hello") isn't as small as you might think

spark magnet
#

@weary garden help me out here: when you paste your progress here, what kind of feedback are you looking for?

weary garden
#

and I not asking for feedback that implies that I don't know what I am doing.

spark magnet
#

ok, what kind?

weary garden
#

any other kind of positive feedback is welcome

grave jolt
#

I'm not sure what your target audience is...

spark magnet
#

Good job Leigh

weary garden
#

you don't seem to understand what "positive feedback" means: valid critcism is positive feedback

strange heath
#

you don't want help that implies you don't know what you're doing.... but if you knew what you were doing why would you ask for help?

spark magnet
weary garden
#

my methods are being questioned here, I am asking for help related to Python language itself and I not asking for "help" because you think my methods are wrong

#

step 1): define the SYNTACTICAL grammar of the Python language
step 2): incrementally define SEMANTICS of the Python language

#

step 1 does not have to be done incrementally

#

step 1 is tedious however and the only reason to do what you suggest is to relieve bordom and get some kind of instant gratification

spark magnet
#

ok, i'm letting you know why it might be hard for us to comment intelligently.

#

was there some specific help you wanted with the tuple syntax?

weary garden
#

I was looking for feedback and @grave jolt 's question was cromulent

spark magnet
#

i'm not sure what cromulent means?

weary garden
#

appropriate

strange heath
#

yeah I googled it it means adequate

raven ridge
#

It's unlikely that you'll get much help with the grammar, for a few different reasons. One is that you're writing it in a language that we don't know and can't read - or look at documentation to learn how to read. Another is that you're pasting screenshots of a subset of the file, depriving us of relevant context.

spark magnet
#

@weary garden can you push the work to GitHub so it's easier to see the whole file?

raven ridge
#

We can tell you that the interesting edge cases for tuple literals are that empty tuples are represented as just (), and one-tuples are 1,

weary garden
#

such feedback the lagnauge is hard to read is useful feedback

#

that is useful to know @raven ridge I didn't know that is how you specific a 1-tuple

grave jolt
#

also consider tuple/set/literal unpacking, and things like (*{*(),*()},*{*(),*()}) (contrived way to make an empty tuple)

weary garden
#

@grave jolt I am hoping I will get that for free from the grammar and associated documentaiton

raven ridge
#

definitely not from the grammar alone, but from the documentation should be doable.

weary garden
#

no I mean if I have correctly defined the grammar and semantic concepts then the example described should just work out of the box otherwise the gramma is incomplete

raven ridge
#

that doesn't fall out of the grammar. Unpacking is entirely a semantic concept.

#

The grammar allows the tokens to exist in that order, but it doesn't tell you what it means. The meaning - unpacking - is a semantic concept.

weary garden
#

indeed and all elements of the grammar will have a semantic concept attached to them

raven ridge
#

do you expect that to be one-to-one?

weary garden
#

it will help with an example: this is math_expression from my reference langauge grammar

#

math.operator.add is a semantic concept rather than a grammar token

#

so the initial SYNTAX grammar can then be elaborated with semantic concepts as appropriate

raven ridge
#

do you expect that each grammar element corresponds to only one semantic concept?

weary garden
#

it can be mapped to 0, 1 or many semantic concepts

#

line 697 associates the math.expression semantic concept with the math_expression grammar token/symbol; if that token is successfuly matched to a rule then the concept will be instantiated for later folding; bytecode is emitted during the folding process

raven ridge
#

so there can be multiple is entries for a single grammar symbol?

weary garden
#

yes

spark magnet
#

what determines if it's a string.utf8 or language.identifier ?

weary garden
#

it is both

spark magnet
#

but a particular token in a program is only one of them, right?

weary garden
#

an "identifier" is both a utf8 string and a language identifier

raven ridge
#

note that, in Python, an identifier is not necessarily a UTF-8 string.

#

I know I mentioned that before, but I'm not sure if you picked up on it.

weary garden
#

well that is from my reference language

raven ridge
#

yep, I figured.

weary garden
#

not Python

spark magnet
#

in print("hello"), print is an identifier, and "hello" is a string. Are we talking about the same things?

#

oh, not Python

raven ridge
#

but yes, he's talking about identifiers.

grave jolt
#

Speaking of identifiers, what's the rational behind allowing unicode names? Well, not all unicode, but e.g. cyrillic letters.

weary garden
#

the alternative to unicode being?

grave jolt
#

it would make sense to restrict identifiers to alphanumeric characters IMO

silent seal
#

How do I Generate 20 random integers between 100 and 1000 which are divisible by 4.

feral cedar
#

that doesn't sound very random

spark magnet
feral cedar
weary garden
#

the only reason to restrict yourself to ASCII is the limited number of keys on a keyboard

silent seal
#

Ah

weary garden
#

but if I live in China and want to write my program in Chinese why should I be forced to use ASCII? not everyone writes open source code in English

grave jolt
#

right, that makes sense

spark magnet
#

but 123 is an identifier?

weary garden
#

@spark magnet look at line 55

spark magnet
#

there are no line numbers in that screenshot

weary garden
#

sorry line 185

raven ridge
#

which means that an identifier isn't necessarily a UTF-8 string, it could be a string in any codepage/encoding

spark magnet
#

ok, but this isn't Python right?

weary garden
#

no

#

but the Python grammar will be similar as appropriate

#

so hopefully you are starting to see how I am mixing syntax and semantics in the same schema file

raven ridge
#

again, to my point, though: # has two different sets of semantics, and those aren't in any way captured by the grammar.

spark magnet
#

when do you expect to push the Python work to GitHub?

weary garden
#

I will do a push when I have fully defined the syntax then I will incrementally push as I define the semantics

spark magnet
#

if you incrementally push the syntax, it will be easier for people to follow along

raven ridge
#

though it's possible that properly supporting # coding comments requires special case handling entirely. You probably need to handle those before even parsing the file, now that I think about it.

grave jolt
# grave jolt right, that makes sense

...although it would be quite inconsistent to mix two languages, since all libraries and even keywords are in English.
I'm a native Russian speaker, but I would never use cyrillic identifiers because

  • I would constantly need to change the keyboard layout;
  • I would constantly need to switch between two languages, and it's difficult (I write comments in English as well);
  • I would constantly mix up characters that look the same or similarly (seeing ะฟ vs n is fine, but what about c vs ั?)
    besides, writing in a non-English language would make the code pretty much unusable by people outside my country
oblique crystal
weary garden
#

I might do a push once I have enough defined for "hello world" (which will be when I get no more undefined reference errors parsing the schema)

spark magnet
#

if you share screenshots here, why not the whole file on GitHub?

#

btw, on line 197 of the last screenshot: what makes the "end" clause kick in?

weary garden
#

there I just done a push as I had some code changes. happy? ๐Ÿ˜„

raven ridge
#

That's not obvious.

weary garden
#

@spark magnet that is referenced externally by another element

weary garden
#

I will be getting the most feelings of gratification when I start emitting bytecode and executing bytecode

#

then feelings of depression because it's not fast enough, then business optimizing things, then feelings of hapiness when it is faster

oblique crystal
#

Btw. Why gpl3

spark magnet
weary garden
#

depth-first?

spark magnet
#

as we were discussing before. Get 2+2 working and executing first.

weary garden
#

I forget? what you mean by depth first?

spark magnet
#

breadth-first is a complete grammar, and then start on semantics. Depth-first is a small subset of the language implemented all the way through.

weary garden
#

well I kind of did that right at the start: I parsed a complete Python program consisting of some comments and a string literal

radiant fulcrum
#

I just get stuck handling the python ast sad

radiant fulcrum
#

Think i just need to mull over handing the ast a bit more

weary garden
#

CPython creates bytecode and can cache it to a file yes?

radiant fulcrum
#

The handing is in rust which makes traversing it a bit tedious without creating a mass of recursion and mess

weary garden
#

I'll be doing something similar before I start work on the JIT

spark magnet
#

the language.keyword in your Python.neos file reminds me that we now have soft keywords, which I have to figure out how to deal with.

weary garden
#

\o/

#

me too I guess

#

keywords appear to just be a string literal in the Python PEG grammar however I have to explictly associate them with language.keyword semantic concept so I can get syntax highlighting and such

spark magnet
#

@raven ridge is right, the coding comments are going to be a pain. you might have to just say you aren't going to support them.

weary garden
#

was that to me?

spark magnet
#

just thinking out loud.

weary garden
#

@oblique crystal GPL3 until neoGFX 1.0 is released then it will be dual GPL3/Commercial

#

I am using GPL3 to protect any IP I consider valuable

raven ridge
#

I was pointing it out for you, Leigh - yeah. Those are something that won't work in your model - they're semantically significant and need to be handled before the file can be parsed (but after the interpreter has started)

weary garden
#

you mean character encoding of source files?

raven ridge
#

yep.

weary garden
#

yeah I will have to address that in a language agnostic way anyway

raven ridge
#

the Python language represents that with a comment that must occur in the first two lines of the file, and that the interpreter must read and handle before parsing the file.

#

it can't be handled in a language-agnostic way - the semantics of the operation are tied to Python.

weary garden
#

I can handle it in a language agnostic way, don't worry

raven ridge
#

it can result in the execution of arbitrary Python code.

#

the encoding is handled by a Python decoder, which can be registered dynamically at runtime.

spark magnet
#

anything can be language agnostic, it might only be used by one language.

raven ridge
#

if your goal really to be able to run absolutely any Python program, you'll need your import machinery (which includes importing any initial file that the interpreter is asked to start with) to support dynamically decoding the file using a Python codec after you find its path on disk, and before you parse it and compile it. The Python codec used to decode the file may have been registered by any other module that had previously been imported in the same interpreter session.

spark magnet
#

It definitely will be a lot to get right, and other languages won't be doing it the same way.

weary garden
#

what is a "python codec"?

raven ridge
#

there's a registry of codecs by name, so you can look up the name "utf-8" and get an object capable of encoding arbitrary text strings to UTF-8, or decoding UTF-8 strings to their corresponding sequence of Unicode codepoints.

#

Likewise, someone can register their own codec, and once it has been registered within a session of the interpreter, it's possible to import files that use it as a coding comment.

weary garden
#

what have these codecs got to do with source code file encoding?

spark magnet
#

they are what decode the file

weary garden
#

so what does a source file look like that uses these codecs to decode itself?

spark magnet
#

here, it's utf-8, which is the default for python 3, but it could be any codec name.

raven ridge
weary garden
#

interesting

raven ridge
#

this isn't a commonly used feature, but if your goal is 100% feature compatibility, it seems like it would throw a wrench in your plans.

weary garden
#

not a wrench

#

just something interesting I will need to support

raven ridge
#

well, it has interesting implications. Like, what does it mean to cache byte code for that file?

#

the AST might be different every time it's imported, depending on what other modules had previously been imported in the same interpreter session.

#

it's possible to construct a file c.py that parses to one AST if you import a before import c, and an entirely different thing if you import b before import c

spark magnet
#

i don't know how CPython deals with that.

raven ridge
#

I'm betting it mostly doesn't.

weary garden
#

I am going to bed. later.

silk pawn
#

with small modifications ofc

raven ridge
#

I don't see why it wouldn't be possible.

silk pawn
#

y e s

#

this is what I'm talking about

#

I wonder if someone has made a library for this

#

eh

raven ridge
#

#bot-commands ๐Ÿ˜‰

silk pawn
#

o yeah sorry

raven ridge
#

Guido is pushing the "export" idea even further - his latest formulation of it on python-ideas might give the ability for a module to have true private attributes that aren't accessible through normal Python attribute lookup.

grave jolt
#

like _dataclasses__json?

raven ridge
#

like that, if it wasn't accessible through normal Python attribute lookup ๐Ÿ˜‰

grave jolt
#

ah

dusty pecan
#

ay9o could i get some quick help?

#

I ;egit need 1 thing

tiny oar
#

Hello, is anyone familiar with the matplotlib library?

charred wagon
#

@dusty pecan @tiny oar this isn't a help channel. See #โ“๏ฝœhow-to-get-help Furthermore, I suggest you ask your actual question when you claim your channels rather than asking if you can get help (the answer is probably yes if you're not breaking rules) or if someone knows a library.

tiny oar
#

@charred wagon Just posted in the help channel, thanks

brave badger
#

I really hope pattern matching doesn't get undermined as just a glorified switch/case e.g. using it over if-chains or dictionaries for "simple" matches

charred wagon
#

I've already seen it happen

#

But people were quick to correct

grave jolt
#

I think pattern matching is rather an extension of destructuring, i.e. [x, *y, (z, w)] = foo

flat gazelle
#

one thing I would love from patma is

match "342":
    case int(a) except ValueError:
        pass
    case _:
        a = 0
grave jolt
#

I guess you can extend my context_manager_patma, because it uses with statements

weary garden
#

is Guido teh Authoritay?

#

I hope Python Land isn't an autocracy like Linux Land: Linux is not going to end well.

undone hare
#

I mean, GvR stepped down from his BDFL position

grave jolt
rich cradle
#

Looks like we're getting these new features then.

brave badger
#

Something tells me gradually-typed, performant Python is the best possible outcome for the language, considering the current climate

rich cradle
#

Gradual typing would be nice.

weary garden
#

@grave jolt you use Twitter? follow me! ๐Ÿ™‚

brave badger
#

I suppose it'd be about the same relationship that TypeScript has with JavaScript, the former won't totally eclipse the other, but it sure is gaining traction

weary garden
#

I guess you could do that with neos given you can mix different languages in the same source file

grave jolt
weary garden
#

although I don't know how the syntax of TypeScript differs to the syntax of JavaScript

radiant fulcrum
rich cradle
#

Something like that for Python would be nice.

radiant fulcrum
#

makes performant optimizations like JIT compiling go from being fairly simple to big pain Hands

weary garden
#

call it Tython ๐Ÿ™‚

radiant fulcrum
#

the whole point of TypeScript is typed

#

using dynamic typing in typescript kinda defeats the purpose bloblul

rich cradle
#

Not really. It's just an extra tool. You don't have to use it all the time.

grave jolt
weary garden
#

somebody needs to create Tython at once! any volunteers?

radiant fulcrum
#

Mmm its by far the biggest pull of TS, is the fact that it's statically typed

radiant fulcrum
rich cradle
radiant fulcrum
#

If you want strictly typed python though you do have MyPy or PyRight i think they are that enforce type hints

weary garden
#

I could do it I suppose: one goal of neos is to make prototyping new languages relatively quick and easy

grave jolt
#

Has type inference/checking been modeled with relational algebra anywhere?
It seems to be a natural tool to deal with overloads and such. But not sure how to fit infinite queries into that (with generics)

limpid marten
#

TypeScript was the best thing to happen to JavaScript.

rich cradle
#

^^

limpid marten
#

I think it's been thoroughly embraced right?

weary garden
#

surely suggesting dynamic typing is non-optimal is blasphemy here? ๐Ÿ™‚

brave badger
flat gazelle
#

dynamic typing has its merits still

rich cradle
#

It would need to be optional to be viable to Python programmers.

visual shadow
#

Yep. Both static and dynamic typing has something going for it, or one would have died out

flat gazelle
#

statically typed python would be interesting, considering how much of the standard library is, well, not that

weary garden
#

dynamic typing is easier for beginners I suppose

rich cradle
#

Indeed.

weary garden
#

but beginners worth their biscuits can soon outgrow it

flat gazelle
#

ye, and it allows weird metaprogramming

#

and well, static type systems which don't get in your way are invariably complex

brave badger
#

I have a bias towards static typing and its generally positive implications to runtime safety, but dynamic typing just speeds up the process of getting to a desired result, and that's just as invaluable

rich cradle
#

I would want something where you could do both in the same file. (Ignore the syntax errors, its a ts file.) Something like this.

weary garden
#

I have a bias forged from mostly using one language for the last 30 years

undone hare
#

Which is?

weary garden
#

C++

flat gazelle
#

I do like static typing for things that are hard to test and debug (frontend), as well as things that shouldn't ever error (banks), but if I just need to quickly grok something, they aren't all that useful

undone hare
#

I don't think static typing should ever be in Python

rich cradle
#

Why?

#

Even if it's optional?

undone hare
#

If you want static typing you should use another language

flat gazelle
#

I don't think it can be in python in a sensible way

#

python compilation runs arbitrary code, remember

undone hare
#

I don't see a scenario where it would fit nicely in Python, even if it is optional

flat gazelle
#

and therefore, so must type checking

visual shadow
#

Optional is a funny way of saying "messy"

rich cradle
#

I see.

flat gazelle
#

gradual typing is neat

#

raku has that

#

but it doesn't give safety

#

just documentation

#

which type hints already do

undone hare
#

I'd rather have better null or exception handling for instance, or better functional like coding

brave badger
#

Every day I wish for null coalescence to exist

flat gazelle
#

yeah, exception handling is quite poor

visual shadow
#

In python?

flat gazelle
#

yeah

undone hare
#

"Ask for forgiveness not permission" is a poor paradigm IMO

flat gazelle
#

its a great paradigm, since for actually important things it is the only correct way to do so

visual shadow
#

Can you explain to me why? First time hearing that

flat gazelle
#

try except is so much more verbose than if that it often feels punishing to use it

#

and there is no excepttry

visual shadow
#

Ah! The verbosity of it. Got it

undone hare
#

Sure, exceptions still have its merit

#

And it is still useful if you have deeply nested calls or stuff like that

flat gazelle
#

so you can't do like

try:
    attr = obj.thing.another
except AtrributeError try:
    attr = int(another_source)
except ValueError:
    attr = 45
#

since you end up with insane nesting

#

this could be solved in patma with a try pattern of sorts

visual shadow
#

I've seen subtle bugs emerge when people tried checking if a file existed before deleting it. It was a nightmare to debug. So there eafp would have saved us a lot of pain

#

And yeah thanks lak, that's perfect. Yeah makes sense

flat gazelle
#

also, not having to parse an int twice to see if it is correct

#

checking is often just as expensive as actually doing it

brave badger
#

EAFP is generally nicer for potentially destructive operations I think?

undone hare
flat gazelle
#

but exceptions are a good solution

visual shadow
#

The point checks being expensive is also important. If the error path is a rarity, eafp will save time

undone hare
#

In a sense you are still asking for forgiveness, you have just hiding the boilerplate

visual shadow
#

That's my understanding of it anyways

flat gazelle
#

a try expression would be helpful

#

but very unpythonic in every implementation I can come up with

#

but honestly, a patma pattern for exceptions would do the trick for most things, though I am not sure how exactly it would look

visual shadow
#

Maybe it would have to be a new symbol to cut down on verbosity. If verbosity is the real problem.

#

But I'm torn, because I do love having python read off like almost English

flat gazelle
#

I don't think a symbol is needed here

#

just some way to try something else that could also error if something errors

#

that doesn't involve nesting even deeper

undone hare
#

One interesting syntaxt could be to have an inline except, something like

expression except (Exception) as default_value```but Iโ€™m not a fan of this, and `as` is a poor choice of word here
noble depot
#

Hey please tell me if I can ask for open source contribution on this server somewhere

flat gazelle
#

don't think that helps

#

since then you have this

    attr = obj.thing.another except AttributeError else (int(another_source) except ValueError else 45)
#

which is still nesting deeper

#

just in an expression, not in a statement

undone hare
#

Yes, but at least you donโ€™t take 4 lines anymore just to catch one exception

brave badger
undone hare
#

.... Which is actually more than Cโ€™s error handling

#

In term of lines, that is

flat gazelle
#

lines don't matter IMO. Creating massive expressions to avoid multiline statements seems pretty invariably bad in python

brave badger
#

except Except as e is a good solution but it feels penalizing when used at large

#

Maybe I just can't be bothered ducky_devil

grave jolt
# flat gazelle try except is so much more verbose than if that it often feels punishing to use ...

I've seen people primarily oppose "exceptions" (EAFP) and "first checking it, then accessing it" (LBYL). LBYL leads to obvious problems, with various examples like filesystems or databases. But it's a false dichotomy -- there are also "error values", which are the best of both worlds, because:

  1. They force you to account for the error cases (given that you e.g. use a typechecker)
  2. They don't allow confusing control flow -- control flow is the same as the rest of the things (classes, functions, generators, coroutines, conditionals,, loops, match etc.). Exceptions can act like gotos on coke
  3. They aren't prone to race conditions (unlike LBYL)
undone hare
#

Alright, maybe the line count is a bad metric, but a try/except still takes a lot of place and is quite verbose

flat gazelle
#

ye, but converting it to an expression is not the solution

#

return value based error handling has its merits yeah

#

but I feel like it's far too late to switch python to that

undone hare
#

Returning exceptions like in C or Rust sounds like a poor idea

flat gazelle
#

python is statement based

#

and I really doubt it can be better than say kotlin at being kotlin

undone hare
#

I havenโ€™t done a lot of Rust, and Iโ€™m already tired of doing .unwrap everywhere

weary garden
#

exceptions should never be checked for; they are a result of failure and if implemented properly have no cost if the exception isn't thrown

flat gazelle
#

not in python

#

in python they are just a way to represent a possible result

undone hare
#

Failures are part of an application

flat gazelle
#

at the same time, nice exception handling is hard

#

which is why even raku fails at it miserably

weary garden
#

it is a solved problem tho

flat gazelle
#

it really isn't. CPP exception handling is also quite poor, there has been direction towards monadic error handling there because of that.

grave jolt
# flat gazelle but I feel like it's far too late to switch python to that

Well, the worst part is that some errors are reported as values, and some as exceptions. E.g. dict.get is used as an alternative to dict[k], and then there are functions on lists, etc.

Error values are sometimes useful when you need to account for an error inside of an expression. So given that python is statement-based, you have to resort to making more statements if with some new change an expression can produce an error. Or making silly helper functions like

def pop_or(xs: list[T], default: T) -> T:
    if not xs:
        return default
    return xs.pop()
undone hare
#

Exceptions are one of the least solved problem of language design IMO

flat gazelle
#

yeah

weary garden
#

disagree ๐Ÿ™‚ C++ exception handling is fine and has no cost if the exception isn't thrown

visual shadow
#

And that too Only when tightly coupled to languages with certain semantics at best. Semantics that don't generalise.

undone hare
#

I donโ€™t think you can have except blocks without any cost

flat gazelle
#

you can

undone hare
#

You have to set it up at some point

weary garden
#

well there is always the cost of larger executables I suppose which could potentially have a CPU cache overhead

flat gazelle
#

there are common lisp conditions which work reasonably well for various tasks, but they are also far more complex than just plain old stack unwrapping exceptions

brave badger
undone hare
#

It is good when you want it

#

Sometimes you just want to do something and let it die out if it fails

brave badger
#

Having the short-circuiting behaviour done for you is the nice thing about Haskell's Either type, which is just Result, any one of these operations can fail and client code is really the only cog responsible for collapsing the computation into an observable result:

-- Any one of these operations can fail
parseCodeBlock :: Parser Markdown
parseCodeBlock = do
  _ <- string "\`\`\`"

  language <- regex ".+" <* char '\n'

  code <- manyTill (regex ".+\\n") (string "\`\`\`")

  pure $ CodeBlock language (List.foldl (<>) "" code)

-- But it's ultimately the resposibility
-- of client code to handle the failure
-- appropriately
main :: Effect Unit
main = do
  codeBlock <- readFile "README.md"
  case runParser parseMarkdown codeBlock of
    Left err -> log err
    Right code -> log code
limpid marten
weary garden
#

some minor differences for -O3, not much difference at all with no optimizations

#

but getting the compiler to do what you want from a benchmarking point of view with optimisation is always tricky

pliant tusk
weary garden
#

@pliant tusk I wasn't referring to catching exceptions: I was referring to how exceptions are thrown in the first place.

pliant tusk
#

You can't really have one without the other?

weary garden
#

for example you should not check if a file exists and then throw an exception, rather you should attempt to open the file and then throw because the open failed; this is mainly a concern for library implementors but is also something to bear in mind when throwing exceptions in app code

undone hare
#

I am personally not a fan of using exceptions to unwind the stack, if you do that you probably have too much nested code

weary garden
#

of course I am not suggesting that you shouldn't catch exceptions; I wasn't suggesting that.

#

@undone hare disagree: how much is "too much"

undone hare
#

When you have too much to refactor and you need to use an exception to move up a few frames

pliant tusk
undone hare
#

โ€œToo muchโ€ is when refactoring isnโ€™t an option IMO

weary garden
#

no; totally disagree. exceptions are great; they are superior to checking error codes with hundreds of if statements all over the shop

#

you should have lots of throws but very few catches if you are doing it right

#

but I am not yet familiar with how exceptions are handled in Python, I am speaking from the point of view of C++.

pliant tusk
#
def get_contents(file_name_user_input):
    try:
        with open(file_name_user_input) as f:
            return f.read()
    except FileNotFoundError:
        raise ValueError('File Not Found!')
``````py
def get_contents(file_name_user_input):
    if file_name_user_input not in os.listdir():
        raise ValueError('File Not Found!')
    with open(file_name_user_input) as f:
        return f.read()```
#

@weary garden are you saying that the first function is superior to the second?

#

cause if you wait for open to fail, then you have to catch that exception to raise your own

undone hare
#

The former should use from None

#

Thatโ€™s one of the thing I donโ€™t like about exceptions, but it makes sense

flat gazelle
#

the second has a race condition in it

weary garden
#

I don't have a fully formed view on this as far as Python is concerned however my Python implementation will have a C++ bent as far as how exceptions work and perform are concerned

pliant tusk
pliant tusk
undone hare
weary garden
#

it will be

weary garden
#

it will be 100% compatible with pure Python

undone hare
#

If you modify the semantics I donโ€™t forsee how that can be 100% compatible

weary garden
#

I am not modifying the semantics

flat gazelle
#

and yeah, I would argue the first is more python

limpid marten
flat gazelle
#

the main reason to check ahead of time is for nicer errors in libraries

pliant tusk
weary garden
#

@limpid marten true

flat gazelle
#

library_function takes str as its first argument is more helpful than bytes has no attribute encode

weary garden
#

@limpid marten but that is not due to the language itself but to how std::vector is designed; but yeah, I agree with your point.

limpid marten
undone hare
flat gazelle
#

likely no

#

the non-erroring route in exceptions is faster than if in most cases

undone hare
#

Can we move C++ out of this channel please?

#

Interesting

grave jolt
#

(2 is happy, 50 is sad)

true ridge
weary garden
#

however if I need Python-specific semantic concepts I will add those too (after sighing)

#

however even Python-speficic semantics will be formulated in a language agnostic way

pliant tusk
#

i think you will find there are a ton of python specific semantics

flat gazelle
#

I don't think cpp exceptions have tracebacks you can look at from code.

weary garden
#

that remains to be seen

#

remember I am not reimplementing CPython, I am implementing the Python language

pliant tusk
#

the python language has a lot of semantics not found in other languages

true ridge
#

well zero-cost exceptions are also something that is been proposed by Mark on his faster CPython proposal, so I'd assume a proper implementation is possible without changing any semantics

undone hare
#

The level of introspection in Python makes it almost impossible to mix with other languages

pliant tusk
true ridge
pliant tusk
#

thanks

flat gazelle
#

it is easier since you don't need os._getframe and inspect and bytecode. Not sure if ast is part of the standard though.

weary garden
#

@undone hare tracebacks will NOT look the same as CPython tracebacks

limpid marten
#

Might be worth it to look at other Pythons that aren't CPython to see what compromises they had to make

weary garden
raven ridge
#

that means you'll have problems with sys.settrace, won't it?

flat gazelle
pliant tusk
#

and things like compile,eval, and exec wont work

weary garden
#

eval will work

flat gazelle
#

and sys.excepthook doesn't seem too painless either

grave jolt
pliant tusk
flat gazelle
#

ironpython has it in full

#

but it may optional

#

can't really tell

true ridge
flat gazelle
#

ah, nice

weary garden
pliant tusk
#

then why not support compile and exec then?

true ridge
#

If you can implement 2 major dynamic languages on the same VM where they'd use the same bytecode and the same interpreter, agnostically, then it truly will be an amazing experiment

#

though for now it seems more about ideas rather than actual work (if I am not missing something?)

weary garden
#

I don't know what they do yet, but from what I guess they do there is no reason I cannot support them too

raven ridge
# weary garden eval will work

Eval could, but I don't see how sys.settrace could. The contract of that is a hook function runs for each line of Python code that is executed. I don't see how you can possibly support that without knowing where lines of Python code are in the multi language bytecode

flat gazelle
#

doesn't graalVM already do that to an extent.

true ridge
#

to an extent, though it is not exactly that 'agnostic'

weary garden
#

it is completely language agnostic

grave jolt
#

except the language-specific concepts

#

right?

pliant tusk
weary garden
#

well, the architecture is completely language agnostic

true ridge
weary garden
#

not yet

#

be patient ๐Ÿ˜„

pliant tusk
#

afaik no, it seems to be mostly configs

weary garden
#

I am still defining the Python grammar

weary garden
#

a lot of work has been done already

undone hare
#

I donโ€™t get how you can have on interpreter doing many languages

weary garden
#

however as far as Python is concerned I am still writing the grammar

undone hare
#

well, I get how you can do it, I just canโ€™t get how you can follow 100% of the specs

weary garden
#

in the same way other non-CPython implementations do I guess

raven ridge
#

Following 100% of the specs isn't that hard. Doing it and winding up with something that isn't approximately equally slow is.

undone hare
#

non-CPython implementations follows 100% of the specs, but only one language at the time

radiant fulcrum
radiant fulcrum
#

same universal bytecode that many languages target

raven ridge
#

sys.settrace is an example of this: a place where a dynamic feature of the language makes lots of obvious optimizations impossible, because they'd change user-observable behavior

undone hare
radiant fulcrum
#

WASM is just a bytecode specification

grave jolt
radiant fulcrum
#

just made with sandboxing in mind

undone hare
#

Yeah I mean, a language isnโ€™t a bytecode spec

radiant fulcrum
#

its the same as neos i imagine because neos is just compiling multiple languages into the same bytecode

#

when you compile a language for WASM you target the bytecode instructions and then compile that with a wasm compatible compiler

weary garden
#

neos architecture is such that a supported language only exists as an input schema file which describes that langauge's syntax and semantics.

raven ridge
weary garden
#

this is why the knowledge of it being python disappears once converted to bytecode .. neos is language agnostic.

raven ridge
#

But then Python hook functions that run once per line of Python code can't work.

finite sparrow
#

what would a AST of that look like thonk

weary garden
#

I am not yet familiar with Python hook functions; I will get around to them at some point

undone hare
#

Alright, so that would be lcc, Leighโ€™s compiler collection, but targeting only one backend? Sounds interesting

weary garden
#

not

#

neos is not like gcc; front ends are compiled whereas neos frontends are dynamic

finite sparrow
#

i ask again: but how?

radiant fulcrum
#

Tbh i think the best way to approach a change in runtime semantics for people who are soused to the Cpython semantics is to treat it like a Python 4

undone hare
#

Yeah I mean, despite the impl details

radiant fulcrum
#

Trying to emulate the Cpython semantics basically takes away every chance for optimizations and design changes

#

Python 3 as a language is pretty locked to the Cpython way

finite sparrow
#

cython go brr?

radiant fulcrum
#

shrug Cython isn't magically quicker

finite sparrow
#

well yes but actually no

raven ridge
#

Or just accepting my one line summary: they allow users to dynamically, at runtime, register a callback which will be called once per line of Python code that is executed, saying what line has been reached.

flat gazelle
#

I would probably start with simpler languages like scheme, smalltalk and lua, just to see how well it works for more languages at once

raven ridge
#

They're used to implement things like coverage analysis tools and debuggers.

weary garden
# finite sparrow i ask again: but how?

neos accepts a shema file which describes the langauge syntax; syntactical elements in that schema can be associated with one or more semantic concepts which are defined in extensible semantic concept library plugins; compilation involves "folding" semantic concepts instantiated during parsing source code; when this folding happens bytecode is emitted. this all happens at runtime however of course bytecode can be cached and I plan on adding a JIT to convert bytecode to machine code.

radiant fulcrum
grave jolt
#

or is it already implemented?

flat gazelle
#

BF isn't that interesting

#

scheme, lua and smalltalk all have entirely different ways of modelling data

#

scheme uses heterogenous arrays with accessor functions, lua uses pseudo-oop very similar to JS, and smalltalk is its own thing which I do not know how to summrize in a single line. How those interact in a single runtime would be quite interesting to see

finite sparrow
#

i could perhaps see something like this working okay on a per-function basis with limited argument/return types to things that most languages can represent

weary garden
#

the ability to mix different languages in the same translation unit or program is not a primary functional requirement merely a side effect of the neos architecture: if two semantic concepts from different languages cannot fold then a syntax error will result

grave jolt
#

will neos have a SQL implementation?

weary garden
#

probably

limpid marten
#

Is SQL even turing complete? ๐Ÿ™‚

grave jolt
#

sure

flat gazelle
#

there is a specific operation you can recurse, so yes

grave jolt
#

well, I don't know about the standard SQL, i don't have the Book

undone hare
#

How can you fit a database engine and Python specific VM in the same backend

weary garden
#

the will be an SQL semantic concept plugin which will interface with my toolkit's RDBMS

finite sparrow
#

do you have any ETA's for this project?

weary garden
#

I hope to have a working Python implementation in 3 months time; adding new languages after that will be a lot less work as I anticipate there will be a lot of overlap of semantic concepts

finite sparrow
#

be sure to ping me once its working, i would love to try a small library i worked on a bunch that im quite sure will just break entirely

weary garden
#

it is open source

finite sparrow
#

open source is not the same as me remembering in 3 months ยฏ_(ใƒ„)_/ยฏ

fallen slateBOT
#
Can do!

Your reminder will arrive in 3 months!

weary garden
#

I cannot gaurantee that I will remember to ping you in 3 months ๐Ÿ˜„

desert peak
#

I envy you folks who have time to work in oss ๐Ÿคท

undone hare
#

OSS is fun!

limpid marten
desert peak
#

I have two? hours a night for myself outside of my work and my family, it usually ends up being spent on entertainment so I feel like I have a break away from working.

limpid marten
#

Some people make time for it because it's something they enjoy, I don't think anyone would blame you if you wanted to leave work at work and enjoy your free time the way you like.

sturdy timber
#

Huh, pep 637 was rejected

#

!pep 637

fallen slateBOT
#
**PEP 637 - Support for indexing with keyword arguments**
Status

Draft

Python-Version

3.10

Created

24-Aug-2020

Type

Standards Track

flat gazelle
#

that's unsurprising

limpid marten
#

Seems like a function call with extra steps.

flat gazelle
#

it would've made it possible to create partial functions with [] though, which seems quite neat

#

if you curse the function object that is

#

but yeah, the confusion of it doesn't seem worth the minimal benefit

limpid marten
#

I like how much they explain in the rejection, it's really well thought out.