I think most core devs felt that making the insertion order preservation part of the language spec was the less bad of several bad options. It does add an extra constraint to future dict implementations in terms of backwards compatibility, but the alternative was that developers would be very likely to write code that depends on an implementation detail of CPython rather than a language guarantee, and result in tons of code that wouldn't be portable to other Python implementations.
#internals-and-peps
1 messages ยท Page 62 of 1
@teal yacht the core devs decided it on the python-dev mailing list, just like they decide every other issue. There was a year between CPython dict becoming order preserving and it being added to the language spec.
@raven ridge Yes, but the thread itself where they finally added it was extremely short and derailed the conversation topprintfor whatever reason (it was an issue, but off-topic to that specific thread), a few people said they didn't agree but the convo moved on directly
https://www.youtube.com/watch?v=p33CVV29OG8 this talk explains the evolution of dict impls in python
https://mail.python.org/pipermail/python-dev/2017-December/151283.html
It's interesting if anyone is interested, they also talk about some difference with OrderedDict
admittedly, all of this is a non-issue if the implementation doesn't change in the future or changes for another implementation that preserves order but idk, the benefits of adding it to the spec are so small imo
it gets you a lot of neat code for dicts that did not work before. list(dict.fromkeys(some_list)) removes duplicates preserving order
a few people said they didn't agree but the convo moved on directly
@teal yacht I don't remember much disagreement, and I didn't notice any while skimming that thread. There was a lot of talk about what the implications of making this language change will be, but there weren't voices saying not to make that language change at all - maybe I missed the messages you're thinking of?
hello How do I make 2 diffrent classes 'talk' to each other? Im making a basic clicker game and I have 2 classes autoclicker and main,
and I want main to use autoclickers methods and autoclicker to use some methods from main
question about cogs with that unload and load thing does that mean anyone in the server can unload one so the commands don't work?
@swift gust thats a #discord-bots question
oh sorry
@chilly zephyr start by writing out your game logic. Usually circular/cyclical relationships between parts of your application are a bad sign
But in general there's no reason any method on an object can't call any method on any other object
I saw something about nested classes so Im trying this out
I don't think that's a good idea
This also is probably better suited for a help channel
This channel is for discussion about the python language itself
Or maybe #algos-and-data-structs for more abstract discussions about software architecture
If you post in help channel @ me, im at lunch now but maybe i can help later
On a conceptual level, you have lots of ways to get classes talking to each other - event listeners for example. But on a specific level, it boils down to calling methods or updating attributes of one class from another. For help with your specific problem, a help channel is best
does anyone know how to turn off css/images for selenium?
using the firefox webdriver
๐ค Why tho
also thats not really what this channel is for, you'd be better off next time asking in #โ๏ฝhow-to-get-help
and also that's not really a problem, so i didn't get a channel
especially if you go to lots and lots of sites with it
just like a normal firefox tab
yeah but disabling it can use less ram
CSS really isnt gonna be the thing increasing ram
not by any noticable amount
If you dont need JS support just use requests to get the html
I've been under the impression that importing within functions is unadvised, but i bump into it now and then
is there a consensus on whether this is alright / when to do it? I don't see why argparse can't be imported at the top of the script there
In seaborn there's an import of bs4 within a function, but that's because it's not a core function (it's to grab datasets), so I kinda get that
I would only do it if you dont want it imported on certain things
e.g
Uvloop for example
cant be installed on windows but you want the program to still work with windows
any thoughts on the example I linked? I'm not familiar with UVloop :S
so you would have a condition that only imports it if its a unix based system not windows
Importing inside functions imo is a big no-no, there's very few benefit, and it makes the code harder to maintain, and IDEs won't like it
so - argparse here should be imported at the top in your opinions?
yes
might as well, yeah
hrm ok, cool, that was what I thought but I bump into it sometimes and assume they know something I don't
all your arguments aswell can be top level
this is why more people should use __main__.py :]
they're only processed when you actually call parse
@teal yacht what do you mean - use it in what way ๐ค
I notice they don't have one, but often I've seen them and they've just been empty
they're importing it in the function because it's only when it's used as a standalone program
empty __main__.py ?
you sure you're not thinking of __init.py__ ?
yeah I think so ๐ค maybe that's init, yeah ๐คฆโโ๏ธ
Has anyone got MyPy working with Pycharm?
odd that this is still in there, as there have presumably been a few eyes on it and it's an easy fix, all good tho
pycharm uses its own type checker iirc, not sure if you can configure it
you can configure the type hinting and stuff
Im trying to work out how df you use this plugin for it
i've finally got neovim working in a semi sensible way :')
to be fair, I understand why they might want that @magic python, it avoids import unnecessary packages in the case you're not running it as a program but importing directly
@teal yacht right - is it "not by the book" but makes sense in practice? That sort of thing
i'd personally just make it a package with one file + a separate entry point but that's just me i guess
i've not really got entry points and stuff yet
yeah, you'll always see recommendations to put imports at the top but in that case it's ok-ish imo
__main__.py sorry
@radiant fulcrum The plugin wasn't working for me for some time, spewing gibberrish in the wrong encoding in the console, and then it just started working after an update ๐คท
to differentiate when you import the package vs run it as standalone
@teal yacht I've used this in the way of having a __main__.py that calls another script, and i then run the package that they're both in with python -m project.package and it seemed to work
all __main__.py did tho was import run and call run.main() which returned a sys argument
that's one way of doing it yea
I personally prefer to put the code directly in the __main__.py, not that it makes a big difference
yeh, i never have anything in init.py but see some people put loads in there
I never really know what is meant to go where ๐
oh, no, most of the time __init__.py will still be empty
all __init__.py means to me is that i can import things from there
__main__.py is a separate thing, if it exists, it is what is ran when you do python -m foo.bar
yeah, where bar is the directory , main is handy for that, i don't make much use of it tho really other than what i mentioned before
Why is dunder main a separate thing instead of having dunder init be the entry point for -m commands? I guess because dunder main only gets run if you do a -m command?
yep
__init__ and __main__ are two different things. __main__ is only run when you use the -m flag.
__init__ is always run
But it's only like that for the directory level module
Unless my programs are working for reasons I don't understand
I drafted a more expressive API to create regular expressions in Python (this is just a concept):
import regexpressive as rex
my_text = "texttexttext Name: Guido moretext"
regex = (
rex.Regex(case_insensitive=True, multiline=True)
+ r'name: '
+ rex.Group(
rex.Multiple(
rex.WORD_CHARACTER
)
)
)
# compiles itself automatically the first time it is used
# and keeps the compiled regex internally
name = regex.search(my_text)[1]
regexes are super intimidating to beginners, which is a shame because they'd be so useful in solving problems that beginners are often interested in solving when trying to get familiar with Python.
This is an idea that could help with that.
I've seen other projects like this. They don't seem to get wider use.
The regex described in the code translates to r'name: (\w+)'
"regexpressive" is a good name ๐
It's used a fair bit in emacs through the name rx
Another (way better imo) approach is called parser combinators
I'm not surprised; I've honestly been baffled by the fact that re as it is exists in the Python standard library because regexes as they are aren't very pythonic I feel like
It's such a widely spread tool, you can't not include it
Yeah; what I'm trying to say is that I'm surprised that there is no more friendly API to compose and use regular expressions in Python.
Python specifically tries to get rid of the amount of special characters in code that other languages suffer from, yet it makes you write regexes by hand
You should look into parser combinators, it's really interesting, and can be used to parse CFGs, not just regular grammars too
I will definitely look into that, got a link ready? I'm not sure where to start ๐
I have several, but they may not be useful depending on whether you know the language or not
parsec and its derivatives in haskell are great, but the code is gibberish if you're not used to it, i'm sure we can find a simple implementation in python somewhere on gh
https://github.com/google/compynator google has one apparently
I only know Java, Python and Rust, and some C, enough to port Python to a different platform ig ๐
Oh that looks good
Looking at that example code is oddly satisfying, but I could not describe why ๐
you should look at some parsec code
https://jakewheat.github.io/intro_to_parsing this has some code in there
If I understand correctly, this can help me create an API such as the one I described, right?
I'd say this is a generalization of what you were doing, thought you could at least take some inspiration from it
Ohh, yeah I see what you mean!
Again, it's a generalization, it can do more than what regexes can
So that may be a bit more complex i guess
Even tho I'm not sure how exactly, it's basically building a state machine through functions
It's definitely good to look at approaches to solving very similar or even more general problems to understand how to solve my problem
Thanks again for showing me this :) It will probably help me get there if I do decide to bring this project to life
I think I should mention the core idea of parser combinators is to have function that takes one or more parsers as input and return another parser as output, so you can have like
foo = Parse("foo")
bar = Parse("bar")
baz = Parse("baz")
foo_or_bar = foo | bar # or like Or(foo, bar) if you don't like operators
foo_or_bar_followed_by_baz = foo_or_bar >> baz # could be .then(...)
```etc
hmm
I'm not sure why I would combine parsers since I'm only parsing regular expressions ๐ค
Yeah, right, I'm just building a regex string using the builder pattern, really
It's cool to know these thimgs though as they're somewhat related
I've seen other projects like this. They don't seem to get wider use.
@spark magnet If you don't mind me asking, can you recall one of them at least? I'd be interested in seeing how they did it
I was just googling that, and I found one
And there's emacs' rx, which is basically the same thing using its macro system https://www.emacswiki.org/emacs/rx
Ah I see
VerEx is actually close to what I wrote, but unfortunately falls short in versatility and readability
don't think .find(string) is a good design choice
It's actually just + r'text'
in the API I described above
oh right
that's a lot of groups lol
in fact nothing is not in a group there
idk if I like that
probably better to have a string concatenation-like API
because that's what's happening under the hood anyways
which means the API would feel less like a black box
Just had a different idea:
import regexpressive as rex
my_text = "texttexttext Name: Guido moretext"
pattern = (
r'name: '
+ rex.group(
rex.multiple(
rex.WORD_CHARACTER
)
)
)
regex = rex.Regex(pattern, case_insensitive=True, multiline=True)
# compiles itself automatically the first time it is used
# and keeps the compiled regex internally
name = regex.search(my_text)[1]
a functional design
Guys this is a weird question but could I code something in python that would draw a non commutative ring from an equation like this
It is similar, but works differently
I think you wanna use a help channel for that Matty
The answer is yes but no idea how, hope you'll get help! #โ๏ฝhow-to-get-help
It is similar, but works differently
This time around I'm explicitly expecting the user to compose a pattern string to pass torex.Regex
That way I am even more transparent about how things work, but also need the user to understand a little bit more
It does feel like just the right balance though
in fact it feels so easy to implement I am sure this has already been done
Yeah; that there is a pattern string
There might not be any real difference actually
Yeah they sure are
Though this is for Python :p
It feels like Click's style
Simple is better than complex
Yeah, I think what we got now is a really good design
just the vibe I'm getting
Yeah,,,, I think differently about code ig
Couldn't explain what I meant if I tried
I guess it has something to do with the functional nature that both the code I sent above and click.style share
I've been researching more into different concurrency models, and it seems python is able to implement multiple versions. Yeah, there is asyncio, but the concurrent.futures library has the classic primitives of threads and processes and you have libraries like ray that implement the actor model.
In comparison to a language like golang that favors CSP via channels and goroutines built into the language, is Python at a disadvantage since concurrency/parallelism was an after thought until recently?
For the record, I do admit a bit of recency bias after reading the book "Seven Concurrency Models in Seven Weeks" and using the actor pattern a lot at work.
(Fun aside: I think subinterpreters are interesting because they communicate CSP-like from what I can tell. I think that is cool to be an awesome game-changer when they come out.)
That is correct, Python is indeed at a disadvantage because of that
but the main reason why Python is at a disadvantage when it comes to concurrency is the GIL
To cut it some slack, it's actually not that much of an afterthought, but due to certain design decisions Python was not thought to be or become extremely parallel for a long time
That is as much as I know
Oh....I am not a GIL hater like some out there. For many things I deal with, the GIL isn't much of a problem. Either I need to be a better coder or write my stuff in C/C++/Cython.
I just don't know if being a "jack of all trades" in async stuff is "better" for development and use instead of golang's model being the "one and primarily only one" way of doing things.
Different concurrency strategies work (better) for different problems methinks ๐ค
Also, one of the biggest proponents of CSP was on the core team that built go. so...
I appreciate the heavy lifting into the asyncio stuff, but the apis still feel a bit clumsy in comparison to working with Node and doing async/await stuff.
it is still a bit of a second class citizen - the fact that Python supports multiple concurrency paradigms is from one perspective an advantage, since it lets users choose the one that seems easiest for their current problem, but the fact that there are a mix of blocking library calls and library calls that expect to yield to an event loop means that the user freedom goes hand in hand with some extra complexity.
Basically entrusting that the dev(s) can make decent decisions.
and can understand why, for example, there's an asyncio.Queue and a queue.Queue that behave differently.
I appreciate the heavy lifting into the
asynciostuff, but the apis still feel a bit clumsy in comparison to working with Node and doing async/await stuff.
@torpid narwhal I fully agreeand wish something like trio would've made it into the stdlib instead
@modern frigate You'll get there :)
This channel is specifically for discussions about Python itself, at the level of the language and its design choices.
it won't be for everyone. ๐
@raven ridge Yeah, that is annoying.
ah lol. looking bad, i guess i do get some of it, but still confused hehe
And, I fully admit this is way higher level stuff. I basically have been in a deep dive in concurrency models the last few days.
@tawny shoal Why trio?
Because I really like its DX (developer experience) and its API design feels very elegant
trio is definitely worth checking out. It uses the same language features that asyncio is built on top of, but builds abstractions that are more high level.
far less clumsy than asyncio at least ^^
I still remember asyncio.coroutine, that was wild
Tysm Yury for blessing us with async/await
yeah. There are very few times where I will put Node above Python, but I would rather deal with promises and async/await than Python's async/await and asyncio. I will check out trio.
I'm pretty sure python's async system technically isn't a promise system under the hood
Js has it like that just as synactic sugar for the promise system
Python's system is based of generators mainly and the coroutine system
One of the things that put python at an advantage other alot of things is the asyncio event loop
Well, most languages have an asynchronous framework
!tempban 678484214311682130 1d Please get you act together
:incoming_envelope: :ok_hand: applied ban to @glad crow until 2020-08-04 10:32 (23 hours and 59 minutes).
How come MyPy lints this: Mypy: Incompatible types in assignment (expression has type "Optional[str]", variable has type "Tuple[Optional[str]]")
when doing
self._host = host where host is a string
Probably more fit for a help channel, depends how self._host is declared
Im just trying to work out How mypy or strict typed python classifies the types
Looks like self._host is a tuple.
Its seems its linting it as a tuple just via a standard type hint
host: str = "127.0.0.1", to mypy seems to be Tuple[str] which doesn't make much sense considering the Python doesn't directly deal with strings a u8 vectors no?
You seem to have a stray ,
its part of a larger parameter section
That's odd
this really looks like a trailing comma
I mean typing it as MyPy expects it being Tuple[str] i dont mind much but it seems weird that it identifies it as that
That's host the mypy is referring to self._host being a tuple
@radiant fulcrum Show some more code.
The expression is host and the variable is self._host (in the error message)
You know i think ive worked out why its doing it
would help if you posted the function
I left the doc string describing it as Optional[:class: str]
you have trailing commas
wait
this makes self._host a tuple
That's one of those muscle memory reflexes you develop after a while. When you start getting unexpected tuples, look for stray commas.
Ive been switching between Rust, Go and python non stop for the last few weeks so everything is all over the place
that being said, i'm curious, can you post the command you run with mypy
Ive had alot of stray := and let's all over the place
I feel that haha, glad you found it at least :)
@teal yacht Im just using the MyPy extension for pycharm
it lints it in the background and then highlights accordingly
I was certain mypy cannot use docstrings ๐ค
some of it is PyCharm making use of them
It doesn't. My guess is the error message was referring to the run function that was written correctly, but in the __init__ self._host was set to a tuple
yeah
yeah i just looked, it's pycharm's builtin type checker
the trailing , at the var defines
they call it "legacy type syntax for docstrings"
Also is mypy different? Because I thought Optional meant that None could be provided as a value
Its me not doing it properly
the optional is only specified in the docstrings, so it looks like it's somehow passing the docstring types to mypy
i dont normally strictly type so much in python compared to Rust and Go which have it by default
trying to get into the habbit of strictly typing py aswell
^ like i tell people, strict annotations prevent a whole class of errors
At the cost of having to occasionally use typing.cast
sometimes assert helps avoid cast
Mypy is smart enough for that?
We need a python type checker shootout
Speed, user interface comparison, intelligence/cleverness, correctness
Is that a mypy feature or part of the language spec
the language only includes support for type hints and the typing module really, theoretically, type checkers can implement whatever they want based on these type hints, but afaik, all the relevant type checkers implement that
How do non-functional but strictly typed languages handle this?
C isnt a good example because the type system is kinda loosey goosey
Too low level
Or do you basically need monads to make this work without complicated inference and/or casting
How do non-functional but strictly typed languages handle this?
@paper echo what do you mean by "this"
input accepts one of 2 types, somewhere along the line one type gets cast to the other
fwiw, hindley milner is a type system capable of global type inference and it's scandalously trivial
of which a special case would be Optional[A]
referring to the "complicated inference", but i see this is not what your question was
yeah ive heard that term, i need to look up how hindley-milner inference works
by complicated inference i mean "figuring out when the programmer has asserted or cast the type of a variable"
because checking for isinstance is kind of crude heuristic no?
you can loosen up the constraints on the argument's type, there are multiple ways to do it, typescript does it using typeof to basically infer the type based on conditions, exactly like mypy, or we can use a subset of what would look like structural subtyping, but the N types will need to share attributes/methods, in the same way we would declare generics, except constraining it to N specific types
i see
one day structural subtyping with global type inference will be the standard
so we can finally have true static duck typing
what do you mean by "global" type inference, as opposed to any other kind of type inference?
as in you don't need any kind of type annotation, unlike for example c++'s auto which only works locally
like you can have
def foo(x):
return x.y + 1```and the type could be like
```ocaml
val foo : <y : int; ..> -> int```
ahh. i forget what language i was looking at with that feature recently, maybe F#
any ML, ocaml, standard ml, f#, as well as haskell like languages
yes it can
isnt the problem with python that basically anything can return any type at any time, and if you dont annotate then python cant infer anything
well, with generic it can I guess.
haskell uses a superset of hindley milner, which already supports global inference
yes, but haskell records do not work such that a function like f x a = x.y + a can have an inferred type(or be made at all)
oh, right right
inferrence to varying extent is present in most modern statically typed languages, e.g. Rust, kotlin, swift, scala. It is not full ML/Haskell inferrence, however
yeah, i'm glad it's becoming more recurrent, despite the communities adopting them with varying degree
even C++ has some inference with auto
but it won't be able to adopt full inference because of how coercion and overloading works
huh?
This might be a silly question but has anyone tried writing a borrow checker for python like the one in rust? Or maybe tell me why that's impractical?
I highly doubt it, that'd imply a reimplementation of python minus the gc, + some extension to the syntax to make it support hints for lifetimes, there's also the issue that current implementations are commonly based on affine types, that is, lifetimes are encoded within the type system directly, that would assume static typing too
So while you could do something that looks like python superficially, it wouldn't really be fair to call it python anymore
there would be no point of borrow checking
Its a garbage collection based lang
Borrow checking can also Decrease development speed dramatically which removes one of the biggest selling points of python
Thanks, yeah
Of course that wouldn't be possible because it would be a hell of a breaking change, but if it was possible, would you prefer to import the standard libraries like it is done now (import random), or having them prefixed with python. (import python.random)? This would make it more obvious if a package more obvious if it is in the stdlib or not, but it would be a bit more typing in the import statements
I don't think it's necessary, but it does make sense to put all the standard modules into a package, perhaps not python but something like stdlib
from stdlib import random, for example
Part of the import structure is to search installed packages/modules if it fails to find locally (cwd)
something like that should prevent standard libraries from being overshadowed by local files, I guess
or at least for as long as there is no stdlib package/module present locally, which I can't see happening often
The current system does lead to cleaner imports, and makes backports somewhat nicer to use
what does reversed(list) do under the hood? is it similar to list[::-1]
it's an iterator that just goes through the list in reverse storing indices
It probably does the same thing yeah, but with something similar to a range
It is implemented in C
[::-1] generates a reversed slice immediately, while reversed will return values lazily
Yes
Indeed, that's a generator
it keeps the last valid index known at creation time and then goes down from that to 0
You could reimplement it in python like this:
def reversed(iterable):
total_items = len(iterable)
current_item = total_items - 1
while current_item > 0:
yield iterable[current_item]
current_item -= 1
(I think to 0, not sure)
list indexing starts at 0 so probably
You could reimplement it in python like this:
def reversed(iterable):
@torpid bridge what do u put under the function
hit enter early
Well, sort of
there's more detail, like searching for __reversed__
wouldn't making all those variables take up unnecessary memory?
gotta keep track of them somewhere
less memory than generating a reversed copy of that list
^
that's the general tradeoff between [::-1] and reversed()
do we keep track of our place and scroll backwards as you want items? or do you just flip it now and be done?
the former
In all honesty, the memory consumed by two ints is very small and unlikely to make a difference
yes, python has a max index size of... 64 bit I think
lol
reversed_meth
nice variable name
also bast
do you know how to use pypy3 in windows cuz apparently python is "slow" compared to languages like c++
"in window"?
windows?
I mean, yes, it's "slow" in comparison. But that's short perspective
It can still do > 1million things per second
well c++ does more then
pypy provides windows binaries
yes thats why i wanna know how to use that
which speeds stuff like looping up considerably
However you dont get much support for C based libs
For lists themselves it's here https://github.com/python/cpython/blob/da4e09fff6b483fe858997da5599c25397107ca1/Objects/listobject.c#L3292, it's really similiar to what Bast did above but with some additional checks and implementing iterator behviour
its recommended for competitive programming if u wanna use python
which is a minority of the people
you cant install it tho?/
only if you are doing long tasks
u get a zip right?
pretty sure it runs with pypy myfile.py
pypy is not recognized by cmd tho
PyPy on windows when you install it will use your highest PATH set python version for the std libs
i dont know how to set it up properly
maybe pyenv works on windows (answer: not really)
So i had Python 3.8 highest just under Intel py which ment PyPy inherited the 3.8 packages which isnt ideal
Try what you're trying in python
if python isn't fast enough, take what you learned and write it in rust
C++ is a very hard and annoying language to get used to
why rust?
and you can use PyO3 to make a python module for it
because Rust doesnt fuck you
because in rust, if you want to install a package, it's cargo install package
C++ has alot of weird and wonderful things and does (I think) manage memory safety or thread safety for you
in c++ if you want to install a package, the answer is start praying
also, compiling? cargo run
c++? praying, again
not to mention the bloat machine needed on windows for build tools
another reason why I like python. python myfile.py
does python plan on supporting manage memory safety or thread safety for you
yes
Python does
Python is garbage collector Lang and GIL
probably Not
depends
or godot
There are games in python, and IIRC Civ 4 was written with python for scripting
Main engines Like unreal are C++ or C# in some cases
C#/C++ would be better options for gamedev
aaaaaaaaaaaaah
you will likely hit pain trying to write the graphics code in python, but that's to be expected
If you are an artist, yes, otherwise probably not
Actually, it isn't harder in python
If you want to update every pixel of a texture multiple times a second, it's simple rust code or numpy fun in python code
What i would say
"fun"
Libraries like ModernGL makes integrating OpenGL really easy, like in any other language
just dont put yourself through that pain
dont use windows to dev on it
@radiant fulcrum wdym
is rust similar to c++ in terms of speed
and functionality
Yes
It's got identical speed, and in some cases more, some cases less functionality
so i can game dev with it?
Yes
i see
you can do game stuff in rust there just isnt much support for it atm
tho i wouldnt be supprised if stuff came out in the future
Real gamedev from you alone will probably depend on a game engine that already exists, limiting your language choice to whatever that uses. You can create an engine with a bit of effort but it won't come close to the toolset already existing commercial engines provide
is rust new or old
From my experience, it's really just the 3d stuff that's painful at the moment
new
like newer than python?
much
Python is very old
Rust is only 10 yrs old
so if i had to start learning a language, c++ or rust?
rust
python 2 was started in 2000, and rust started 10 years after
Its just a more enjoyable experience
would rust do well in competitive programming
Very
Rust is one of the fast languages around at execution speed, equal to C++ if not faster in cases
but why do the majority still use c++ then
because C++ is donkeys years old
C++ has been around for wayyyyyy longer than Rust has
C++ is from 1985, rust is from 2010 and gained proper async stuff.. 6months to a year ago?
and only in the recent Years has Rust gained popularity since pre 1.x was a reallly painful experience
?
what this dudes tutorials^^
He goes over the concepts that you Need to know when doing rust to get anywhere in the language
Considering how PyO3 intergrates rust and python pretty well
otherwise you will be clueless to whats going on around
I don't think it would be strange the blend them
One thing you'll run into with rust is it requires you to know what you want to do very precisely
python is much less restrictive on that front
C++ pretends to be less restrictive, but it really isn't
Rust: no, you can't do that
C++: You can do that sharpens knife
Python: sure. Also, I'll make sure that doesn't bite you later by keeping your stuff together for you
Go is also a pretty fun language tbh
Its basically a compiled strictly typed python
the only issue is you really are stuck without any low level stuff or and C compatibility
Go seemed a bit bland, vs python.
I can understand why they didn't go with try/except
I like it tbh, tho ive gone back to rust again after switching for the last 7 times
I cannot understand why they went with if err != nil
overhead ig
literally, something like 15% of all go code is that line
I feel like discussion of Go/Rust is OT for this channel - but Go's exception handling is very nice, it's much cleaner than try/except I feel - try/except really doesn't add all that much utility vs Go's method
I do prefer Go's methods for EH
Meet you in #ot2?
yes
when you write ProcessPoolExecutor.submit is the data for the work sent to the process right away?
or is it "held" in the calling process until the executor is ready?
wondering about overhead of big multiprocessing jobs w/ ProcessPoolExecutor.submit + as_completed as opposed to Pool.imap_unordered
There's a brief explanation of the ProcessPoolExecutor implementation at the top of https://github.com/python/cpython/blob/master/Lib/concurrent/futures/process.py.
If I'm understanding it correctly, then it looks like the data is "held" in the calling process.
interesting
in the calling process, but a separate thread
nice find
so potentially there is additional process spawning overhead compared to Pool methods with the chunksize param
i just wish there was imap_unordered with executors, so i could use tqdm for a results progress bar but still have the option to use chunksize ๐
I'm not familiar with multiprocessing.pool. Is chunksize > 1 just a way to reduce communication between processes by sending data for multiple calls together?
I guess you could modify your code to submit batches of data to ProcessPoolExecutor, but it's not ideal.
yep that's exactly what chunksize does
Rust is one of the fast languages around at execution speed, equal to C++ if not faster in cases
@radiant fulcrum If I get good at rust, would I be able to pick up C++ quickly? Like, is rust built off of C++ syntax or is it completely different? I'm just curious about the transferability of skills between the two. For example, making the jump from Fortran to C++ is not trivial.
concepts might not be as unusual for you, but Rust's system for stuff is pretty unique
@radiant fulcrum ๐ thanks for the explanation
I think Rust was designed to be a better alternative to C++, so I do think it might one of the languages that better prepare you to learn C++, but they are quite different both syntactically and conceptually. It's just that they solve similar problems, so I think it might easier to understand C++ with Rust under your belt. Both are pretty difficult languages to learn, though.
Yes and no. Rust's approach to memory management is vastly different compared to how the C's do it
So while the level of abstraction might be the same, the way you approach writing your code don't really mesh
If you're talking about C++/Rust here: what's a good language to learn for someone who has only ever learned high-level ones (Java, Python) and wants to dip their toes in lower-level? Out of C, C++, and less known ones like Rust apparently.
@full jay That's true, but you can see how Rust's model evolved from C++, especially the modern Boost-based abstractions.
C++ smart pointers are pretty similar to what rust has, just with less syntax support and overall worse
Fair point
@pearl river I think Rust is the superior language, so I would probably go with just diving into that.
Maybe C would be beneficial as well. It's a decent way to get introduced to manual memory management, and it can be useful if you wanted to get into embedded development.
C++ feels like too much of a time investment if you're just gonna move onto Rust later.
Thanks!
@random birch asked in #algos-and-data-structs if the garbage collector only activates at the end of a scope. I thought it will collect any non-permanent thing as soon as the reference count reaches zero, however that happens, but that all the variables in a given scope have their reference counts decremented at the end of a scope, which could trigger a number of collections back-to-back.
wrong channel bud
this one's for Discussion on the use cases, implementation and future of the Python programming language including PEPs, advanced language concepts, new releases, the standard library, and the overall design of the language.
gc doesnt always happen immediately at 0 references @boreal umbra
>>> from weakref import ref
>>> a = A()
>>> r = ref(a)
>>> r()
<__main__.A object at 0x000001CDD66B1988>
>>> del a
>>> r()
<__main__.A object at 0x000001CDD66B1988>
>>> r()
<__main__.A object at 0x000001CDD66B1988>
>>> r()
<__main__.A object at 0x000001CDD66B1988>
@steep cove take a look at #โ๏ฝhow-to-get-help. I would also encourage you to turn off caps lock.
@clear coral wouldn't del a still be decrementing the reference count, but r would still contain a reference to it?
r is a weakref, but I think that more has to do with it being in the repl
what happens if you still have a weakref but the object has been deleted?
You get None
wouldn't you get a lot of unexpected behavior?
I think this suggests things with the ref count at 0 should get collected immediately https://github.com/python/cpython/blob/b4e85cadfbc2b1b24ec5f3159e351dbacedaa5e0/Modules/gcmodule.c#L425
of course it's still not guaranteed to happen at all in some cases
I think if we already have weakref, I feel like my earlier global del idea isn't as bad as I thought.
@peak spoke calling gc.collect will result in r() returning None afterwards. if the repl was somehow keeping a alive behind the scenes this wouldnt be the case.
I assume it kept it alive because _ was pointing to it
it wasnt
_ is for free values that get pushed onto the stack
like if you just type 1+1
or if you call some thing() then _ will be set to its return value
>>> from weakref import ref
>>> class A: pass
...
>>> a = A()
>>> r = ref(a)
>>> r()
<__main__.A object at 0x00000191554A0AF0>
>>> del a
>>> r()
<__main__.A object at 0x00000191554A0AF0>
>>> _
<__main__.A object at 0x00000191554A0AF0>```
yeah no, it's pointing to it
Try it with prints wrapping the expressions
>>> _
<__main__.A object at 0x00000191554A0AF0>
>>> 5
5
>>> _
5
>>> print(r())
None```
About as soon as you drop the `_` reference, it turns to `None`
>>> a = A()
>>> r = ref(a)
>>> print(r())
<__main__.A object at 0x00000191554A0AF0>
>>> del a
>>> print(r())
None```
Wrapping into print skips the `_` reference
then why does gc.collect kill it
_ gets an another result
gc's collect shouldn't have much to do with it unless the repl is keeping reference cycles in the back
yeah, collect returns a number (I assume it's the amount of collected items)
>>> a = A()
>>> r = ref(a)
>>> r()
<__main__.A object at 0x00000191554E2400>
>>> del a
>>> res = collect() # skip _ reference
>>> r()
<__main__.A object at 0x00000191554E2400>```
on a similar note
if you have an instance of a class that you made, you can arbitrarily give it attributes
why can't you do that with an object()?
I think object doesn't have a __dict__, just __slots__
I see
types.SimpleNamespace comes in handy when you need that
You can't give arbitrary attributes to object for the same reason you can't do it to any built-in, essentially
I figured the not being able to add attrs to builtins was added to each builtin individually, since classes that inherit only from object have a __dict__.
Not sure if it even has slots, just no dict so can't have instance attrs
there's no accessible __slots__ attribute apparently
could have something to do with the fact that it's implemented in C
you can overwrite/add attributes via forbiddenfruit
I think object just has attributes that map directly to fields of the pyobject struct
Why don't map and filter support asynchronous iteration?
f: A -> B
g: AsyncIterator[A]
h = map(f, g): AsyncIterator[B]
something like that?..
my guess is that it's simply not what the python core developers want to spend time on
we have async comprehensions
makes sense
https://www.datadoghq.com/blog/engineering/cgo-and-python/
Calling python from go...interesting.
Basically, one would use go's FFI to call the Python C api. Not sure what advantages this gives one....but interesting example of what one could do.
honestly by the time you learn how todo it all and set it up you might aswell do it all in go
the syntax really isnt massively diffrent overall
in datadog's case they have an agent that runs other peoples code and there is already a large amount of plugins written in python. there's no world where they could say "we rewrote our agent in go, everyone has to rewrite everything"
having written monitoring agents before though I'd probably go with a process per plugin model with IPC so plugins can be written in any language and you don't have to work about poorly written plugins messing with your agent nearly as much
"run X lang from Y lang" is kind of a nice thing to have anyway
esp telling SREs to rewrite in Go gary
that would quickly go to "Go to hell Datadog"
What is the best way to iterate over two lists with both zip and enumerate ?
Is this considered a good practice ?
list1 = ['a', 'b', 'c']
list2 = [1, 2, 3]
for i, (a, b) in enumerate(zip(list1, list2)):
print(i, a, b)
yes
Ok, thanks !
i thought that read "is this considered bad practice" and i was like how on earth would that be considered bad
i started using VS code for some frontend stuff at work that i need to learn, and ngl, it's pretty legit
Hi, I am an intermediate level python user and wanted to know how often you use async and await at an advanced level? Do you only use it at the end for optimization purposes ?
It really depends on the app, if it's async you'll be using it a lot
how can I install and use the latest python version on google cloud debian ssh console ?
okay so
you use it when doing asynchronous IO. If your project uses async, you will use it all the time, if not, there is almost no case where you use it
Type in "||Python your mom version||" in google search
@verbal drift RealPython usually has pretty good guides, here's one about async: https://realpython.com/async-io-python/
maybe I'm missing the point of what you said though.
thanks guys
If you're just asking about when it's used, not all advanced Python use cases use async. I think it's mostly for event-driven programs
Most of what I do is data science and I've never used async, but I'm also not very good 
!tempmute 677994881779630094 3d It seems that you're only here to make jokes about inappropriate body parts and mothers of other people.
:incoming_envelope: :ok_hand: applied mute to @teal notch until 2020-08-07 19:18 (2 days and 23 hours).
Async is pretty interesting in the web-dev world because of how much "work" there is waiting on IO. There's still a ways to go (you still need to be very careful about calls to things like DBs which are usually synchronous), but it theoretically makes it so a single process can handle way more requests, making it easier to scale out
But, at least for me, I don't use it at all (currently)... it's still a bit rough around the edges. I think Django just had a release today adding support for async views and middleware, which is an awesome step.
is it hard to implement, or/and (&&, || lol) does it take a lot of time ?
Anyway, right now if you want to handle multiple requests at a time in prod, you traditionally use gunicorn/uwsgi and have multiple processes. This is expensive especially when compared to threads or coroutines... async lets each process potentially handle multiple requests, using async/await to yield to other requests (in laymans terms).
I'd personally avoid it unless you absolutely need the performance or you're making something that absolutely has to be in real time
It's useful, but can be fairly complex, and has a number of easy-to-miss pitfalls
okay thanks, the thing is that python tends to be on he slow end, so I thought optimization (such as async) would be used more often at a higher level
Async is not really an optimization, it's a whole another way of designing your code
async/await is a programming paradigm, cooperative multitasking is an execution model
also @cloud hill worth considering
http://calpaterson.com/async-python-is-not-faster.html
https://lucumr.pocoo.org/2016/10/30/i-dont-understand-asyncio/
https://lucumr.pocoo.org/2020/1/1/async-pressure/
Async Python is slower than "sync" Python under a realistic benchmark. A bigger worry is that async frameworks go a bit wobbly under load.
A little confession that I have no idea how asyncio works in Python 3.
An introduction to back pressure in systems and why it matters.
I'll read up on that
I'm admittedly more familiar with async in other languages, though I assume there are a number of similarities
The GIL does change things a bit though
it does not, python async is generally single threaded afaik, just using epoll/select/poll/libuv to pick what to handle at a given time
Which, if you're specifically limited on network (and using async calls for all network calls), can perform better
The GIL should only come into play with executors, other than that it's an event loop running in a single thread
Most of the time anyway
exactly @flat gazelle
terminology salad: single-threaded single-process asynchronous i/o with an event loop that implements cooperative multitasking
Fair. I think django does some magic to let you make non-async blocking calls on another thread, but I haven't looked into that...
async does make it a lot easier to scale out to write real-time applications... since each request taking up a full process (as would be the case with uwsgi/gunicorn) would be incredibly expensive.
But most people also don't need to write real-time applications
one of armin ronacher's complaints has to do with backpressure
basically you can have an arbitrary number of coroutines all blocking themselves
Ah, there is a lot of good stuff in those articles "async/await is great but it encourages writing stuff that will behave catastrophically when overloaded."
Also, some of the benchmarks use a fairly old version of Django... I'd be interested to see similar benchmarks with the version that just released with async views and middleware.
{1 : 2} == {1 : 2} returns true, why is this though? this is because a __eq__ dunder is present?
yes
Well, yes, dicts have comparison operations. Well, equality ones that is.
Yes, AFAIK, types in CPython contain vtables of operations like addition, equality etc.
So it's not that hard to implement operations that make logical sense for basic data structures.
This creates unsurprising (at least logically/mathematically) relations like {1: 2} == {1: 2} or [1, 2, 3] == [1, 2, 3, 4] or "abcd" == "0abcde".
hi guys
guys what is the easiest way to create a command line programe using python
@drifting fossil This is not a help channel, read the channel description. Please use #โ๏ฝhow-to-get-help .
Why does "create task" start an asyncio task?
Like what if i want to create a Task but not actually run anything yet
like just creating a task but not running it is basically like just returning a coro no?
thats essentially just returning a coro no? or similar to that
ensure_future makes more sense as a name
Compared to create_task
But it's not really clear why we need both ensure_future and create_task to co-exist these days.
im not clear on what an asyncio Future even does
Well ensure_future's name makes sense, but wat the function actually does doesn't make as much sense
do they just exist for backward compatibility inside the asyncio codebase?
Futures are a lower level API
Can you use asyncio as a job scheduler
It allows you to work with things besides coroutines
We use Jenkins at work to monitor when jobs submitted to be Grid Engine finish
I'd rather be able to do it in python
Jenkins kicks off additional scripts after those jobs finished
call_at needs to be an absolute timestamp w/ respect to the event loop's internal clock
not necessarily a proper unix timestamp
Yeah I feel like I need to learn how to use asynchio
One of the few modules I've never touched
Seems useful
ensure_future will return the object you pass it unchanged if it was a Future or Task, otherwise it returns a new Task - so, if you have a coroutine and want to turn it into a Task, ensure_future will do that (despite its terrible name).
actually, though, seems like it schedules the new Task as well - I thought it didn't. So, nevermind.

