Python Developer learns Rust (and remaking my chess engine)

แชร์
ฝัง
  • เผยแพร่เมื่อ 5 พ.ย. 2024

ความคิดเห็น • 129

  • @TheSandwichCoder
    @TheSandwichCoder  วันที่ผ่านมา +31

    WHAT I DIDNT EXPECT THIS TO BLOW UP SO FAST.
    But as many have pointed out, no matter how confident I sound, I’m still a noob at c++ and rust. So pls take everything shown with a massive grain of salt. And pls go easy on the criticism 😢

    • @CrypticConsole
      @CrypticConsole วันที่ผ่านมา

      noob

    • @zahash1045
      @zahash1045 วันที่ผ่านมา

      @@TheSandwichCoder then get good first before spreading misinformation

    • @zahash1045
      @zahash1045 วันที่ผ่านมา

      @@TheSandwichCoder at least have the decency to run the code and check if it does what you expect it to do.

    • @Navieddamooc
      @Navieddamooc วันที่ผ่านมา

      Damn chill

    • @nikitawew6087
      @nikitawew6087 วันที่ผ่านมา +1

      yea, lost me at words python + rust as c++ dev. anyway, great video, there is always a lot to be lerned.

  • @Tantandev
    @Tantandev วันที่ผ่านมา +36

    Much of this reminds me of my experience learning rust.
    It was painful at times battling the borrow checker.
    But it has "unintentionally" taught me valuable lessons sometimes, how sometimes multiple mutable references can shoot you in the foot,
    or forcing me to take a deeper thought to what data types I'm working with.
    Sometimes though because of the borrow rules it's easy to take short cuts like cloning stuff willy nilly or unwrapping everything.
    But over time your intuition will develop to know immediately what will work well in a rust way.
    Welcome to the tribe :P
    Some things I love about the language:
    Enums (Every time I use another language I miss the way Rust Enums work), enforced naming convention(clean api's and for collaboration), excellent compiler error messages, Clippy (tool for giving you tips on improvements on your code)

    • @peacefuldeityspath
      @peacefuldeityspath 23 ชั่วโมงที่ผ่านมา +3

      TanTan! ;) can't wait for the next video to drop my friend.
      whatever you're doing keep it up psst yes im subbed to you!

    • @TheSandwichCoder
      @TheSandwichCoder  23 ชั่วโมงที่ผ่านมา +6

      WTF MOM GET THE CAMERA 📷

  • @weston3597
    @weston3597 วันที่ผ่านมา +57

    this shit is hella well made for 69 subs

    • @aasimamin5710
      @aasimamin5710 วันที่ผ่านมา +2

      I thought he had a lot more, video is good quality

    • @cirkulx
      @cirkulx 16 ชั่วโมงที่ผ่านมา

      nice

  • @Anonymous-e7t3w
    @Anonymous-e7t3w วันที่ผ่านมา +24

    4:40 i32 is a 32 bit integer that can be negative. u32 is a 32 bit integer that can't be negative, so unsigned integers are appropriate types for indexing. And usize is basically just a 32 or 64 bit unsigned integer, depending on whether or not your PC is 32 or 64 bit.

    • @Anonymous-e7t3w
      @Anonymous-e7t3w วันที่ผ่านมา +2

      PS good video. It reminds me when I was younger and in a very similar stage, except Rust wasn't a thing at the time 😅. I went from Python - > C++ - > Rust as well. Something I will say is Rust basically forces you to learn concepts that C++ doesn't, but you can guarantee you'll shoot yourself in the foot if you don't understand them in C++. And good luck on your career 🙂

  • @diamondapple1648
    @diamondapple1648 วันที่ผ่านมา +8

    9:34 you don't actually need mutable references, as you don't change elements but only read them, so shared references will do. However you can even get two mutable references to elements in one vector using split_at_mut method

  • @oglothenerd
    @oglothenerd 20 ชั่วโมงที่ผ่านมา +4

    A "usize" is an unsigned integer with the size of the platform. Example: "usize" on a 64-bit CPU is an unsigned 64-bit integer. There is also "isize" which is the same but signed.
    Other non-dynamic number types in Rust are:
    u8
    i8
    u16
    i16
    u32
    i32
    u64
    i64
    u128
    i128
    f32
    f64
    They are pretty self-explanatory, examples:
    u8 - Unsigned 8-bit integer. (AKA a byte.)
    f64 - 64-bit floating point number.
    i32 - Signed 32-bit integer. (Signed just means that it can also store negative numbers by giving up some of the larger unsigned numbers that it could store if it was unsigned.)

  • @Hellbending
    @Hellbending 10 ชั่วโมงที่ผ่านมา +1

    And that’s how summer works as a guy! 😂
    Memes aside - welcome to oxidation, and a phenomenal video btw

  • @arjix8738
    @arjix8738 21 ชั่วโมงที่ผ่านมา +3

    6:43 bro complains about having to read documentation, what a world we live in

    • @verified_tinker1818
      @verified_tinker1818 6 ชั่วโมงที่ผ่านมา

      That's what I was thinking, too. ChatGPT is great for specific, hard-to-Google questions, but you should use it only as a way to orient yourself in the right direction, not try to have it do the work for you.

  • @oglothenerd
    @oglothenerd 20 ชั่วโมงที่ผ่านมา +2

    The borrow checker is actually quite simple. If you put something into a function call by value, it deallocates the variable after use. If you pass by reference, you can reuse the variable. And if you have something reading/writing to a variable, you cannot read/write to it somewhere else.

  • @pvaqueiroz
    @pvaqueiroz 3 ชั่วโมงที่ผ่านมา

    Awesome video. Peak cinema. You'll have one billion subs in no time

  • @jaysistar2711
    @jaysistar2711 18 ชั่วโมงที่ผ่านมา

    4:04 &str is a slice (a.k.a. fat pointer), which can point to any UTF8 string in memory, and it doesn't own the string to which it points. A String is an owned string. You can borrow it as a 4:08 &str to pass to functions, but you can also append to it, which may cause reallocation (like C++'s std::string).

  • @noxmore
    @noxmore 8 ชั่วโมงที่ผ่านมา

    1:16 jdh enjoyer spotted
    Also great video, as a Rust and Bevy evangelical i approve

  • @cg4631-vv9gq
    @cg4631-vv9gq วันที่ผ่านมา +9

    something to note on your explanation at 3:32 - vectors and other containers are not automatically referenced when passed in cpp. this might also be a source of issues in your chess code. function parameters are ALWAYS passed by value (calling the copy constructor) and only referenced when you declare the type as a reference (const std::vector& myints). secondly i dont know what syntax you used for the cpp hashmap and linkedlist example at around the same time stamp - but those dont exist. not under those names anyway. a std::unordered_map is a hashmap-like container which also doesn't have the initialization syntax shown there.
    good work though i understand the beginners trouble with cpp - nice end montage lol

    • @TheSandwichCoder
      @TheSandwichCoder  วันที่ผ่านมา

      Ohhh I see. Yeah for the hashmap and linked list I was too lazy to find the actual syntax so I just put some BS there. There was supposed to be a comment at the start that said I was too lazy but I guess it got dropped out 🤷. Thx for the advice though!

    • @cg4631-vv9gq
      @cg4631-vv9gq 23 ชั่วโมงที่ผ่านมา

      np man keep up the good work

  • @WoolyCow
    @WoolyCow วันที่ผ่านมา +3

    great vid! dropped a sub! i suck at programming but that python ball collision checker code physically hurt me to look at :>
    very relatable and im sure youll go far! that chess montage was very fun

  • @-syn9
    @-syn9 2 วันที่ผ่านมา +4

    I also learned rust from a chess engine project, it's quite well suited for it

    • @TheSandwichCoder
      @TheSandwichCoder  วันที่ผ่านมา +3

      Yeah it helps a lot to learn the logic and basic functions 😎😎

  • @jaysistar2711
    @jaysistar2711 17 ชั่วโมงที่ผ่านมา

    4:43 A usize is an unsigned integer that is the same size as a CPU register, and is used for offsets and lengths.

  • @DeoTheFactsGuy
    @DeoTheFactsGuy 23 ชั่วโมงที่ผ่านมา +1

    Very well made video, Nice 👍👍

  • @Lusd-p4v
    @Lusd-p4v 21 ชั่วโมงที่ผ่านมา

    Nice video! When implementing a spatial hash in bevy you should store the Entity instead of a components reference, this enables you to get back the entities components inside your system using the spatial hash Resource.

  • @thomasturner1065
    @thomasturner1065 6 ชั่วโมงที่ผ่านมา

    In Python you can specify the variable type almost the exact same way as in Rust:
    a_number: int = 5
    Not that it does much of anything aside from helping with documentation.

  • @zahash1045
    @zahash1045 วันที่ผ่านมา +1

    3:25 that doesn’t edit the outer vector because you are passing by value. You are just editing the local copy.
    You have to pass a mutable reference to do that.
    vector& n

  • @loganrowe1727
    @loganrowe1727 วันที่ผ่านมา +2

    75 subs? Let me fix that.
    Keep up the good work

  • @zeep-yt
    @zeep-yt วันที่ผ่านมา +2

    this is so cool
    i wish i could edit like that xd

  • @xkxjvvjvk
    @xkxjvvjvk 22 ชั่วโมงที่ผ่านมา

    youre the sigma sandwichcoder thank you for the good content

  • @webkinskid
    @webkinskid 15 ชั่วโมงที่ผ่านมา

    I also did the python-to-rust switch for game development, it's been about 2 months and I love it, the typing is so much more explicit, I no longer lay awake at night fearing my integer is going to get turned into a float without my consent
    I suggest you try using bevy's event systems ASAP, they really change how you can make your systems interact, and they're a good way to handle mutating your components without conflict, I did mine like this: put player input event writers in pre-update, put all event readers in update, put game logic event writers in post-update, there's a ton of benefits to doing things this way that I won't get into in this comment, but it prevents systems mutating the same variable at the same time causing crashes, and guarantees that when systems are reading data, the data will not change during the frame, the data is essentially "still" while systems read it and decide how they want to change it
    my first components I wrote in bevy were Velocity, Acceleration, and Spin, it was a great study on how to work within the ECS

  • @empathy_monster
    @empathy_monster 23 ชั่วโมงที่ผ่านมา

    Cool video! I really encourage people to spend some time in a functional language, maybe Scala, if they come from an OOP background before diving into Rust. Everything will make sense and you'll pick it up much faster.

  • @tryoxiss
    @tryoxiss 21 ชั่วโมงที่ผ่านมา

    String is a data object internally represented as a Vec and is far more versatile.
    &str is a pointer to a string literal. They are much less flexible but faster.
    &String and str are almost never used.
    usize is an unsigned number the size of the systems pointer length.

    • @arjix8738
      @arjix8738 20 ชั่วโมงที่ผ่านมา

      to add ontop of that, string literals are &str and not String because Rust removes duplicate string literals, so you get a shared immutable reference
      this is an optimization done at compile time

  • @alarie0
    @alarie0 วันที่ผ่านมา +1

    4:50 if you have a variable named "index" it should almost always be a usize by default, e.g. `let index: usize = 0;` or `let index = 0usize;`
    usize is just the largest integer the local system can handle... it prevents a 32 bit system from trying to store a 64 bit integer

  • @_ethqnol_
    @_ethqnol_ วันที่ผ่านมา +3

    2:44 BASED opinion. everybody hates on Rust syntax for some reason, but its so beautiful (or maybe I've been indoctrinated by the new testament, aka the rust programming language 2nd edition, and I am now too far gone. or maybe rust is just better ¯\(ツ)/¯ )

    • @TheSandwichCoder
      @TheSandwichCoder  วันที่ผ่านมา

      @@_ethqnol_ I have converted to be a rustacean

    • @arjix8738
      @arjix8738 21 ชั่วโมงที่ผ่านมา

      I think most people "hate" it because it looks like typescript and other languages that have the type on the right

    • @_ethqnol_
      @_ethqnol_ 19 ชั่วโมงที่ผ่านมา

      @@arjix8738 maybe... Tbh, i like the syntax where the type is on the right after the colon. it looks cleaner. I've also heard complaints about forming a string, where people complain that you have to use "String::from()" or "String::new()", but obviously they don't understand the beauty of Rust strings

  • @HumanityAsCode
    @HumanityAsCode 2 ชั่วโมงที่ผ่านมา

    10:40 You might try saving detected collisions to a list of collision events containing data about which balls to update and how to update them. Then you update one ball at a time using that data instead of copying the whole ball list.

  • @bilalazhar4495
    @bilalazhar4495 2 ชั่วโมงที่ผ่านมา

    this video is extemely well made i susbroobed

  • @divine203
    @divine203 วันที่ผ่านมา +9

    1:26 Damn, I'm honored lol

    • @TheSandwichCoder
      @TheSandwichCoder  วันที่ผ่านมา +1

      Yeah just ignore the one below it 😂

    • @justinliu7788
      @justinliu7788 22 ชั่วโมงที่ผ่านมา

      @@TheSandwichCoderthick of it 😱

  • @hamstercap
    @hamstercap 2 วันที่ผ่านมา

    really cool video man, keep it up

  • @antoniong4380
    @antoniong4380 19 ชั่วโมงที่ผ่านมา

    &str vs String in a nutshell:
    &str is a 'String' which you know how long it is, but don't know if you can write past the last byte of the &str.
    A String is also a 'String' which you know how long it is, but also have an extra field which we call capacity which lets you know how much more can you write to it

  • @poleve5409
    @poleve5409 วันที่ผ่านมา +1

    peak cinema

  • @MiScusi69
    @MiScusi69 2 ชั่วโมงที่ผ่านมา

    You're great!

  • @feenusek
    @feenusek 5 ชั่วโมงที่ผ่านมา

    Honestly, amazing. Do you have a Discord server?

  • @seanp5524
    @seanp5524 21 ชั่วโมงที่ผ่านมา

    10:30 Instead of copying the list of balls every time you want to check collisions, Why not use immutable references in your for loops and push the collision updates to a stack? Then after you've looped through each ball, you have a vector of the collision updates that need to be performed and can do all of them without needing 2 mutable references or having only half the balls have collision.

  • @kerolisesa8191
    @kerolisesa8191 14 ชั่วโมงที่ผ่านมา

    4 nested for loops is crazy

  • @DerSolinski
    @DerSolinski 22 ชั่วโมงที่ผ่านมา

    I'm actually amazed you got this far...
    Bevy uses high level Rust concepts, that can do amazing stuff when utilized correctly.
    But hell I'm tinkering with Rust now almost two years and I still do not feel comfortable enough to play around with bevy beyond its examples.
    Learning Rust is already hard mode, learning Rust with Bevy earns you respect from the Doom Slayer...

  • @yassinsoftware
    @yassinsoftware 23 ชั่วโมงที่ผ่านมา +1

    14:50 rust is actually llvm-based so....

  • @jvcmarc
    @jvcmarc วันที่ผ่านมา

    also, did you compile it in release mode? you get much better performance in release mode vs debug mode

  • @v0idbyt3
    @v0idbyt3 17 ชั่วโมงที่ผ่านมา

    this video earned my approval
    btw im stupid yippee

  • @AimForDaHead-16s
    @AimForDaHead-16s วันที่ผ่านมา

    1:26 "Goofy dies in a car crash while listening to sunflower " 💀💀💀💀

  • @alexanderleschanz9991
    @alexanderleschanz9991 20 ชั่วโมงที่ผ่านมา

    awesome video, the music and sound effects are just WAY too loud

  • @niklaswojtkowiak3
    @niklaswojtkowiak3 วันที่ผ่านมา

    this burns my eyes

  • @IdeleIdi-uz7ev
    @IdeleIdi-uz7ev วันที่ผ่านมา

    Nice video man. Thumbnail would've been way better using a white background and red and black text

  • @sakurako-omuroo
    @sakurako-omuroo วันที่ผ่านมา

    nice vid keep it up

  • @tordjarv3802
    @tordjarv3802 วันที่ผ่านมา +10

    A minor correction, there is no such a thing as a reference in Rust. At least not in the way you think of it from other languages. When you pass a parameter to a function you either let it borrow the value (meaning you want to keep control over it after the function call) or you give the function ownership of the value. Borrowing is not equivalent with pass by reference and give ownership is not equivalent with pass by value. Realizing this and accepting it is the key to truly unlocking the awesomeness of Rust.

    • @TheSandwichCoder
      @TheSandwichCoder  วันที่ผ่านมา +2

      Ohhh yeah I heard those terms before but I didn’t really get what they meant. Thx though!

  • @jaysistar2711
    @jaysistar2711 17 ชั่วโมงที่ผ่านมา

    6:12 There are faster linkers, like gold, and you can setup Bevy to be made a DLL while developing.

  • @eduardabramovich1216
    @eduardabramovich1216 23 ชั่วโมงที่ผ่านมา

    Time to try Nim if you want something Python-ish or Odin if you want something C-ish.

  • @arjix8738
    @arjix8738 21 ชั่วโมงที่ผ่านมา

    I believe you could use an Arc to view the balls instead of making a snapshot

  • @Masq_RRade
    @Masq_RRade 15 ชั่วโมงที่ผ่านมา

    3:20 this is completely wrong. Variables in C++ are always passed by value unless the parameter’s type is a reference

  • @soeinflooo7978
    @soeinflooo7978 วันที่ผ่านมา

    Helo Mr. im new here. good video. 👍

  • @Takatou__Yogiri
    @Takatou__Yogiri 22 ชั่วโมงที่ผ่านมา

    I love how challenging it is. I feel like an idiot every time I use Rust, but I keep going because of my ego. Lmao

  • @DuniC0
    @DuniC0 22 ชั่วโมงที่ผ่านมา

    Too late for Rust man! Imagine Python but fast... They even call it Mojo!

    • @arjix8738
      @arjix8738 21 ชั่วโมงที่ผ่านมา

      just use pypy at that point

  • @cyanmagar4986
    @cyanmagar4986 วันที่ผ่านมา

    00:33
    Wait whatttt's in your browser thooo😂😂

  • @coffee-is-power
    @coffee-is-power วันที่ผ่านมา

    7:55 that pub let mut is not valid rust, global variables are declared with static
    pub static mut SCORE: i32 = 0;
    you can add `mut` to make it mutable, however accessing it is unsafe because if you access it from different threads you'll end up with undefined behavior (possibly data races and memory corruption). You can use a AtomicI32 instead, which uses internal mutability which means the static variable itself is not mutable but the value inside the AtomicI32 is and it is safe to access on multiple threads at the same time because the CPU synchronizes the access to that memory location between all CPU cores.
    pub static SCORE: AtomicI32 = AtomicI32::new(0);

    • @TheSandwichCoder
      @TheSandwichCoder  วันที่ผ่านมา

      @@coffee-is-power yeah I noticed this right after I did the snippet… didn’t think anyone would notice the error though. Statics and constants in rust are a pain…

  • @jadxvx
    @jadxvx วันที่ผ่านมา

    YOU ONLY HAVE 189 SUBS?

  • @Takatou__Yogiri
    @Takatou__Yogiri 22 ชั่วโมงที่ผ่านมา

    I love low chatgpt is insulting you. i'm glad he doesn't insult me. i use him 24/7 to write html and css.

  • @sakul_the_one4821
    @sakul_the_one4821 วันที่ผ่านมา

    hmm, I think I stick with C++ and risk the stability of the universe, because why not ¯\_(ツ)_/¯

  • @Takatou__Yogiri
    @Takatou__Yogiri 21 ชั่วโมงที่ผ่านมา

    13:59 after seeing those comments why do i feel like it was written by chatGpt 🤔🤔🤔🤔

  • @ivanjansevanrensburg5377
    @ivanjansevanrensburg5377 18 ชั่วโมงที่ผ่านมา

    Your explanation about C++ references doesn't seem right to me. C++ Vectors aren't implicitly copied by reference and there is also a difference between a const and a mutable reference.
    References in C++ is just a convenient way to pass around a pointer that is known to be initialised, so technically you can also pass a reference using a pointer where you can pass a pointer to a constant. I have included some examples below for you:
    // Pass by value.
    void foo(std::vector vec) {
    //...
    }
    // Pass by mutable reference.
    void foo(std::vector& vec) {
    // ...
    }
    // Pass by mutable reference using pointer.
    void foo(std::vector* vec) {
    // ...
    }
    // Pass by const reference.
    void foo(const std::vector& vec) {
    // ...
    }
    // Pass by const reference using pointer.
    void foo(const std::vector* vec) {
    // ...
    }
    Passing by reference using pointers can also be confusing but a great explanation is from a Stackoverflow post describing:
    """
    const char* is a pointer to a constant char
    char const* is a pointer to a constant char
    char* const is a constant pointer to a (mutable) char
    """
    (source: stackoverflow.com/questions/162480/const-int-vs-int-const-as-function-parameters-in-c-and-c)

  • @ZenithoraMusic
    @ZenithoraMusic วันที่ผ่านมา

    What is Hello Wolrd

  • @juliansantos1900
    @juliansantos1900 18 ชั่วโมงที่ผ่านมา

    the wordle code is bruh ._.

  • @bilalazhar4495
    @bilalazhar4495 3 ชั่วโมงที่ผ่านมา

    skill issue is not python or rust , skill issue is gaming operating system with browser based notepad++ clone

  • @arjix8738
    @arjix8738 21 ชั่วโมงที่ผ่านมา

    bro uses onedrive

  • @catto-from-heaven
    @catto-from-heaven 16 ชั่วโมงที่ผ่านมา

    Bro really said
    if n == 0:
    return 0
    if n == 1:
    return 1
    instead of
    if n < 2:
    return n

  • @Qohist
    @Qohist วันที่ผ่านมา

    You meant explicit not readable

  • @niveus69420
    @niveus69420 4 ชั่วโมงที่ผ่านมา

    So you're asian? Name every asian person

  • @Wraient
    @Wraient 21 ชั่วโมงที่ผ่านมา

    281 subs? wtf?

  • @__Merchant
    @__Merchant 22 ชั่วโมงที่ผ่านมา

    I mean you could've cached the python script at the start of the video...problem solved...

  • @feliche-demiannetliukh3703
    @feliche-demiannetliukh3703 7 ชั่วโมงที่ผ่านมา

    You know that coding in rust on windows is illegal, right?

  • @johanavril1691
    @johanavril1691 22 ชั่วโมงที่ผ่านมา

    now learn zig

  • @MutasimosDoesProgramming
    @MutasimosDoesProgramming วันที่ผ่านมา

    vscode and windows nah you need neovim and linux

    • @coffee-is-power
      @coffee-is-power วันที่ผ่านมา

      vscode is fine, windows though is 💀

    • @TheSandwichCoder
      @TheSandwichCoder  วันที่ผ่านมา

      The day I switch to neovim is the day I get a gf 😂 (so never)

    • @epixerty
      @epixerty วันที่ผ่านมา

      i dont really get the point of neovim, i only use it to quickly edit text files from the terminal, but configuring it seems like a hassle

    • @solmateusbraga
      @solmateusbraga 23 ชั่วโมงที่ผ่านมา

      kakoune >>>>>>>

  • @luigidabro
    @luigidabro วันที่ผ่านมา +3

    Please, don't fake your knowledge of c++. Pretty much any c++ snipped in the video is incorrect.
    Vectors, like any other type, get copied when passed as value
    Your second code snipped after the vector snipped was just a python reskin that doesn't have anything to do with c++
    Your expression with .copy could be inlined, you don't even need to copy it when passing it as value since it is copied there, unless you've not propperly implemented the constructor.
    Btw at 5:45
    println! already flushes, only print! doesn't.

    • @TheSandwichCoder
      @TheSandwichCoder  วันที่ผ่านมา

      Ok gotchu. Yeah I’m still learning the inner workings of C++ and rust so I’m still kinda blur on it. I’ll make sure to fact check next time though, I didn’t expect this to get that many views lol

  • @zizu789
    @zizu789 10 ชั่วโมงที่ผ่านมา

    can't wait for this language to die soon so everyone can shut up about it and return to normal languages like c and c++

  • @FredyyDev
    @FredyyDev วันที่ผ่านมา

    I'm jealous

  • @not_eagleye
    @not_eagleye วันที่ผ่านมา

    x d

  • @cheesepop7175
    @cheesepop7175 19 ชั่วโมงที่ผ่านมา

    1:55 is he actually using command line? dude, it's not the 80s, people use GUIs now.

    • @aarorissanen930
      @aarorissanen930 15 ชั่วโมงที่ผ่านมา

      This better be a joke

    • @cheesepop7175
      @cheesepop7175 14 ชั่วโมงที่ผ่านมา

      @@aarorissanen930 I mean it's really primitive

    • @aarorissanen930
      @aarorissanen930 ชั่วโมงที่ผ่านมา

      @@cheesepop7175 You must be a beginner in compsci to think that. The terminal is the MOST powerful tool for a person working with a computer, no doubt about it. Not everything needs to be a GUI designed for babies.

  • @iaminfinityiq7182
    @iaminfinityiq7182 วันที่ผ่านมา

    3:56 bro tryna do recursive with this one 🫡🫡🫡