Go Iterators Are Bad

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

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

  • @BosonCollider
    @BosonCollider 6 หลายเดือนก่อน +48

    The thing is that Go iterators are primarily there to get people to not use channels for iteration in cases where you just needed an iterator abstraction. So yield just works exactly like "func that pushes into channel" but an order of magnitude faster (yield just calls the loop body instead of going via the goroutine scheduler) and you can refer to shared variables without race conditions.
    If you want a pull based iterator you call iter.Pull on the rangeable func and much like the Go keyword it will create a thread-safe coroutine like in Lua. The approach that Odins creator mentioned here works only for iterating over data structures, but not for usecases like iterating over a database cursor with automatic cleanup at the end, or something nontrivial that actually behaves like a separate process, much like Python generators. The pro and the con of go iterators is that they are goroutines without the overhead of synchronizing across threads.
    Also, the func type signatures will be cleaned up into an alias (1.23 allows parameters in aliases) so that the first line would be
    func Backward[T Any](s []T) Seq[T] {
    ...
    }

    • @defenestrated23
      @defenestrated23 6 หลายเดือนก่อน +14

      Ding ding ding. This is the correct answer. The Odin-style iterator works fine for finite data structures (where an "i" makes sense), works less well for a continuous stream (like gRPC streams), poorly for lazy streams/paginators/cursors, and falls on its face where you want to interact with the inner state in any way.
      In python it's the difference between Collection (has len, iter, and next methods), Iterable (has iter and next, but no len), Iterator (has next), and Generator (has next and yield from). The merged proposal can do all of those, the struct iterator can't do it without significant complexity.
      I find the syntax a bit weird but it's tolerable once you spend some time to wrap your head around it.

    • @MartinodF
      @MartinodF 6 หลายเดือนก่อน +1

      Thank you for eloquently putting my exact thoughts into words!

  • @joecairns21
    @joecairns21 6 หลายเดือนก่อน +242

    That syntax looks like a nightmare.

    • @mundanesquirrel8687
      @mundanesquirrel8687 6 หลายเดือนก่อน +22

      it does. hopefully it'll be hidden away and most of us will mostly consume these, rather than create them.

    • @sillymesilly
      @sillymesilly 6 หลายเดือนก่อน +12

      And they have the delusion it will replace C.

    • @HypothesisI
      @HypothesisI 6 หลายเดือนก่อน +6

      A nightmare to implement - not to use. That's basically the only way its justifiable. IMO.

    • @HypothesisI
      @HypothesisI 6 หลายเดือนก่อน +7

      @@sillymesilly Who? And What? Rust?

    • @linminsu3443
      @linminsu3443 6 หลายเดือนก่อน +26

      @@HypothesisIno one said it would replace C. it having a GC to begin with already tells you this lol

  • @jimiscott
    @jimiscott 6 หลายเดือนก่อน +161

    "When the language you're stann'ng for is still having discussion over iterators." shock.

  • @muno
    @muno 6 หลายเดือนก่อน +133

    Normally I feel bad about listening to video essays in the background because I feel like I'm missing out on important context. Videos like these alleviate that for me because even if I do watch it I don't understand any of the code onscreen

    • @nyx211
      @nyx211 6 หลายเดือนก่อน +19

      It's okay not to look at it even if you do understand it. Golang code looks ugly AF.

    • @Kane0123
      @Kane0123 6 หลายเดือนก่อน +24

      @@nyx211I agree. I only look at sexy code.

    • @TOZA
      @TOZA 6 หลายเดือนก่อน

      ​@@nyx211 nah, golang have one of best looking code I have seen.

    • @ts-wo6pp
      @ts-wo6pp 6 หลายเดือนก่อน +7

      ​​@MantasXVIIIyou seem weird. Can you try to be more normal?

    • @tongpoo8985
      @tongpoo8985 6 หลายเดือนก่อน +1

      @@ts-wo6pp can you try to be less boring? "EHRRM AWKWARD AMIRIGHT GUYS"

  • @davidkoffi985
    @davidkoffi985 6 หลายเดือนก่อน +67

    I thought go was supposed to be simply? That syntax was so confusing?

    • @enkiimuto1041
      @enkiimuto1041 6 หลายเดือนก่อน +4

      I had to pause the video and think about that as soon as I saw it.

    • @7th_CAV_Trooper
      @7th_CAV_Trooper 6 หลายเดือนก่อน +11

      Skill floor VS skill ceiling.

    • @iatheman
      @iatheman 4 หลายเดือนก่อน +3

      @@7th_CAV_Trooper With go the height wasn't very high and the house was build at sea level. Now its still at sea level but the ceiling is higher.

  • @genuismensa
    @genuismensa 6 หลายเดือนก่อน +22

    All of the new changes are all for Kubernetes. Every knew K8S version depends on it to the point that they had to delay the deploy of I think it was 1.24 or 1.26 because Go dropped a new version the week before they were going to launch. I listen to the Kubernetes pod cast by Google.

    • @lucascottle2345
      @lucascottle2345 4 หลายเดือนก่อน +1

      Mind sharing what episode they disscuss this? im interested :)

  • @KevinLyda
    @KevinLyda 6 หลายเดือนก่อน +46

    A go iterator method built off of interfaces and return types would have been clearer.
    So something like this:
    for i, v := iterate (int, string) foo{}
    Where foo meets the interface
    interface{
    Init()
    Next() (int, string)
    }
    Or something like that.

    • @Tvde1
      @Tvde1 6 หลายเดือนก่อน

      interface IEnumerable
      {
      T Current;
      bool MoveNext();
      }
      very simple

    • @krumbergify
      @krumbergify 6 หลายเดือนก่อน +3

      You also need a way to cleanup resources stored in the iterator.

    • @KevinLyda
      @KevinLyda 6 หลายเดือนก่อน

      @@krumbergify is there some difficulty with adding a third function to the interface?

    • @krumbergify
      @krumbergify 6 หลายเดือนก่อน +2

      @@KevinLyda No. It’s just that Go in many ways avoids the need to write state machines through its light weight goroutines.
      A worker that reads from a channel, computes a new value and writes it to another channel can be written using a single function without the need for custom structs.
      This iterator design simulates how you would write it using channels although it doesn’t involve concurrency.

    • @michaelthornes
      @michaelthornes 6 หลายเดือนก่อน +2

      @@krumbergify nitpick: it involves concurrency (interleaving code counts), but doesn't involve parallelism (goroutines/threads)
      > Concurrency is when two or more tasks can start, run, and complete in overlapping time periods. It doesn't necessarily mean they'll ever both be running at the same instant. For example, multitasking on a single-core machine.

  • @nesssel
    @nesssel 6 หลายเดือนก่อน +18

    For anyone still confused, here's an actual explanation of what's going on and where the yield function comes from.
    Go takes your for loop's body and desugars it to a function that takes the loop variables as arguments and processes them. This is what Prime meant how it's similar to a forEach in Javascript.
    If your loop body terminates it returns true so the outer function re-excecutes yield, however a break in the loop body desugars to 'return false' in the function. Similarly continue desugars to an early return of true in the function.
    All that said I strongly feel this should've just been a Ranger interface where these mapping are less obtuse, but range is inherently magical so maybe that's why they didn't care so much.

    • @lazymass
      @lazymass 6 หลายเดือนก่อน +2

      Damn... I really don't like it...

  • @von_nobody
    @von_nobody 6 หลายเดือนก่อน +14

    Article author do not understand completely C++ iterators, they do not have `iterator_next()` as they need work for subranges too. This mean you can find two iterators in any range and use them in any place where you could use whole range iterators.
    Another benefits is all algorithms that correctly work with iterators will work with pointers that make range too.

    • @Satook
      @Satook 6 หลายเดือนก่อน +4

      I reckon Bill probably does understand C++ iterators.
      Having watched and read a few of his blogs and interviews, he’s predisposed towards simplicity and straightforward semantics. So copying C++ anything is likely a non-starter.

    • @egg-mv7ef
      @egg-mv7ef 5 หลายเดือนก่อน

      c++ iterators are so gooood

  • @yapet
    @yapet 6 หลายเดือนก่อน +5

    This makes me appreciate Lua iterators a lot more.
    Given some similarities between Go and Lua, I think Go would’ve been well-served by the Lua style iterators.
    Although there are things that are dealbreakers as in eyes of Russ: state is not stored in control flow, defer doesn’t really work for cleanup, Lua doesn’t cleanup after iteration ends (which might be fixed by the gingerbill’s onBreak boolean flag)

  • @hanifarroisimukhlis5989
    @hanifarroisimukhlis5989 6 หลายเดือนก่อน +18

    That design of iterator also makes it _trivially_ easy to disregard break and possibly leaks the inner closure too. With iterator being struct there's no way for the iterator to know the flow of inner loop at all.

    • @metaltyphoon
      @metaltyphoon 6 หลายเดือนก่อน +2

      Non sense. In C# you can create iterations that are aware of the loop and is massively simpler. Just introduce a `yield` keyword

    • @Aidiakapi
      @Aidiakapi 6 หลายเดือนก่อน

      ​@@metaltyphoonC#'s iterators follow an almost identical structure to Rust and Odin, not like Go.
      The yield keyword is just syntactic sugar over top of it which generates the closure and state machine. You can do the same thing in Rust by using generators.

    • @metaltyphoon
      @metaltyphoon 6 หลายเดือนก่อน

      @@Aidiakapi yes I’m aware of that. I was replying to the OP that C# iterators CAN know about the flow of the inner loop like Go can.

    • @hanifarroisimukhlis5989
      @hanifarroisimukhlis5989 6 หลายเดือนก่อน

      @@metaltyphoon I mean, it's more of generators and *not* iterators right? It's not just passing values, but actually influence the inner loop, possibly calling it from *outside* the loop or even other goroutine (which is another huge can of worms).

  • @josefjelinek
    @josefjelinek 6 หลายเดือนก่อน +15

    This happens in every language which gets wider adoption. Authors somehow lose track what got people attracted in the first place. They suddenly try to accommodate people, which were just force to use the language and do not like it at all.
    This will be used to actually get teams off of Go instead of onboard as the "haters" will just point to this and argue that if you cannot understand it right away, Go is not really as simple as advertised and "we should go with Rust".

    • @hamm8934
      @hamm8934 6 หลายเดือนก่อน +6

      How did this get through but arena allocation didnt

    • @josefjelinek
      @josefjelinek 6 หลายเดือนก่อน +4

      @@hamm8934 a really good question. I know people (who do not hate programming in Go) were waiting for arenas with excitement as it was able to address very real and specific class of performance problems. I know zero people, which were like "I like how Go was doing things so far, but I really want some high-order-functional construct directly in the language, which I will need to relearn every time I want to implement that."

  • @johanneskohnen8747
    @johanneskohnen8747 6 หลายเดือนก่อน +15

    N.b.: „nota bene“ it’s a „Note:“ but with sprinkles

  • @AK-vx4dy
    @AK-vx4dy 6 หลายเดือนก่อน +5

    I saw once very through presentation on some C++ conference when guy analysed through all kinds of iterators in many languages with pros and cons, very interesting

    • @IQof2
      @IQof2 6 หลายเดือนก่อน +1

      Link?

  • @genuismensa
    @genuismensa 6 หลายเดือนก่อน +3

    Return sends a specified value back to its caller whereas Yield can produce a sequence of values. We should use yield when we want to iterate over a sequence, but don’t want to store the entire sequence in memory. Yield is used in Python generators. A generator function is defined just like a normal function, but whenever it needs to generate a value, it does so with the yield keyword rather than return. If the body of a def contains yield, the function automatically becomes a generator function.

    • @sophiophile
      @sophiophile 6 หลายเดือนก่อน +2

      Also, the main difference from a *practical/performance standpoint* for Python is that when your iterable uses a generator function to instantiate instead of an iterator object, instead of being compiled by loading the entire instance into memory, __next__() calls the function, so it only needs to keep a single value in memory at time.

  • @JoeTaber
    @JoeTaber 6 หลายเดือนก่อน +19

    OH the reason why it's not an interface is because Go doesn't support generic interfaces, and may never.

    • @metaltyphoon
      @metaltyphoon 6 หลายเดือนก่อน +5

      Exactly. Go can’t do genetics methods. Prime has been using Go for a wihile now and can’t seem to have this conclusion

    • @alexlowe2054
      @alexlowe2054 6 หลายเดือนก่อน +7

      It's actually sad how many problems are created by the lack of support for genuine generics. Yes, it's slow to compile, but there's a reason most high level strongly typed programming languages support generics. They're super useful for lots of things, and certain problems can't be easily solved without generics. I'm not sure if it's funny or sad how much Go refused to support proper generics.

    • @WoolieOG
      @WoolieOG 6 หลายเดือนก่อน +1

      wrong, it does support generic interfaces

    • @JoeTaber
      @JoeTaber 6 หลายเดือนก่อน

      @@WoolieOG Incorrect. Go does not support generic methods on interfaces, which would be required to implement iterators.

    • @JoeTaber
      @JoeTaber 6 หลายเดือนก่อน

      @@alexlowe2054 It's not a "refuse to support" problem, it's a "nobody came up with a solution that met all the necessary criteria" problem

  • @TheJimeux
    @TheJimeux 6 หลายเดือนก่อน +8

    I thought I was about to get roasted when I saw my sequence diagram in the thumbnail.
    I’m still not sure how I feel about the iterator spec. There are definitely readability issues, and a type called Seq2 seems more like something from a third-party library. I’m cautiously optimistic though.

    • @the.overthinking.bee2
      @the.overthinking.bee2 24 วันที่ผ่านมา

      Where could I have a look on your séquence diagram please ?

  • @blarghblargh
    @blarghblargh 6 หลายเดือนก่อน +2

    8:30 - "I don't know what n.b. is"
    n.b. is "nota bene", or so FYI. or just "note: ..."

  • @michaelmueller9635
    @michaelmueller9635 6 หลายเดือนก่อน +7

    DUCK SOUND @25:04

  • @KalleJillheden
    @KalleJillheden 6 หลายเดือนก่อน +1

    This Go proposal still allows for vectorization optimizations. I wonder if they could do inlining as well (maybe when doing PGO) of the for loop's code block, which is probably non-trivial as the block is passed around as a function pointer with nested layers of closures.

  • @johnhershberg5915
    @johnhershberg5915 6 หลายเดือนก่อน +30

    Every time I hear Prime describe what a language should be I think he's describing C#. You can't make a language so simple that people need to write everything every time, you need to make a language simple enough so everything you need to write should already be written and provided in the standard library. That's C# and .NET!

    • @jimiscott
      @jimiscott 6 หลายเดือนก่อน +14

      I bet he writes c# all the time, but doesn't have the guts to tell us.

    • @infantfrontender6131
      @infantfrontender6131 6 หลายเดือนก่อน +1

      @@jimiscott, literally C# tsundere-kun

    • @Jason-xw2md
      @Jason-xw2md 6 หลายเดือนก่อน +7

      besides errors as values, and null safety o_O

    • @johnhershberg5915
      @johnhershberg5915 6 หลายเดือนก่อน

      @@Jason-xw2md You can do errors as values if you want.
      What do you mean by null safety?

    • @zwparchman
      @zwparchman 6 หลายเดือนก่อน +8

      ​@@johnhershberg5915
      You cannot as the code you call is free to throw exceptions. You can do a mix, but that isn't the same.

  • @Bolpat
    @Bolpat 6 หลายเดือนก่อน +1

    It reminds me of how D does custom iteration. First of all, there are both approaches, i.e. the push and pull approaches. A type that implements the pull approach is called a range. A range has the following members: empty (returns true if it’s done), front (gives you the current element), and popFront (steps forward). A "foreach (x; xs) { … }" is equivalent to "for (auto copy = xs; !copy.empty; copy.popFront) { auto x = copy.front; … }". Most algorithms, such as iota, map, filter, reduce, etc., are based on ranges. However, sometimes iteration needs nontrivial state, such as walking a tree. For that, the push approach is better. In D, you give your type a member function named "opApply", which takes a callback delegate as a parameter. The body of a "foreach" is transformed to an appropriate callback for you. When "opApply" calls the callback, the callback returns 0 indicating "go ahead", or something nonzero, which "opApply" is supposed to return immediately. The transformed foreach body returns non-zero on break, return, goto, etc. (not continue, though). The neat thing is, the D compiler as a switch that lets you see the code after such lowerings.

    • @Bolpat
      @Bolpat 6 หลายเดือนก่อน

      The opApply can be overloaded with different-arity callbacks so that you can use "foreach (x; xs)", but also "foreach (i, x; xs)" or whatever number of arguments the callback takes.
      I have once written a tree type that has opApply walk the tree and provide an optional index, which is an array of indices that tells you which branch on the respective node was taken. Because "opApply" can re-use the index array, it can be allocated on the stack if the tree height is known in advance.

  • @LaPingvino
    @LaPingvino 6 หลายเดือนก่อน +2

    I think the reason for this is that for the easy models, Go already has and does what it is supposed to do. The design is literally meant to have full flexibility to implement support for everything else in Go. For anything the simple models support, you can already just use a loop with a channel. Works exactly the way you want and is cheaper. The whole idea of the proposal is to support everything that this approach cannot support.

  • @blarghblargh
    @blarghblargh 6 หลายเดือนก่อน +2

    oh are we bringing back the HR cut aways? hell yeah!

  • @SimonBuchanNz
    @SimonBuchanNz 6 หลายเดือนก่อน +2

    I think the explanation of push vs pull was rather confusing, if not confused.
    Mentioning that JS array methods operate on the whole array before the next method happens is talking about eager vs lazy evaluation, both push and pull iterators can do both - though what Prime is probably getting at here is that it's a lot easier to do eager with a push iterator than lazy, while both are easy with pull.
    The thing named iterator (or enumerator) from you're probably familiar with is a pull iterator, it has some "next" method you call to get either the next value or that it's done. A push interface is the opposite: you pass the iterator a "next" method that receives the items in the control of the iterator.
    The trade-off is generally that pull iterators are much easier to compose, but depending on the language much harder to write (without some sort of generator syntax at least) as they need to keep internal state between calls.
    Push is, in a way, really common in many situations you don't think of as being iterators at all, namely event listeners.

  • @rayoutube5451
    @rayoutube5451 6 หลายเดือนก่อน +2

    The function returning a function isn't a bad approach, but instead of the whole iteration and the yield function stuff, the iterator generator should return a next function like:
    func backwards[T](slice []T) func() (int, T, bool) {
    // setup everything
    return func() (int, T, bool) {
    // backwards access
    }
    }

  • @jfftck
    @jfftck 6 หลายเดือนก่อน +1

    Basic text files are also without a standard for encoding, but a smart user will use UTF-8 and modern software will usually default to it. But before Unicode created a standard, it was very hard to decode text files. Unfortunately, they first created standards that would make every character 2 or more bytes. Because of this, many applications have to have an algorithm to try and determine the encoding.
    So, being surprised that CSV doesn't have an official standard is mostly due to the encoding issue of the file that the data is stored in.

    • @defenestrated23
      @defenestrated23 6 หลายเดือนก่อน

      It's worse than that though. CSV makes no claims about when to use quotes or not, LF vs CR vs CRLF, escape characters, illegal sequences, unmatched quoting. Parsers and emitters are basically whatever "feels right"

    • @7th_CAV_Trooper
      @7th_CAV_Trooper 6 หลายเดือนก่อน

      RFC 4180

  • @realms4219
    @realms4219 6 หลายเดือนก่อน +12

    The most important aspect of a language is readability. This seems extremely unpleasant to process mentally, like Rust.

    • @matress-4-2323
      @matress-4-2323 6 หลายเดือนก่อน +14

      rust is more readable than go in my opinion. it's kind of a combination of javascript and ocaml syntax which i find to be readable. in theory go should be more readable but it requires a lot of boilerplate and i find boilerplate in go to be ugly and hard to read.

    • @monolith-zl4qt
      @monolith-zl4qt 6 หลายเดือนก่อน +3

      @@matress-4-2323 as a beginner in Go, I have no problem understanding any codebase, idk what unreadable boilerplate you're talking about. Go is by far the most readable lang I've used, but then again I've never touched rust so far. But what I hear from others about Rust is everything but a nice readability experience

    • @natescode
      @natescode 6 หลายเดือนก่อน +6

      Less code is more readable that the mess that Go is becoming. Maybe true for junior engineers.

  • @KayandraJT
    @KayandraJT 6 หลายเดือนก่อน +2

    I do agree making go iterators use an interface does make sense.
    fun fact we can sort any arbitrary datastructure in go by fulfilling an interface, so iterators would have fit right into this model.

  • @0xdiane
    @0xdiane 6 หลายเดือนก่อน +2

    I don’t have time to watch the full video so I might be missing context, but it seems really strange to me that channel syntax and go routine syntax wasn’t used. Really there’s not much going on here aside from having a go routine and channel that can swap back and forth without hitting a scheduler / mutex. Could have the syntax be like, out := go func(){ out

    • @defenestrated23
      @defenestrated23 6 หลายเดือนก่อน

      One of the main points was performance, because folks were using channels for iterator-like behavior. Channels have a mutex and involve the scheduler. Iterators are pure function calls and have order of magnitude less overhead.

  • @albertoarmando6711
    @albertoarmando6711 6 หลายเดือนก่อน +16

    I want go to stay as simple as possible.

  • @timburstefan
    @timburstefan 6 หลายเดือนก่อน

    Hey, Prime, random question: Why i cant watch 4k content on netlfix even if i have the 4k subscription and the HDCP protocol. Is there some sort of limitation because i want to watch 4k netflix content on my 2k screen but i cant so i have to make a custom res of 4k and then check netlfix to see that there is really 4k quality, which it is. Why just cant display 4k content on 2k display just like yt?

  • @anvityuk
    @anvityuk 5 หลายเดือนก่อน +1

    I agree that the syntax is not great. However, I disagree with the general statement that pull-based iterators are strictly superior than push-based.
    The beauty of a push-based iterator is that any existing data structure traversal code can be converted to the push-based version. This is almost as simple as replacing your print function with the yield function in relevant places.
    This is not so easy with the push-based, especially if you are using recursion in your implementation. Converting simple recursive algorithm into a pull-based iterator is not that simple.
    Another factor is a performance. In a pull-based version you do end up with more branches since the implementation has to restore its current state on every iteration. This is probably less of an issue for simple traversal algorithms.
    Another problem with the pull-based approach in C++ is that your loop state is managed in different places which makes it harder to reason about loop invariants.
    Where pull-based iterators shine, indeed, is composability. You can easily implement various constructs on top of it, such as iterating two data structures in parallel. This would be impossible in a push-based version without buffering all elements from one of the sides.
    So, back to the Go language proposal. Maybe it is in the spirit of Go’s simplicity.

  • @blarghblargh
    @blarghblargh 6 หลายเดือนก่อน

    I haven't thought about it much, but does "the odin iterator approach" require that each slice be fully baked out into contiguous memory, or can it deal with sparse generation/population? cause I think other iterator approaches might be more generalizable.
    is that difference the difference between "push" and "pull" iterators? I haven't heard those terms before.
    not sure how much that matters in practice. I have used iterators and made generators a decent amount (about a decade), and I understand the state machine under the covers, but I haven't thought comparatively about different approaches to implementing them. in places where I've actually cared about performance, I've switched to a fully imperative model that's as stupid and ugly as possible, so I could be damned sure of the memory usage and control flow patterns.
    but now that the subject is coming up, would be interested to see the differences.

    • @michaelthornes
      @michaelthornes 6 หลายเดือนก่อน

      summarizing a top-level comment here from SimonBuschanNz about push vs pull:
      push iterators are in control of the data, and are easier to implement (ie loop over data and yield values), but do require that ability to yield values. push iterators are like event emitters or js .forEach, where the iterator controls the data and you pass it the next function, so it can call that with each element.
      pull iterators can be more difficult to implement, because they usually need to keep state, but they can be easier to use on the client side. pull iterators are like calling a next function on the iterator when you want the next value, but you can choose to stop, skip by ignoring, sometimes reverse, etc. whenever you want.
      generators by means of go channels are push model, the iterator produces data on its terms. generators in js are pull model, since you have to explicitly ask for values by calling next on the iterator (js does allow you to "push" values by using yield. however, generators don't choose *when* the client code runs, since they don't call a function which runs the content of the loop like .forEach doesz the caller chooses when, if ever, to accept the produced yield values, by calling next)
      if you want to iterate over an infinite resource, like an iterator which always produces 0, you generally want a pull iterator, unless you're given a way to stop a push iterator (like your callback returning true/false) or you want it to go on forever

  • @7th_CAV_Trooper
    @7th_CAV_Trooper 6 หลายเดือนก่อน +1

    Pull VS push. As always it's a tradeoff and depends on the situation. As an architect that's pretty much all I say every day. "maybe. It depends."

  • @Gennys
    @Gennys 6 หลายเดือนก่อน +26

    In my mind, whenever Prime says "I wish they would have done it the *Rust* way". I can almost always just replace Rust with Java and it still works. Because he's usually just talking about interfaces anyway xD.

    • @tempname8263
      @tempname8263 6 หลายเดือนก่อน

      If you can replace it with Java, then you can replace it with C#. If you can replace it with C#, then you can replace it with BeefLang, - the ultimate language of all programming 🐮

  • @Kane0123
    @Kane0123 6 หลายเดือนก่อน +1

    28:05 literally ran into the lack of standard today…

  • @TravisBerthelot
    @TravisBerthelot 6 หลายเดือนก่อน

    Iterators perform poorly in C++ and Java as well. In what language are iterators a good thing (does not create objects)?

  • @ThomasWSmith-wm5xn
    @ThomasWSmith-wm5xn 6 หลายเดือนก่อน +1

    what the heck - i dont re-write the stuff ; i use proper golang structure so if i have it one place i can use it anywhere.

  • @escher4401
    @escher4401 6 หลายเดือนก่อน

    That's a pretty standard generator/coroutine/callback of callback/observer of observer pattern, it's just in the functional syntax

  • @doppeltevier
    @doppeltevier 6 หลายเดือนก่อน

    Could you create a video about Atlassian's new framework-agnostic, low-level dnd library called "pragmatic-drag-and-drop"?

  • @lovyNOM
    @lovyNOM 6 หลายเดือนก่อน +7

    imo I prefer C# iterators, they keywords yield return and yield break (and other syntax sugar) make it's iterators easy to read

    • @101Mant
      @101Mant 6 หลายเดือนก่อน +1

      Very similar to Python iterators and other languages.
      Go seems to have made an overly complicated mess of a problem that has been clearly solved already.

    • @sophiophile
      @sophiophile 6 หลายเดือนก่อน

      ​@@101Mant Yeah, things like the simplicity of having an iterator that is not an iterable, simply by using a generator function/using a yield statement so that you don't have to load iterables that are unfeasibly large, while having to change *nothing* else, is a perfect example of why I just zone out all the hate Python gets and finish POC projects 10x faster than other teams. Haha.

    • @SimonBuchanNz
      @SimonBuchanNz 6 หลายเดือนก่อน

      That's generators, strictly: a way to implement the iterator interface. (Actually IEnumerable/IEnumarator)
      Iterators are more about having an easy way to consume sequences (for each) than to define them, but really you want both.

    • @sophiophile
      @sophiophile 6 หลายเดือนก่อน

      @@SimonBuchanNz At least in Python's parlance, an iterator is a built-in class that takes either:
      * an iterable (an object, like a list, tuple, etc) which is iterated over, calling __next__() after each iteration to retrieve the subsequent item in it, or
      * a generator (a function that ends with a yield statement, and each time __next__() is called the function is called again to generate the next term in the sequence instead of loading a whole iterable when the class is constructed)

    • @SimonBuchanNz
      @SimonBuchanNz 6 หลายเดือนก่อน

      @@sophiophile that makes __next__ the python iterator interface, so a generator is still an iterator.

  • @patrickshepherd1341
    @patrickshepherd1341 5 หลายเดือนก่อน

    Lol do you think Dijkstra ever imagined that one article title would come to be a built in joke for programmers? 18:28

  • @captainfordo1
    @captainfordo1 6 หลายเดือนก่อน +3

    Odin mentioned.

  • @thekwoka4707
    @thekwoka4707 6 หลายเดือนก่อน

    the iterator syntax, while it has sense to it, looks like pure chaos.
    the whole function that returns a function that returns a function makes it look quite awkward.

  • @biggerdoofus
    @biggerdoofus 6 หลายเดือนก่อน +3

    I use c and lua because I like small numbers of tool rather large toolboxes. Do I get to be mediocre too?

  • @megetmorsomt
    @megetmorsomt 6 หลายเดือนก่อน

    Nim:
    iterator reversed[T](x:openArray[T]):T =
    var idx = x.high
    while idx >= x.low:
    yield x[idx]
    dec idx
    var nrs = [1,2,3,4,5,6,7,8,9,10]
    for nr in reversed nrs:
    echo nr

  • @microcolonel
    @microcolonel 6 หลายเดือนก่อน +1

    In JavaScript you have push and pull, as well as both generators and a method interface. I think it's a'ight.

  • @Alguem387
    @Alguem387 6 หลายเดือนก่อน +1

    Closures are just fancy objects, functions that take functions and return functions are just fancy classes

    • @7th_CAV_Trooper
      @7th_CAV_Trooper 6 หลายเดือนก่อน

      You're saying a closure is a higher order function? That's not right.

  • @microcolonel
    @microcolonel 6 หลายเดือนก่อน

    Both generators and first class async are almost the same thing: a persistent scope/continuation.
    If they made this thing a single concept from the language side, that would be one thing...
    Generators are great, can be a lot cleaner than struct (because the struct IS the scope), but the way they designed it for Go doesn't make sense to me.

  • @Monkeydew1o2
    @Monkeydew1o2 หลายเดือนก่อน

    Seems like one of those weird things where you could just "not use it" in a different sense than how C++ is. It's not so confusing that you can't understand it without using it.

  • @Jojor11
    @Jojor11 6 หลายเดือนก่อน +8

    When I tested go, I felt like the things I missed were generics and iterators… it feels like I’ll be completely happy with go soon xd

    • @AdroSlice
      @AdroSlice 6 หลายเดือนก่อน +1

      Honestly the only thing that's missing for me is an easier way to deal with common errors. Zig does this excellently by implementing error returns as a seperate language construct rather than using multiple returns, which allowed them to easily implement operators to early return errors

    • @natescode
      @natescode 6 หลายเดือนก่อน +6

      So basically when Go catches up to real languages but with worse developer ergonomics.

    • @orterves
      @orterves 6 หลายเดือนก่อน +1

      Except they both seem half-baked and tacked on

  • @dorktales254
    @dorktales254 6 หลายเดือนก่อน +2

    I guess we can call them "shiterators"

  • @nikocarpenter
    @nikocarpenter 6 หลายเดือนก่อน +2

    There's a reason Go couldn't implement pull iterators with an interface. Something like
    type Iterable[T any] {
    Iter() Iterator[T]
    }
    type Iterator[T any] {
    Next() (T, bool)
    }
    Seems like a very nice interface. The problem, and this was called out, is what if someone defines a type like `type MyType chan int`, and then implements Iterable on MyType? Now, if you for range over an instance of MyType, it's unclear as to whether you should get an iterator and call it's Next method, or whether you should receive values from the channel.
    By making both push and pull iterators functions, you're making them unique types, rather than existing types that implement an interface, so this problem goes away.

    • @nullid1492
      @nullid1492 6 หลายเดือนก่อน

      Just prevent implementing the iterator interface on channels. This is the same as how in rust you cannot impl iterator on the Range struct or any other struct that is already iterable.
      A neat way of doing this is to make a channel internally use the iterator interface.

    • @TurtleKwitty
      @TurtleKwitty 6 หลายเดือนก่อน

      If MyType implements the Iterable then clearly they meant to by iterable on MyType? Not sure how that would be unclear

  • @chaoslab
    @chaoslab 6 หลายเดือนก่อน

    Tonight on "When Iterators Go Bad!" (I'll show myself out...)

    • @tongpoo8985
      @tongpoo8985 6 หลายเดือนก่อน

      Iterators Gone Wild

  • @FUBAU
    @FUBAU 6 หลายเดือนก่อน

    I did honestly enjoy this video, as I generally dislike the screaming and acting “for entertainment/show”. Thanks!

  • @krumbergify
    @krumbergify 6 หลายเดือนก่อน +1

    I really like that the new iterators in Go support defer.

  • @jessypouliot8374
    @jessypouliot8374 6 หลายเดือนก่อน +1

    n.b. "nota bean" did chat meant to say "notez bien" 🇫🇷. Wtf is a naughty bean

    • @bitmasked
      @bitmasked 6 หลายเดือนก่อน +1

      It's from the latin "nota bene". On a beau être géniaux, on n'est pas le centre du monde.

  • @bokunochannel84207
    @bokunochannel84207 6 หลายเดือนก่อน

    compared to other changes in GO (everything isn't internal), iterator involve very little ammount of go contributors and i think their decision are biased.
    "if you can't decide, the answer is no."
    they shoudn't standarize iterator. but instead provide a best practive guides.

  • @hatter1290
    @hatter1290 6 หลายเดือนก่อน +1

    I don’t know how you can call Odin’s iterators simpler. I’ve always absolutely hated implementing pull iterators. I feel like Go’s approach is an order of magnitude simpler and less error prone.

    • @hatter1290
      @hatter1290 6 หลายเดือนก่อน

      @marcsfeh When composing with other iterators, it’s much harder (maybe even impossible) for the cleanup code not to run.
      I have definitely messed that up in pull based iterators before.

    • @TurtleKwitty
      @TurtleKwitty 6 หลายเดือนก่อน +1

      @@hatter1290 That's not a problem of the iterator being a pull style, it's a problem of memory management though

  • @isodoubIet
    @isodoubIet 6 หลายเดือนก่อน +8

    "historically, a C++ iterator would look like this:"
    *shows a snippet of what range-for desugars to*
    So much for the language designer.

    • @isodoubIet
      @isodoubIet 6 หลายเดือนก่อน +4

      Dude also has no idea why C++ iterators work the way they do. Anyone who wants to _actually_ understand this stuff and the tradeoffs being made should watch the talk "Iterators and Ranges: Comparing C++ to D to Rust" by Barry Revzin.

    • @ensuretime
      @ensuretime 6 หลายเดือนก่อน +1

      @@isodoubIet exactly, every time they need to compare how c++ handles this, they show how the expression is defined behind the compiler and not how it's actually used, it says a lot about the person...
      "hey, let's compare it to c++"
      - put the "real" c++ code in cppinsights and show the code to the compiler's eyes

    • @justanothercomment416
      @justanothercomment416 6 หลายเดือนก่อน +2

      And the standard library is so complete it's extremely unlikely you'll ever need to write an iterator in C++. So his entire argument is rather moot.

    • @loo_9
      @loo_9 6 หลายเดือนก่อน

      @@isodoubIetgiving this a watch, thx

    • @isodoubIet
      @isodoubIet 6 หลายเดือนก่อน +1

      @@justanothercomment416 And if you do end up having to write your own, it will automatically work correctly with all the algorithms in the standard library, some of which are flat out impossible to write in simpler iterator models. Alex Stepanov's STL is a work of genius; anyone trying to criticize it should at the very least understand it.

  • @luizpbraga
    @luizpbraga 6 หลายเดือนก่อน

    "I'm a language designer" 6:30

  • @andrewzuo86
    @andrewzuo86 6 หลายเดือนก่อน +1

    What's wrong with CSV? Although TSV is better because you're less likely to use tabs.

    • @maccsguitar
      @maccsguitar 5 หลายเดือนก่อน +1

      That its a non-standard brings problems everywhere. Some are separated with a comma, some are separated with semicolons or tabs, some have quotes surrounding the values and some have them only when the separator is included in the value, some use haphazard json-typing inside the values, some have more than one header-row and so produce multiple tables, some allow newlines inside values, some use backslash for escaping and some don't, some programs produce a different syntax depending on locale and don't know how to read all of their own produced formats (e.g. excel). Standardization would do it good.

  • @recarsion
    @recarsion 6 หลายเดือนก่อน +1

    This just feels so unneeded to me ngl. The whole selling point of Go is being a grug-brained language and this is the opposite of that.

  • @ddystopia8091
    @ddystopia8091 6 หลายเดือนก่อน

    Rust also has yield etc, called coroutines (generators previously)

    • @SimonBuchanNz
      @SimonBuchanNz 6 หลายเดือนก่อน +1

      Nothing is real until it's stable

  • @Lars-ce4rd
    @Lars-ce4rd 6 หลายเดือนก่อน

    yeah, so who are we going to believe? The mighty creator Thor, or the guy trying to convince us of his cgi stach?

  • @batatanna
    @batatanna 6 หลายเดือนก่อน

    It's been a while I've felt dumb watching a CS video. Guess I have to study more iterators.

  • @mrdmajor
    @mrdmajor 6 หลายเดือนก่อน

    Watching programmers argue, complain and make memes over complex unreadable syntax and calling human readable syntax "lame" is bizarre. I don't ever want to be a "programmer", I just want to learn how to create solutions for things I personally need done. I'd rather be on the Evan Czaplicki or Richard Feldman side of things. Thanks for reminding me why, genius system/low-level programmers. 🤣✌

  • @KangoV
    @KangoV 6 หลายเดือนก่อน

    To parse CSV I use an ANTLR grammer/lexer/parser. It's so cool.

  • @paxcoder
    @paxcoder 6 หลายเดือนก่อน

    The author admits himself to be imperative programming oriented. I think this is why the imperative variant looks easier to him. To me, the variant with yield is more straightforwards, maybe because I went through a functional programming (learning) phase. With functional programming concepts being built-into languages these days, I think new coders might agree

  • @TheCatmorte
    @TheCatmorte 6 หลายเดือนก่อน

    Same for me. It butthurted me so much right after announcement. We were ok without it and now instead of well known N approaches of doing things we'll have N+1 approach. Already imagining zoomers and boomers arguing in the comments under every PR about doing/not doing sht though iterators

  • @faiqr
    @faiqr 6 หลายเดือนก่อน

    they should have just called it yeet

  • @PassifloraCerulea
    @PassifloraCerulea 6 หลายเดือนก่อน

    I'd have more sympathy for Rob Pike's statement about Googlers not being able to appreciate a brilliant language if I knew of a brilliant language he himself had designed earlier. As it is, it feel like several of Go's design deficiencies have more to do with Pike and team's unfamiliarity with non-C-family language features. For example, in ML sum types & pattern matching and type inference & generics work together brilliantly but it's still plenty simple to learn and use.
    I appreciate Go's simplicity, but I can't shake the notion that it would have been a much better language while only a tiny bit more complex if it had some of these features, and further that if they had been familiar ML or similar that it wouldn't have taken them a decade to figure out how to do generics.

  • @sungwoolee484
    @sungwoolee484 6 หลายเดือนก่อน

    I expected a reaction video, prime.

  • @alexischicoine2072
    @alexischicoine2072 6 หลายเดือนก่อน

    The whole point of csv is that there’s no standard and it’s free for all.
    In the end it usually works fine other than it’s very slow.

  • @batboy49
    @batboy49 6 หลายเดือนก่อน

    I thought I would hate it....I love it now.

  • @TheHackysack
    @TheHackysack 6 หลายเดือนก่อน

    Please fix your "STREAM" link in your description.

  • @simonplace5164
    @simonplace5164 5 หลายเดือนก่อน

    @0:42 "for key,value := range myStruct" is 'super cool feature' only problem => it doesn't exist!
    thought i might have missed so double checked and everything. (during which i see others saying this.)WTF
    FWIW here's an field iter...
    '''
    import "reflect"
    func Fields(v any) (seq[struct{string;any}]){
    values := reflect.ValueOf(v)
    types := values.Type()
    return func(on func(struct{string;any})bool){
    for i := 0; i < values.NumField(); i++ {
    if !on(struct{string;any}{types.Field(i).Name,values.Field(i).Interface()}){
    return
    }
    }
    }
    }
    '''

  • @miracleinnocent2649
    @miracleinnocent2649 6 หลายเดือนก่อน +1

    we really need to gate keep more

  • @skeleton_craftGaming
    @skeleton_craftGaming 6 หลายเดือนก่อน

    15:29 yes writing LUA is easy but writing the interface between Lua and your C[++] program is not...
    I don't think that C++ iterators are the same thing as go/Odin iterators... C++ iterators are an abstraction of pure pointer math were as it seems that in GO and Odin they seem to generators incrementing over a list... and for what its worth c++ is like 40 years old at this point ...

    • @shinjoshinjo946
      @shinjoshinjo946 5 หลายเดือนก่อน

      Oh thanks for pointing that out. My only exposure to iterators so far has been in the context of C++ STL where they are explained as an abstraction of pointer arithmetic for custom data structures. So if you have proper operator overloading for your iterator type which conforms to the STL interface, an STL algo can operate on the elements without being exposed to its implementation details. While in Go iterators are more discussed in the context of iterating over a collection one element at a time, thereby saving memory, and also generators

    • @skeleton_craftGaming
      @skeleton_craftGaming 5 หลายเดือนก่อน

      @@shinjoshinjo946 C++'s iterators are pointers that point to the next value in the container rather than in the the next valid address for the contained T. AS FAR I CAN TELL Odin and GO just abstract the whole pointer thing away (so it is just opaque copy)

  • @larjasoul
    @larjasoul 5 หลายเดือนก่อน

    My issue is: what does this let Go do that it couldn't before? This is a violation of what most people like about Go.

  • @ThomasWSmith-wm5xn
    @ThomasWSmith-wm5xn 6 หลายเดือนก่อน +1

    hate the go iterators; javascripting my golang with worse looking syntax.

  • @jakubtomsu
    @jakubtomsu 5 หลายเดือนก่อน

    ODIN MENTIONED!!!🔥 WTF IS A BAD LANGUAGE DESIGN 🗣️🗣️

  • @KevinLyda
    @KevinLyda 6 หลายเดือนก่อน

    I do wish they'd used an interface for iterators.

  • @klasus2344
    @klasus2344 6 หลายเดือนก่อน

    If the language itself is powerful enough (like Rust), iterators are a cake walk

  • @alexpyattaev
    @alexpyattaev 6 หลายเดือนก่อน +3

    Any iterator ultimately stores state, rust just makes it explicit. The downside of this in rust is that it requires lifetems which are unfun. In go it would have been so easy to do with no additional syntax.

  • @badrakhariunchimeg1031
    @badrakhariunchimeg1031 4 หลายเดือนก่อน

    Don't they have ssh of their own for example reg 0110++1 mov reg [massage] ;

  • @xhivo97
    @xhivo97 6 หลายเดือนก่อน +1

    I love gingerbill I will watch this.

  • @krumbergify
    @krumbergify 6 หลายเดือนก่อน

    CSV tried to be so simple that it became extremly complicated.

  • @TheWrxrally
    @TheWrxrally 6 หลายเดือนก่อน

    They tried to make it look like Python generators. That's the easiest way to think about it if you know Python.

  • @IgorKaratayev
    @IgorKaratayev 6 หลายเดือนก่อน +5

    Go iterators are very simple, people just overcomplicate them in their mind for some reason.

  • @Tony-dp1rl
    @Tony-dp1rl 6 หลายเดือนก่อน

    I will never understand why Go has such terrible syntax. It was freaking new. Everything the language is designed to do could have been done with really nice, familiar syntax, and it would have been an amazing language.

  • @_neophyte
    @_neophyte 5 หลายเดือนก่อน

    5P and LTTM seething rn

  • @neiljp-dev
    @neiljp-dev 6 หลายเดือนก่อน

    I enjoy your content, though still surprised to see you engage on X - I don't see any obvious fediverse/mastodon presence?

  • @mikhailryzhov9419
    @mikhailryzhov9419 4 หลายเดือนก่อน

    CSV is for people who don't like regulation, you can make your own rules and carve your own incompatible path.

  • @dough-pizza
    @dough-pizza 6 หลายเดือนก่อน

    Just code in a normal language like Java guys, that go snippet was simply too horrible to deal with

  • @Tvde1
    @Tvde1 6 หลายเดือนก่อน

    why make such complex concepts and such heavy and complex function definitions (you have to write func 6 times) instead of making it simple like C#

  • @tiko-
    @tiko- 6 หลายเดือนก่อน

    they are good actually. i've written like 5 slightly different iterators when making libraries. just give me a standard interface. thank you

  • @andrewiglinski148
    @andrewiglinski148 15 วันที่ผ่านมา

    Why Go? Because I had s--t to do and learning Rust would've taken too long.

  • @zactron1997
    @zactron1997 6 หลายเดือนก่อน

    I despise this version of Go iterators. Far too hard to understand what's going on at a glance and very deeply nested. Go's designers aren't idiots so I'm sure there are very good reasons they're championing this design, but C#/Rust/Java got it right with an Iterator interface that you pull values out of.