for list comprehension syntax, is it valid to have a one-liner at the end like this?
myList = [myObj for myObj in myObjList myObj.MyBoolean = True]
Nope, that's not a valid comprehension
damn it lol
what's your goal?
Does the walrus operator support attributes?
i was just trying to set a property on an object before i feed it into a list of coroutines. i can do it without a list comp though
You are not allowed to use that command here. Please use the #bot-commands channel instead.
it's just like a normal =, except it also returns the value
i was just trying to set a property on an object before i feed it into a list of coroutines. i can do it without a list comp though
@minor sinew it's generally considered bad form to have side effects in a comprehension
ah yeah, you're right
like theoretically speaking you could do myObj.__setattr__('MyBoolean', True) but that would be all sorts of disgusting
but either way, you shouldn't use a list comp there
you could do [... for MyObj in ... if not setattr(myObj, 'MyBoolean', True)]
I feel physically ill
map, partial, and setattr may be better
I think this is rapidly devolving into #esoteric-python territory, and not in a good way
map is a generator, so you'd need to iterate through it as well
[*map(...)] :)
yeah these are all bad ideas lol
[(myObj, setattr(myObj, 'MyBoolean', True))[0] for myObj in myObjList]
but don't do that ๐
all(map())
Then again, causing side effects on a comprehension is a bad idea like @gm had mentioned
[(myObj, setattr(myObj, 'MyBoolean', True))[0] for myObj in myObjList]
but don't do that ๐
@raven ridge I was thinking of this too
shoehorning to the max
don't use a list comp if you don't need to save the data
it's so horrific the camel case doesn't even register on my radar
heh
hahahah
putting underscores after every word is even uglier imo, but to each their own
[(my_obj, setattr(my_obj, 'my_boolean', True))[0] for my_obj in my_obj_list]
well, now it's pep8-compliant
whats wrong with using inline if?
what's wrong with it?
myObj
a regular for loop is just easier to read if a list comp can't do what you want
fixed
no point shoehorning some functionality if it's terribly difficult to read lol
what's wrong with it?
(well, not counting the fact that it has the condition after the then-branch....)
[my_obj for my_obj in my_obj_list if not setattr(my_obj, 'my_boolean', True)]
honestly I prefer that order to what you might see in Haskell or something
oh
abusing not None for truthiness
true_value if condition else false_value just seems more readable to me because of the "if" and "else" words
naming convention is pretty irrelevant as far as you being the sole dev in your own repo lol
like I can see condition ? true_value : false_value in C etc. because there aren't words
if you work on a team (99.999% chance of this happening), you should 100% comply with what's used
conditional operator syntax in python is pretty unpleasant
as much as i sympathize with their decision not to use ? : i really don't like how "inverted" it is
it's really hard to read
maybe that's by design, to prevent you from being tempted to use it more
incidentally, does anyone think that empty collections being falsey is undesirable?
like lambda
i definitely prefer the && and || instead of and and or
python is a bit like go in that respect
conditional operator syntax in python is pretty unpleasant
@paper echo I think I'm the only person who actually likes it
@gleaming rover i think it's legitimate
i dont hate it, you just can't use it for complicated expressions without \ line breaking
I think allowing non-booleans in conditions is a sin ๐
yes
just pretend bool() is wrapped around everything after if ๐
and IMO it's weak typing (I don't mean that pejoratively)
even as the sole developer on your own repo, it's better to follow the relevant coding standards. it's easier to learn good habits from the start than break bad habits later.
that's basically what the if does right?
the coding standards for variable names is different from language to language lol
duck typing != weak typing
i think the idea of an empty container being falsey is the ability to write if not lst:
so for the most part, it's pretty irrelevant unless you're working on a team
no, it's not
i think the idea of an empty container being falsey is the ability to write
if not lst:
@paper echo orif iterable, conversely
yep
but IMO that is weird.
like how many other languages treat an empty container as a false value?
python is strongly typed, but types are defined at runtime lol
the coding standards for variable names is different from language to language lol
@minor sinew oh yes, definitely - but Python has a strong standard for it that nearly everyone follows, and not following it makes your code look amateurish, and will make it harder to get a job, or get your code accepted into OSS repos, etc
it's not even that much clearer than checking the length like: if len(lst) < 1
it's not like matlab which is weakly typed, and types are defined at runtime
python is strongly typed, but types are defined at runtime lol
@minor sinew yes, that's what I'm saying; it's not fully strongly typed
because you have automatic type coercion in stuff like if
doesnt C++ do a lot of implicit type coercions
yes
does that make it strongly or weakly typed?
weakly
makes sense
weakly statically typed
so python is weakly typed but not as weak as, say, javascript
C++ would be weakly typed without that because of memset and such
and over there you have the weakly dynamically typed JS
C does relatively few implicit type coercions... but it does coerce between basically every numeric type.
C++ does significantly less implicit coercion than C
!e
g = (x for x in ())
if g:
print("oops... :)")
how strong is ruby's type system compared to python's?
@grave jolt :white_check_mark: Your eval job has completed with return code 0.
oops... :)
yeah exactly @grave jolt i was going to say
C++ does significantly less implicit coercion than C
@teal yacht Huh? C++ is (roughly) a superset of C; it has every coercion that C has.
bool() needs to do the right thing
it's a really leaky abstraction that depends on every programmer of custom iterables writing them intelligently
it's not even that much clearer than checking the length like:
if len(lst) < 1
@feral cedar less even, IMO
"intelligent" == "the iterable knows when it contains more data to be read"
ok so fair point @gleaming rover , maybe python didn't need falsy empty containers
how about falsy None?
yeah, create LengthAwareIterable protocol :)
i'd rather just have to check is None
None is another page of discussion...
how about falsy None?
@paper echo split on this
what if we had three-valued logic...
at least python didn't conflate None with null pointers ๐
although I am a big fan of explicit option types
me too ^
!pep 505
yeah, those look nice
lest we forget
and static type checkers have to do some work to make sure you don't miss a None
How about making Optional an actual optional class that can be used 
that opens up a really big can of worms though
how far down the monad rabbit hole do you want to go
yeah
I'm not sure if it would be productive for the majority of people
even though from a conceptual standpoint I like it
also it would be ridiculously backward compatibility breaking if it would replace None
and superfluous if it wouldn't
i think none-aware operators are good enough for the majority of Maybe-like use cases
is Optional a special thing? is it a specific case of something generic?
Well,async/awaitwas added.
true.
incidentally, is for-else unique to Python?
but they implemented it with a generic protocol which is my point
if Optional has some kind of monad-esque behavior, how is it actually designed into the langauge?
*redesigns language from scratch*
@raven ridge if someone is judging the content of my code in my own repos that im the sole developer solely based on my variable nomenclature, then i simply don't want to work for them lmao
everything else you mentioned is when it becomes important, which is working on a team
while we're on stuff that is weird and crufty
I would really appreciate it if id was renamed
yes
yeah
can we also snake case everything
- identity
- some ID
@minor sinew well, the "learning bad habits" part was more generally applicable, too.
getLogger
datetime.datetime -> datetime.DateTime
if we had a wishlist for Python 4, id shouldn't even be a builtin.
hell, about half of the builtins shouldn't be builtins.
getLogger
Yikes
id should be somewhere in sys
@raven ridge some devs like the underscores. some other devs like camel case. like i said before, it's only a bad habit if you can't break it when you go to a team, so it's a bit irrelevant otherwise.
chr and ord certainly don't need to be builtins.
Python has like the most polluted default global namespace ever
and they removed reduce :)
:)))
oh, and most of the exceptions are imported by default
Hmm. Well, maybe (no pun intended) it's possible to add a decorator that would implement do-notation?!
# one_over: float -> Maybe[float]
# sqrt: float -> Maybe[float]
@do
def f(x):
reciprocal = await one_over(x)
the_sqrt = await sqrt(reciprocal)
return the_sqrt * 3
# equivalent to:
def f(x):
return one_over(x).__bind__( lambda reciprocal: sqrt(reciprocal).__bind__(lambda the_sqrt: the_sqrt * 3) )
like, it could parse the AST or something
Eh. Iโm working on a rails project now. Thatโs more frustrating than any bad python stuff.
@raven ridge pointers don't get implicitly casted like in C, for example, this is invalid C++
int main()
{
int *arr = std::malloc(10 * sizeof(int));
return 0;
}
that code makes me feel equal parts sick and warm inside
but the weak typing part is that you can cast them like that
but the weak typing part is that you can cast them like that
@grave jolt I don't think that's weak typing....?
weak typing is about implicit typecasting
Well..... maybe
weak/strong is about *implicit type coercion
@grave jolt what, practically, would __bind__ do here
explicit typecasting can be defined for arbitrary source and destination types
and is therefore not a problem
thanks for opening the next can of worms ๐ @paper echo
if we want to be monadic let's not privilege Maybe
i will show you an example with lists, since they are monads
"a monad is just a monoid in the category of endofunctors, what's the problem?"
def list_map(list_, fn):
return [fn(x) for x in list_]
def list_join(list_of_lists):
return sum(list_of_lists, [])
map applies a function to each element of a container M[T], and join turns M[M[T]] into M[T], like, it flattens it
i follow
bind is flatmap, right
yes (for lists)
So map: (A -> B) -> List[A] -> List[B]
join: List[List[A]] -> List[A]
i don't really like the flatmap name because it doesn't always make sense imo, but maybe i'm just misinterpreting it
And
def bind(list_: "List[A]", fn: "A -> List[B]"):
return list_join(list_map(list_, fn))
not that bind make sense either lol
"shove"
honestly I don't see why it's called bind
to me bind is called what unit is
but I'm not a category theorist so
you know what's confusing for Python programmers
JS arrays convert to strings before sorting by default
even if it's not needed
yes, I fell for that
[10, 2, 3].sort() == [10, 2, 3]
> [23, 16, 10, 3, 1].sort()
[ 1, 10, 16, 23, 3 ]
wait. is monadic binding the same as flatmap? how is that
or are there different meanings for the term "bind"
the monadic operation with the name "flatmap", AFAIK, is also called "bind"
in haskell it's called bind for some reason, yes....
the bind makes sense when you do the parallel with the do notation
but it's still very foggy imo
Well, yes, bind/flat_map is the composition of map and join
join ~= turn two layers of container into one
So
bind([1, 2, 3], lambda x: [42]*x) == [42, 42, 42, 42, 42, 42]
right
so bind in this particular context analogous to more abstract operations w/ monads?
in a hypothetical Python Option:
class Option(Generic[T], Monad):
def __init__(self, value: Optional[T]):
self._value = value
def flat_map(f: Callable[[T], Option[T]]): Option[T]:
# could be replaced with a singleton actually
return Option(None) if self._value is None else f(self._value)
:D
def maybe_map(f, m):
match m:
case Just(x):
return Just(f(x))
case Nothing():
return Nothing()
def maybe_join(m):
match m:
case Just(m2)):
return m2
case Nothing():
return Nothing()
return Option(f(self._value)) should be just return f(self._value)
that's map, not bind
f is a -> M a
trying to imagine what it would be like in Scala and translating to Python is confusing
type hinting function types in Python is Difficult
i still dont understand how this "flatmap" bind is the same as >>=
or is it not the same thing
all 3 refer to the same function
i thought i understood haskell's >>= conceptually but maybe i dont
it's the same thing
Thst coalesce operator from 505 would have been nice
you have a monadic value, as well as a function that takes a raw value and returns a monadic value
right
Why won't they add that?
but flatmap is binding specifically for the List monad
flatmap is the operator that applies the latter function to the former (after unwrapping) for all monads
bleh thats such a stretch
@raven ridge pointers don't get implicitly casted like in C
@teal yacht good point, forgot about that.
yes
that's the primary issue with haskell and the likes
why do we use map to mean apply iteratively in the first place
like, the language would be fine if it wasn't for the 173 symbols defined in Data
fine for beginners to pick up*
@gleaming rover i much prefer that form of "mapping" because it's analogous to the math term
also I think the nature of function composition in Haskell is very nonintuitive for someone who isn't a mathematician
Idk I like it
It all makes more sense in the context of Functors and Applicatives.
Functor F[T] is something which has map : (T -> U) -> F[T] -> F[U] (fmap). The shape of the container doesn't change after you do map.
Applicative A[T] is a functor which has pure : T -> A[T] which returns a simple value wrapped in a container (x -> [x] for lists, x -> Just x for Maybe) and the <*> : A[T -> U] -> A[T] -> A[U] (frog asshole) operation. This operation applies each function in the left container to each member of the right container. It's more powerful, but the values themselves can't alter the shape of the container..
A monad M[T] is an applicative which defines the >>= : M[T] -> (T -> M[U]) -> M[U]. Here the value of the container can alter the shape of the result. For example, sqrt : float -> Maybe[float] and one_over : float -> Maybe[float] are computations that can fail. >>= allows to chain them easily (as in my Python example above ^ far away)
like how Scala does it (method chaining) is more readable for the average person
so yeah flatmap i think is a horrible term because the whole idea of "flattening" is kind of a list-specific concept
I miss composition so often in python
why do we use
mapto meanapply iterativelyin the first place
@paper echo aren't they linked
as explained above ^
I don't have a mathematical background but Wiki says "Originally, this was an abbreviation of mapping, which often refers to the action of applying a function to the elements of its domain"
ah
so yeah flatmap i think is a horrible term because the whole idea of "flattening" is kind of a list-specific concept
@paper echo I believe the idea is flattening the monad
because otherwise you would end up with a nested monad
and yes i just realized that
like Option[Option[T]]
ok fine
Just imagine a non-technical person hearing "flattening a nested monad"
I miss composition so often in python
@teal yacht I mean more the order
s/monad/container
like I get that mathematically f(g(h(x))) means h comes first but
x |> h |> g |> f 
Well, you can create your own Pipe class
f . g . h $ x ๐
plate(bake(marinate(ingredient))) seems to me to be much less readable than ingredient.marinate().bake().plate()
(I know not valid haskell)
(Pipe(x) >> h >> g >> f)
but yeah i get you, definitely agree
@grave jolt so map() in the "typical" sense is the implementation of fmap for Lists?
or, one possible implementation
I think the only possible implementation that obeys the laws
ah
i'll leave that to the theoreticians
i think i can start to see how you could apply a concept like monads to a language like python if you call it a "Context"
(I know not valid haskell)
I beg to differ
You know what I meant 
yes, I just wanted to nitpick!!!
well
i dont even want to call it a container? a context container? an environment?
...with could be reformulated in terms of python monads
I beg to differ
@grave jolt I actually have no idea what&is but I'll take your word that it works
Monads as containers e.g. Lists, Maybes
Monads as computations e.g. State, Reader, Writer, IO
Roughly
though that really looks like a few trees separating pregnant women holding young children
with a weirdly shaped chair on the left end
just so i understand: unwrapping a value from inside a monad like IO is when the i/o actually happens?
I mean technically State can be interpreted as a container because it parametrizes on a result a but it's more of a computation because of the state
Maybe they're both ยฏ\_(ใ)_/ยฏ
If you're interested, I have an entire implementation of the IO monad in python, together with an adapter to Postgres (I used aiopg instead of asyncpg for some reason, but ig it's easy to swap).
btw this is why nobody except the most dedicated learns haskell https://wiki.haskell.org/State_Monad
Emphasis is placed on intuition
(200 lines of impenetrable code)
i think you shared some earlier version of that
im just trying to wrap my head around how something like this would look in python
or maybe here
async/await is another example of monads.
async def f(a):
x = await g(a)
y = await h(x)
z = await j(y)
return m(z)
def f(a):
return g(a) >= (lambda x: h(x) >= (lambda y: j(y) >= (lambda z: m(z))))
if a : A and x : X, then g : A -> Awaitable[X]
yes I've read that
It's a simple string parsing algorithm.
simple indeed
and I don't know...the syntax of Haskell is just so weird to me
Whenever I read "simple" on haskell wiki, I read it in rAnDOM cASe to add a little bit of sarcasm to it
like types are just easier for me in Scala
still better than Python annotations