Threads for s-video

  1. 2

    One of the funny things about starting with C and later Go is that every other language seems so vast in comparison. That gives Zig some appeal to me.

    1. 9

      Not sure how to feel about that. Those new styles certainly look cleaner but I reflexively dislike introducing new ways to do the same thing. (Though I do think try was ok.)

      Edit: On second thought, the arrow style looks really weird. I think if an anonymous struct has to have the word struct, then an anonymous function should have the word func.

      1. 3

        On second thought, the arrow style looks really weird. I think if an anonymous struct has to have the word struct, then an anonymous function should have the word func.

        I’m used to the fat arrow from JavaScript. In the abstract, I agree that it would be better to reuse the func keyword, but given that to make it work grammatically, they would have to drop the parentheses, which makes things look misgrouped, I think all things equal, the fat arrow is the lesser of two evil.

      1. 29

        Am I the only one being completely tired of these rants/language flamewars? Just use whatever works for you, who cares

        1. 13

          You’re welcome to use whatever language you like, but others (e.g. me) do want to see debates on programming language design, and watch the field advance.

          1. 7

            Do debates in blogs and internets comments meaningfully advance language design compared to, say, researchers and engineers exploring and experimenting and holding conferences and publishing their findings? I think @thiht was talking about the former.

            1. 2

              I’m idling in at least four IRC channels on Libera Chat right now with researchers who regularly publish. Two of those channels are dedicated to programming language theory, design, and implementation. One of these channels is regularly filled with the sort of aggressive discussion that folks are tired of reading. I don’t know whether the flamewars help advance the state of the art, but they seem to be common among some research communities.

              1. 5

                Do you find that the researchers, who publish, are partaking in the aggressive discussions? I used to hang out in a couple Plan 9/9front-related channels, and something interesting I noticed is that among the small percentage of people there who made regular contributions (by which I mean code) to 9front, they participated in aggressive, flamey discussion less often than those that didn’t make contributions, and the one who seemed to contribute the most to 9front was also one of the most level-headed people there.

                1. 2

                  It’s been a while since I’ve been in academia (I was focusing on the intersection of PLT and networking), and when I was there none of the researchers bothered with this sort of quotidian language politics. Most of them were focused around the languages/concepts/papers they were working with and many of them didn’t actually use their languages/ideas in real-world situations (nor should they, the job of a researcher is to research not to engineer.) There was plenty of drama in academia but not about who was using which programming language. It had more to do with grant applications and conference politics. I remember only encountering this sort of angryposting about programming languages in online non-academic discussions on PLT.

                  Now this may have changed. I haven’t been in academia in about a decade now. The lines between “researcher” and “practitioner” may have even become more porous. But I found academics much more focused on the task at hand than the culture around programming languages among non-academics. To some extent academics can’t be too critical because the creator of an academic language may be a reviewer for an academic’s paper submission at a conference.

                  1. 2

                    I’d say that about half of the aggressive folks have published programming languages or PLT/PLD research. I know what you’re saying — the empty cans rattle the most.

            2. 9

              You are definitely not the only one. The hide button is our friend.

              1. 2

                So I was initially keen on Go when it first came out. But have since switched to Rust for a number of different reasons, correctness and elegance among them.

                But I don’t ever say “you shouldn’t use X” (where ‘X’ is Go, Java, etc.). I think it is best to promote neat projects in my favorite language. Or spending a little time to write more introductory material to make it easier for people interested to get started in Rust.

                1. 2

                  I would go further, filtering for rant, meta and law makes Lobsters much better.

                  rant is basically the community saying an article is just flamebait, but short of outright removing it. You can choose to remove it.

                2. 6

                  I think this debate is still meaningful because we cannot always decide what we use.

                  If there are technical or institutional barriers, you can ignore $LANG, such as if you’re writing Android apps, where you will use a JVM language (either Kotlin or Java) but if you are writing backend services, outside forces may compel you to adopt Go, despite its shortcomings detailed in this post (and others by the author).

                  Every post of this kind helps those who find themselves facing a future where they must write Go to articulate their misgivings.

                1. 12

                  I’d like to mention Bartosz Ciechanowski, who explains complex technical topics with interactive, animated figures.

                  1. 5

                    These are so well crafted that I’m at loss. I can’t imagine the amount of time it would take to come up with something like this.

                  1. 8

                    It’s sort of crazy how influenced this is by Go.

                    1. 7

                      Go is in many aspects a better C, but the runtime makes it not a C replacement.

                      1. 2

                        On a related note, I suspect the name “Hare” and the mascot are a nod to Plan 9’s Glenda mascot.

                      1. 15

                        They’re not active streams, but on the Go YouTube channel there’s a video of Andrew Gerrand and Brad Fitzpatrick pair programming in Go. I think there’s at least one more. There’s also Russ Cox’s Advent of Code series, which has has about two hours of Go material, including an hour long and half hour long videos.

                        1. 4

                          The advent of code series from @rsc is great! Though it’s not quite “doing The Thing” as much as explaining a solution he’s already worked out.

                          1. 1

                            That’s true, but I think at least the hour long video was done without having a solution ahead of time? I haven’t watched it in full, but I’ve skipped around and it seems like he’s doing it off the cuff in that one.

                        1. 1

                          I’ve only skimmed this at the moment, but compiling highlights and philosophy from Plan 9 (and adjacent) mailing lists is something I’ve wanted to do for a while, so I’m really happy someone else has had the idea.

                          1. 2

                            Indeed. although the current post only scratches the surface. I regularly mine 9fans for tips and tricks from seasoned practitioners. I use (deadpixi) sam especially when working on remote machines. It is a refreshing change from the frantic typing required on emacs and vi(m) and not having to carry your config across machines. Terminals still need a lot of typing but using @LeahNeukirchen’s tt, which is a Ruby/Tk implementation of the ideas from 9term, has made it tolerable again. Perhaps I should switch to acme fully…

                            1. 1

                              Amazing this still works!

                              1. 1

                                Ruby/Tk was a bit of a bother to build (needed some symlinks to find the libs). Once built, tt is easily one of the most useful v0.1 program on my computers. Thanks!

                          1. 14

                            Overall, this is a well researched and detailed article, but the tone comes across as “this doesn’t monomorphism 100% and therefore Go generics are bad and slow” - which as a prevailing sentiment, represents a simply incomplete analysis. The Go team was obviously aware of the tradeoffs, and so it seems unfair in many ways.

                            One key thing not discussed in this article are generic containers where the element type was previously interface{} and no methods are ever called on that interface. In this extremely common use case, Go’s generics are likely to be as fast as manually monomorphized code.

                            Another key use case is for general code that need not be performance-critical, where reflection may have been used previously. In these cases, generics are likely to be strictly faster than reflection as well (potentially modulo some icache issues for megamorphic call sites).

                            Finally, this design allows for future compiler enhancements - including additional inlining of indirect/interface calls!

                            As an aside, if you were doing semi-automated monomorphization before with text templating, you now have a much richer and more robust for such a toolchain. That is, you can use Go’s syntax/parser and type-checker, then provide a code generator that spits out manually monomorphized Go code. If nobody has done this yet, I’m sure it will happen soon, as it’s quite straightforward.

                            1. 9

                              I didn’t get that tone, especially with the conclusion of the article. The author encourages folks to use generics in certain cases, shows cases where they do get optimized well, and is hopeful for a future where they get either full monomorphization and/or for the optimization heuristics to get better.

                              To me this seemed like a very fair article, even if they did miss the case that you mentioned.

                              1. 3

                                One key thing not discussed in this article are generic containers where the element type was previously interface{} and no methods are ever called on that interface. In this extremely common use case, Go’s generics are likely to be as fast as manually monomorphized code.

                                The article mentions that byteseq is fast. This is just a special case of that: the vtable indirection can’t slow you down if you never dispatch a method. :-)

                                That is, you can use Go’s syntax/parser and type-checker, then provide a code generator that spits out manually monomorphized Go code. If nobody has done this yet, I’m sure it will happen soon, as it’s quite straightforward.

                                I was looking into this last night. I think you can still use the “go2go” tool from the design prototyping of generics, but it’s no longer being maintained and will probably become subtly incompatible soon if it isn’t already.

                                1. 0

                                  It’s hard to take it seriously as anything other than the Go team continuing to hate generics and trying to do everything they can do to discourage people from using them.

                                  The fact that there are people here talking about (afaict) continuing to use old Go code generators to support generic code without an absurd memory hit demonstrates that Go’s generics have not achieved the most basic of performance goals.

                                  1. 21

                                    It’s hard to take it seriously as anything other than the Go team continuing to hate generics and trying to do everything they can do to discourage people from using them.

                                    sigh It’s hard to take you seriously with this comment. You might have different opinions/preferences than the Go team, but to assume that they are trying to sabotage themselves is ridiculous.

                                    Go’s generics have not achieved the most basic of performance goals

                                    I’ve written and deployed at three major Go systems – one of which processes tens of petabytes of video per week – and I can count the number of times monomorphisation was necessary to achieve our performance goals on one hand. Generally, I copy/paste/tweak the < 100 lines of relevant code and move on with my work. Performance is not the only motivation for generics.

                                    I’ve also written a fair bit of C++ in my life & have also had the experience where I had to disable monomorphization to avoid blowing the instruction cache. To say nothing of compile times.

                                    You don’t like Go. That’s fine, but maybe don’t shit on the people who are working hard to create something useful for the people who do like it.

                                    1. 8

                                      Generally, I [do something simple] and move on with my work.

                                      That summarizes my Go experience in the last decade. I miss this in basically every other language now.

                                      Also the generics turned out very nice imho, I’m impressed with the balance they managed to strike in the design.

                                      1. 6

                                        Also, this is…. clearly a compiler heuristic that can be tightened or loosened in future releases. They just chose “all pointers are the same” in order to ship quickly.

                                        1. 2

                                          OTOH, no one can say they shipped generics “quickly“. Even Java did it quicker, though not better.

                                          1. 1

                                            It only took 11 years after this was posted: https://research.swtch.com/generic :-)

                                        2. 0

                                          The Go team has stated that they do not like generics. They only added them now because everyone working with Go was continuously frustrated by, and complaining about, the lack of generics.

                                          Given that background, I believe it is reasonable to assume that the Go team did not consider competitive generics to be a significant goal.

                                          Worrying about compile time is something compiler developers should do, but given the option between faster build time for a few developers, vs faster run time for huge numbers of end users, the latter is the correct call.

                                          I obviously can’t speak to what your projects are, but I would consider repeatedly copy/pasting essentially the same code to be a problem.

                                          I don’t like Go, but I also didn’t complain about the language. I complained about an implementation of generics with questionable performance tradeoffs, from a group that has historically vigorously argued against generics.

                                          1. 6

                                            The Go team has stated that they do not like generics.

                                            Do you have a source for that claim? All I remember is a very early statement, that also has been on the website.

                                            Looked it up. This was in since at least 2010[1].

                                            Why does Go not have generic types?

                                            Generics may well be added at some point. We don’t feel an urgency for them, although we understand some programmers do.

                                            [1] https://web.archive.org/web/20101123010932/http://golang.org/doc/go_faq.html

                                            1. 2

                                              You’re right in that I can’t point to a single quote.

                                              I can however point at the last decade of Go devs talking about supporting generics, which has pretty consistently taken the path of “generics make the language harder” (despite them being present in a bunch of builtin types anyway?), “generics make the code bigger”, “generics make compilation slower”. Your above quote even says that they recognize that it’s developers outside the core Go team that see the benefit of generics.

                                              This is not me beating up on Go, nor is it me questioning the competence of the core team. This is me saying that in light of their historical reticence to support generics, this comes across as being an intentionally minimal viable implementation created primarily to appease the hoard of devs that want the feature, rather than to provide a good level of performance.

                                              1. 7

                                                in light of their historical reticence to support generics

                                                Ian Lance Taylor, one of the largest and earliest Go contributors, was advocating or at least suggesting generics for quite some time. He was exploring design ideas since at least 2010, with a more serious design in 2013. I think this contradicts the “giving in and appeasing the masses” sentiment you’re projecting on the Go team.

                                                Come to think of it, he also wrote a very long rebuttal to a commenter on the golang-nuts mailing list who was essentially saying what you’re saying. I’ll see if I can find it. Edit: Here it is.

                                                1. 3

                                                  this comes across as being an intentionally minimal viable implementation created primarily to appease the hoard of devs that want the feature, rather than to provide a good level of performance.

                                                  That sounds like a very unconvincing argument to me. In my opinion they did a very good job with the accepted generics proposal, because it keeps the language simple while also helping to avoid a lot of boilerplate, especially in libraries. Also, the Go team has pointed out several points of the generics implementation they want to improve on in upcoming releases. Why should they do that if they just had implemented generics only to please “ the hoard of devs that want the feature”?

                                                  1. 2

                                                    I will say that compared to early generics proposals, the final design is quite a bit more Go-like. It’s unfortunate that the type constraints between the [] can get quite long, but if you ignore the type parameters, the functions look just like normal Go functions.

                                              2. 4

                                                The Go team has stated that they do not like generics.

                                                I don’t think that is true at all. They stated (1) that they did not like either end of the tradeoffs with erasure (characterized by Java) causing slow programs and full specialization (characterized by C++ templates) causing slow compile times. And (2) that some designs are needlessly complex.

                                                They spent years refining the design - even collaborating with Academia - to minimize added type system complexity and choose a balanced performance/compile-time implementation tradeoff that met their objectives.

                                                given the option between faster build time for a few developers, vs faster run time for huge numbers of end users, the latter is the correct call.

                                                I couldn’t possibly disagree more.

                                                I would consider repeatedly copy/pasting essentially the same code to be a problem.

                                                I can’t think of any lowery severity problem affecting any of my projects.

                                                Anyway, I won’t reply to any further messages in this thread.

                                                1. 1

                                                  They only added them now because everyone working with Go was continuously frustrated by, and complaining about, the lack of generics.

                                                  I would phrase it that everyone not working with Go was complaining about the lack of generics, and the Google marketing team assigned to Go (Steve Francia and Carmen Ando being the most prominent) are working hard to sell Go to the enterprise, so it was priority to clear that bullet point up.

                                                  People working with Go generally just bite the bullet and use code generation if necessary, but mostly just ignored the lack of generics.

                                              3. 4

                                                Self-sabotage just for the sake of generics doesn’t make sense because this release slowed down build times for everyone not just people using generics: https://github.com/golang/go/issues/49569.

                                            1. 3

                                              I get this was probably the best design given that they really didn’t want to break backwards compatibility and didn’t want something too difficult to implement, but I’m not a fan of type sets being in interfaces, or constraints being a special kind of interface that can only be used to describe type parameters. It kind of overloads the meaning of interface to be either a regular interface that you can use (almost) anywhere, or a special one that you can only use for type parameters. Knowing that something is an interface won’t be enough to know where you can use it; you’ll have to know if it has a type set in it. And even though listing types and listing methods are two ways to describe sets of types, I see them as fundamentally different, because when describing a set of types by listing them you start with an empty set and widen it, and when you describe a set of types by listing methods you start with every type and narrow it down.

                                              1. 3

                                                Interfaces as type sets is a powerful new mechanism and is key to making type constraints work in Go. For now, interfaces that use the new syntactic forms may only be used as constraints. But it’s not hard to imagine how explicitly type-constrained interfaces might be useful in general.

                                                My guess is they will add unrestricted constraints as interface values next year in 1.20.

                                                1. 1

                                                  I was kind of worried that unrestricted constraints would lead to type Result[T any] interface { T | error }*, but it seems like that still wouldn’t be allowed. It still mildly bugs me that these two ways of describing sets of types are merged into one construct. My “dream” Go would just separate them into a different construct like union types at that point. But oh well, still a nice design overall. Also, I wonder if we would still call them constraints at that point, or just interfaces–wouldn’t they be interchangeable?

                                                  * Not that I don’t like result types, it would just be uncharacteristic for Go if new error handling techniques suddenly popped up.

                                                2. 2

                                                  An earlier generics proposal actually had type constraints as a separate concept, but it was struck down.

                                                  I believe the Go team has plans to allow using type-list interfaces outside constraints as well.

                                                1. 11

                                                  Feels unusual reading something from Dan Luu that also has CSS.

                                                  1. 2

                                                    Do you think he has a gun to his head?

                                                  1. 2

                                                    I like how design proposals and github threads are in there. I like reading them because sometimes you see insightful or interesting comments you wouldn’t find elsewhere. A recent example is in the Github discussion for revising the doc comment syntax, in which Russ Cox proposes having gofmt change bulleted lists using “*” or “+” to use “-”, because dashes are used for list items in professional typesetting but not asterisks or plusses.

                                                    1. 21

                                                      I lack the knowledge and vocabulary to rant about UI/page designs I dislike in a way that gets across what I dislike about them so it was really gratifying to read this.

                                                      1. 1

                                                        meta: does a website really have to look like this in 2022? Luckily Firefox has “reader view”.

                                                        1. 5

                                                          It works well in mobile at least.

                                                          1. 2

                                                            Yeah, it seems just adding body { max-width: 36em } would be enough for the site to be readable on desktop as well.

                                                          2. 4

                                                            Heh. As soon as content from this author shows up on HN, there’s a gush of people fawning over the “clean” and “oldschool” look of their pages.

                                                            Personally I’d be fine with it if the margins were a bit bigger.

                                                            1. 6

                                                              I like “brutalist” webdesign too, but readability should be the focus of published text IMO

                                                              1. 2

                                                                As a counterweight, do you like or dislike this recent submission?

                                                                http://rachelbythebay.com/w/2022/02/09/nice/

                                                                1. 6

                                                                  Rachel’s site is unfashionable but fine. Dan’s site is an aggressive nose thumb to the reader. There’s no comparison.

                                                                  1. 4

                                                                    not beautiful but a lot more readable.

                                                              2. 3

                                                                I think the author made his website like that to work for people with really bad connections. I think he also mentioned somewhere that wiping CSS off his site led to more engagement, but I could be wrong.

                                                                1. 6

                                                                  Obligatory http://bettermotherfuckingwebsite.com/ I guess. 7 lines of CSS isn’t going to make a noticeable difference on load times even on dialup.

                                                                  But yeah, how on earth do people survive without Reader View?

                                                                2. 1

                                                                  +1, a column of text 70-90 characters wide is the most readable option personally, and it requires the least css. One could do it with <br> if one really wants.

                                                                  1. 3

                                                                    Don’t hard wrap! It will make it look horrible on harrow screens. max-width will do that in a sec.

                                                                1. 5

                                                                  Every time I’ve tried to start SICP so far I’ve given up. I usually fail to complete books I start (I did finish The Little Schemer though), so I wouldn’t pin that entirely on SICP, but I do resonant with the comments here on its style and prose; to me that aspect of it is particularly painful. A book that starts with a thesis that programming is really no more than a tool of expressing thought or something is likely to lose me, for better or for worse. That’s just me though.

                                                                  I can also relate this to a microelectronics textbook I had in college, Sedra and Smith. It has good reviews and approving blurbs from other EE professors, but when I sat down to read a section that covered whatever was in the latest homework, I could barely parse it. It may have been full of correct statements, but it just did not feel like it was written in a way for someone who has never understood the material before to understand. I found that a lot of popular undergrad textbooks are like this.

                                                                  1. 17

                                                                    Keyword arguments

                                                                    If these are important, you can get a pretty good approximation with structs, e.g.

                                                                    type Point struct{ X, Y float64 }
                                                                    func EuclidianDistance(p Point) float64 { ... }
                                                                    d := EuclidianDistance(Point{X: 3.0, Y: 9.6})
                                                                    

                                                                    Absence of sum/discriminated-union types

                                                                    Because reposurgeon events can have any one of a set of types (Blob, Tag, Commit, Callout, Passthrough, Reset) I found myself writing a lot of stupid boilerplate code like this:

                                                                    Yeah, type assertions usually aren’t the way to go, as they’re not runtime-safe. Generics will make this better but the best approach right now is a non-discriminated union type e.g.

                                                                    type Event struct {
                                                                        *Blob
                                                                        *Tag
                                                                        *Commit
                                                                        ...
                                                                    }
                                                                    

                                                                    and checking for nils.

                                                                    Catchable exceptions require silly contortions

                                                                    Go does not have exceptions. Using panic/recover as ersatz exceptions is essentially always a design error. If you ever find yourself trying to recreate an exception control flow, you are almost certainly on a bad path.

                                                                    I kept looking at places where existing nonlocal control transfers in Python could be replaced by explicit Go-style passing upwards of an error status. But I noticed that there were a significant percentage of cases in which doing this made the code more difficult to follow rather than easier . . . An early reviewer pointed out that if the Go code were an entire function it could be expressed something like this . . . That’s still a lot of eyeball friction compared to functional-style with exceptions. And it gets worse faster as the number of stages rises.

                                                                    Effective use of Go requires the programmer to choose to see that example function as wonderfully explicit, rather than full of “eyeball friction”. I’ve said this many times: in Go, the happy path is equally important to the sad path. You have to just accept that and work with it, or you’ll hate the language.

                                                                    Figuring out how to do type-safe polymorphism in the event list

                                                                    Go does not currently support type polymorphism. Generics will change that, but at the moment, trying to approximate it is a sure-fire way to frustrate yourself and produce bad code.

                                                                    1. Keyword arguments should be added to the language.

                                                                    Emphatically no.

                                                                    1. True iterators are felt by their absence and would be easy to add.

                                                                    Not without sacrificing the performance goals of the language.

                                                                    1. Any enlargement in the range of what can be declared const would be good for safety and expressiveness.

                                                                    +1.

                                                                    1. Yes, throw()/catch() needs to be writeable in the language. Two minimal relaxations of compilation rules would make writing it possible.

                                                                    Emphatically no. One of Go’s fundamental opinions is that exceptions are bad. You have to buy in to that. If you don’t want to, no problem! Go isn’t the language for you.

                                                                    1. A technical writer with an outside-in view of the language should be hired on to do an edit pass and reorganization of the documents.

                                                                    +1.

                                                                    1. Lookbehinds should be added to the regexp library.

                                                                    There are good reasons this doesn’t exist currently. It’s unlikely to change.

                                                                    1. 20

                                                                      There are good reasons this doesn’t exist currently.

                                                                      This comment is Go community in the nutshell. How many people were happy about lack of generics, and now they are happy about their future presence. Same think can happen here.

                                                                      1. 11

                                                                        Every week, I get another bullshit security notification from Depndabot that my JavaScript depends in some tangential way on a package with a malicious regex vulnerability. If people want lookbehinds, whatever, but it shouldn’t be in the standard library because it’s a total safety hazard.

                                                                        1. 8

                                                                          Package regexp implements RE2 which does not support backtracking or lookbehind (are they the same thing? I’m not totally sure) by design. Adding support for these capabilities would mean switching to a different flavor of regexp, which would break the compatibility guarantee.

                                                                          There are several third-party PCRE modules available, though I’m not sure what compromises they may make.

                                                                          1. 4

                                                                            Context for the Regexp limitations: https://swtch.com/~rsc/regexp/regexp1.html

                                                                            1. 4

                                                                              Insightful comment. Thank you.

                                                                              Not without sacrificing the performance goals of the language.

                                                                              Is that true? I don’t necessarily agree that Go should get iterators, but I can’t wrap my head around why they would make Go lose performance. Couldn’t it be as simple as having range accept an interface like: (yes yes, no generics in the language, but range is special)

                                                                              interface Iter<T> {
                                                                                  Next(): *T, bool
                                                                              }
                                                                              
                                                                              1. 1

                                                                                I’m unclear why no one has brought up channels and go routines as an alternative to iterators. Channel size of 1, blocks on send making it “lazy”.

                                                                                1. 4

                                                                                  The linked blog post in the original post does go into that: https://ewencp.org/blog/golang-iterators/index.html

                                                                                  1. 2

                                                                                    Blargh! you are correct. I overlooked that when I read the post. :)

                                                                                  2. 3

                                                                                    They’re too slow. See a recent issue discussion: https://github.com/golang/go/issues/48567

                                                                                2. 2

                                                                                  Broadly I agree, but I’m a little confused on this point:

                                                                                  Not without sacrificing the performance goals of the language.

                                                                                  Iterators should be zero cost, no? Is your concern that the next() method won’t be properly inlined? I also haven’t been following the generics saga closely, but presumably we’ll have typesafe generic iterators either via the stdlib or third-party once generics land.

                                                                                  1. 1

                                                                                    My guess is that the go compiler isn’t optimizing hard enough. Until very recently, it didn’t even put arguments in registers when calling functions.

                                                                                    Rust made iterators “zero-cost”, but the real cost is in compilation time, and Go would rather sacrifice runtime speed for compilation speed.

                                                                                    1. 1

                                                                                      Go definitely has an inliner, but it probably can’t see across package boundaries to your point. Personally I would like to know more about the compilation cost of link-time optimizations which would optimize across compilation units.

                                                                                      1. 1

                                                                                        It does indeed inline across package boundaries.

                                                                                        1. 1

                                                                                          Really? I thought packages were compilation units and Go didn’t do LTO (I assume LTO is required for optimizing across compilation units, but I’m pretty out of my depth)?

                                                                                          1. 1

                                                                                            I’m no expert, but here’s a basic example https://godbolt.org/z/98xKj1dfc

                                                                                            1. 1

                                                                                              Hmm, I’m suspicious about stdlib packages because I know they are treated specially by the compiler, at least in some cases.

                                                                                              1. 1

                                                                                                I believe you’re referring to compiler intrinsics. But from what I’ve seen, the compiler doesn’t special case inlining rules for the stdlib.

                                                                                      2. 1

                                                                                        It is not true that Go prefers to sacrifice runtime speed for compilation speed. Rather, compilation speed is a first order priority of the language, and compiler optimizations are made only when people decide to make them. The lack of a register based calling convention, for example, didn’t become the lowest hanging performance fruit until relatively recently, so effort was spent elsewhere. That’s fine.

                                                                                  1. 5

                                                                                    Gilles Chehade, one of the authors of OpenSMTPD, wrote a big tutorial on setting up an OpenBSD email server, in case anyone else wants to try it.

                                                                                    1. 7

                                                                                      The book The UNIX Programming Environment by Kernighan and Pike is also a great read on much the same topic. It’s expensive to buy new but I found a cheap second-hand copy.

                                                                                      The thing is, I find the argument really compelling… but it doesn’t seem to have caught on. Some people really like this style of computing - see the Plan 9 holdouts, for example - but UNIX moved away from it pretty quickly once it left Bell Labs (hence this paper, which uses BSD and SysV changes as examples). GNU is definitely not UNIX, and Windows never was.

                                                                                      It seems like the UNIX style appeals strongly to a few people, but has no mass appeal. Maybe it appeals strongly to developers whose main focus is building software systems, but less to end users - and hence less to developers whose main focus is building software for those end users? Contrast Kernighan and Pike’s paper with Jamie Zawinski’s Unity of Interface, which he described as, “An argument for why kitchen-sink user interfaces (such as web browsers, and emacs) are a good idea.”

                                                                                      1. 11

                                                                                        Modularity is great if it comes with composability. UNIX originally justified its existence with a typesetting system and the UNIX kind of modularity where you consume a text file and produce a text file was great for that. The only stage that wasn’t plain text was the set of printer control commands that were sent to the printer device (over a stream interface, which looked like a text stream if you squinted a bit). It doesn’t actually work for anything non-trivial.

                                                                                        Here’s a toy example: Consider ls -Slh. In a UNIX purist world, -l is the only one of these that you actually need in ls and actually you don’t need that because if -l is the default you can get the non-verbose output with ls -l | cut -f 9 -w and you can make that a shell alias if you use it often enough. You don’t need -S because sort can sort things, so you can do ls -l | sort -k5. Except that now you’ve gone away from the UNIX spirit a bit because now both sort and cut have the functionality to split a line of text into fields. Okay, now that you’ve done that how do you add the -h bit as a separate command? You can do it with some awk that splits the input and rewrites that one column, but now you’ve added an entire new Turing-complete language interpreter to the mix. You could, in fact, just do ls | awk and implement the whole sort part in awk as well. If you do this, you’ll discover that awk scripts compose a lot better than UNIX pipelines because they have functions that can take structured values.

                                                                                        Many years ago, I sent a small patch to OpenBSD’s du to add the -d option, which I use with around 90% of du invocations (du -h -d1 is my most common du invocation). The patch was rejected because you can implement the -d equivalent with -c and a moderately complex find command. And that’s fine in isolation, but it doesn’t then compose with the other du flags.

                                                                                        The UNIX-Haters Handbook explained the problem very well: We’ve implemented some great abstractions in computing for building reusable components: they’re functions that consume and produce rich data types. Composing systems implemented in terms of these primitives works great. Witness the huge number of C/C++ libraries, Python packages, and so on in the world. In contrast, plumbing together streams of text works well for trivial examples, can be forced to work for slightly more complex examples, and quickly becomes completely impossible for more complex ones.

                                                                                        Even some of the most successful kitchen-sink UIs have been successful because they support composition. Word and Photoshop, for example, each have rich ecosystems of extensions and plugins that add extra features and owe their success in a large part to these features. You can build image-processing pipelines in UNIX with ImageMagick and friends but adding an interactive step in the middle (e.g. point at the bit you want to extract) is painful, whereas writing a Photoshop workflow that is triggered from a selection is much easier. Successful editors, such as vim, emacs, and VS Code, are popular because of their extensions far more than their core functionality: even today, NeoVim and Vim are popular, yet nvi has only a few die-hard users.

                                                                                        1. 5

                                                                                          Yeah I agree the sort -k5 thing is annoying. Several alternative shells solve that to some extent, like PowerShell, nushell, and maybe Elvish (?). They have structured data, and you can sort by a column by naming it, not by coming up with a sort invocation that re-parses it every time (and sort is weirder than I thought.)

                                                                                          However I want a Bourne shell to have it, and that’s Oil, although it’s not done yet. I think what PowerShell etc. do has a deficiency in that it creates problems of composition. It doesn’t follow what what I’m calling the Perlis-Thompson principle (blog posts forthcoming).

                                                                                          So Oil will support an interchange format for tables, not have an in-memory representation of tables: https://github.com/oilshell/oil/wiki/TSV2-Proposal (not implemented)

                                                                                          I also think the shell / awk split is annoying, and Shell, Awk, and Make Should Be Combined.

                                                                                          1. 1

                                                                                            Unfortunately, it’s not really something that you can solve in a shell because the problem is the set of communication primitives that it builds on. PowerShell is incredibly badly named, because it’s not really a shell (a tool whose primary purpose is invoking external programs), it’s a REPL. It has the converse problem: there’s no isolation between things in PowerShell.

                                                                                            Something like D-BUS would be a reasonably solid building block. If the shell managed a private D-BUS namespace for the current session then you could write composed commands that run a bunch of programs with RPC endpoints in both directions and some policy for controlling how they go together. You could then have commands that exposed rich objects to each other.

                                                                                            ’d be quite curious to know what a shell based around the idea of exporting D-BUS objects would look like, where if you wrote foo | bar then it would invoke both with D-BUS handles in well-known locations for each, rather than file descriptors for stdin / stdout. For example, a shell might provide a /shell/pipeline/{uuid} namespace and set an environment variable with that UUID and another with the position in the pipeline for each process so that foo would expose something in /shell/pipeline/3c660423-ee16-11eb-b8cf-00155d687d03/1 and look for something exposed as /shell/pipeline/3c660423-ee16-11eb-b8cf-00155d687d03/2, expose the /0 and /3 things for input from and output to the terminal (and these could be a richer set of interfaces than a PTY, but might also provide the file descriptor to the PTY or file directly if desired). Each shell session might run its own D-BUS bus or hook into an existing one and the shell might also define builtins for defining objects from scripts or hooking in things from other places in a D-BUS system.

                                                                                            1. 2

                                                                                              (very late reply, something reminded me of this comment recently)

                                                                                              I don’t see why you need DBus or anything similar to solve the sort -k5 problem? I think you just need something like TSV over pipes, and then a sort-by tool that takes a column name to sort by. An enhancement would be to attach types to column names, so you don’t have to choose whether to do sort (lexicographic) or sort -n (numeric) – that would be in the data rather than the code.

                                                                                              There are already people who use CSV/TSV, XML/HTML, and JSON over pipes. And entire shell-based toolkits and languages around them, like jq, csvkit, etc.

                                                                                              Projects listed at the end of this page: https://github.com/oilshell/oil/wiki/Structured-Data-in-Oil

                                                                                              So I think there is a lot of room to improve the shell without changing anything about the kernel. Sure you don’t have metadata for byte streams, but these tools should be strict about parse errors, and it’s very easy to tell a TSV vs. HTML vs. JSON document apart. I think better parse errors would go a long way, and that can be done in user space.

                                                                                          2. 4

                                                                                            Interestingly enough, OpenBSD added the -d option to du some years ago: https://cvsweb.openbsd.org/src/usr.bin/du/du.c?rev=1.26&content-type=text/x-cvsweb-markup

                                                                                            And the reason is to be compatible with other BSDs and Linux and so we’re back to the original topic ;)

                                                                                            1. 5

                                                                                              I think I submitted my patch to add -d in 2004 or 2005, so it took OpenBSD over a decade to actually add the feature. I was running a locally patched du for the entire time I was using OpenBSD. That interaction put me off contributing to OpenBSD - the reaction of ‘this feature is a waste of time, you can achieve the same thing with this complicated find expression’ and the hostility with which the message was delivered made me decide not to bother with writing any other code that would require that I interacted with the same people.

                                                                                              1. 3

                                                                                                Sorry to hear that. In general I find it is extremely difficult to reject patches gracefully, even when you are trying to. It’s one of those things where text loses nuance that would do the job in real life, and so you have to be extra enthusiastic about it. I usually try to start on a positive statement ‘cause that’s what people will see first, something like “I love this, thanks for submitting it. But, there’s no way I can accept this because…”. If it’s a (smallish) bug fix rather than a feature addition I often try to accept it anyway, even if it kinda sucks, and then clean it up myself.

                                                                                                I’m all for technical rigor, but if a project wants to attract contributions, it’s nice to have a reputation for being easy to work with. And it’s better for everyone if people are encouraged to submit patches without them fearing a nasty rejection. You never know when someone sending a patch is a 13 year old self-taught hacker with more enthusiasm than sense, just starting to play with getting involved in the world outside their own head.

                                                                                                1. 2

                                                                                                  Interesting, found the original mailing list response where the “rejection” was given: https://marc.info/?l=openbsd-tech&m=115649277726459&w=2

                                                                                                  How frustrating to receive that response, “it is not being added as it is not part of POSIX”, since -d got added some years later, with the commit message explicitly acknowledging its omission from POSIX standards at the time. :\

                                                                                                  On the upside, looks like you had the right intentions all along so I send some kudos your way for trying :)

                                                                                                  1. 3

                                                                                                    How frustrating to receive that response, “it is not being added as it is not part of POSIX”, since -d got added some years later, with the commit message explicitly acknowledging its omission from POSIX standards at the time. :\

                                                                                                    To be fair, eight years is a long time and the project might have changed its mind about POSIX.

                                                                                                    I started this comment by writing that I was not sure the reasoning was inconsistent. David’s patch was rejected in part due to portability concerns. And schwarze’s commit message does mention compatibility with other BSDs and GNU as justification.

                                                                                                    But on the other hand, support for -d appeared in NetBSD around the same time as David’s patch and in FreeBSD even before that. Soooo… you’re probably right :-)

                                                                                                    1. 2

                                                                                                      haha, yeah I mean, it’s fair to stick to POSIX, but I guess in David’s case it was a matter of the person reviewing the submission being more stringent about that than the person/people who adopted the change later.

                                                                                                      Out of curiosity I checked the FreeBSD du.c commit history and found that the -d option was added in Oct 1996! Glad they kept the full commit history upon each transition to a new versioning technology (since I’ve definitely encountered projects where that history was lost). Ah well, anyway, that’s more than I expected to learn about the history of du this week! haha :)

                                                                                            2. 5

                                                                                              To me, the closest thing to the Unix philosophy today is the Go standard library. It has lots of functions with simple APIs that take io.Readers or io.Writers and lets you compose them into whatever particular tool you need. I guess this makes sense, since it’s from Rob Pike.

                                                                                              The thing about the Unix philosophy is it’s not just about “small” tools that do one thing. It’s about finding the right abstraction that covers a wider range of cases by being simpler. Power comes from having fewer features.

                                                                                              For example, file systems before Unix were more complicated and featureful. We see today that for example, iOS makes files complicated in an old school mainframe like way where some data is in the Photos library, some is locked in a particular app, some needs iTunes to be extracted, and some is actually in the Files app. This might be the right choice in terms of creating a lot of small seemingly simple interfaces instead of one actually simple interface that can do everything, but it makes it much harder to extend things in ways not envisioned by the software developers.

                                                                                              1. 3

                                                                                                To me, the closest thing to the Unix philosophy today is the Go standard library. It has lots of functions with simple APIs that take io.Readers or io.Writers and lets you compose them into whatever particular tool you need. I guess this makes sense, since it’s from Rob Pike.

                                                                                                Yeah, he mentioned this in “Less is Exponentially More”:

                                                                                                Doug McIlroy, the eventual inventor of Unix pipes, wrote in 1964 (!):

                                                                                                We should have some ways of coupling programs like garden hose–screw in another segment when it becomes necessary to massage data in another way. This is the way of IO also.

                                                                                                That is the way of Go also. Go takes that idea and pushes it very far. It is a language of composition and coupling.

                                                                                                It’s fun to think of Go programs like that. Like a website could be a bunch of http handler functions slotted into a mux, and an HTML template parser is wired up to the handers’ response witers. It’s nice to think like that in terms of packages too. My favorite packages are those that I can think of as a “part” that I can hook up to other parts.

                                                                                                The thing about the Unix philosophy is it’s not just about “small” tools that do one thing. It’s about finding the right abstraction that covers a wider range of cases by being simpler. Power comes from having fewer features.

                                                                                                Definitely. I think the “do one thing…” etc sayings kind of miss the point. And io.Writers and io.Readers are definitely that kind of abstaction. They have one method and can therefore easily cover a wide range of types. I think Go’s interfaces work that way in general too, since they grow more specific and “narrow” with more methods and the number of types that implement them shrinks.

                                                                                            1. 3

                                                                                              This is good to see. I tried running a program that happened to use color in 9term and the output was just unreadable because it doesn’t process ANSI escape codes. It would be nice to have a similar environment variable for disabling animations that use ANSI escape codes as well, like progress bars or anything that goes back and modifies lines and characters that were already printed.

                                                                                              1. 8

                                                                                                like progress bars or anything that goes back and modifies lines and characters that were already printed.

                                                                                                That’s not ANSI escape codes, that’s just carriage return. And if your terminal doesn’t even support carriage return… well, I don’t have a strong urge to support your terminal.

                                                                                                Really though, you should enter the 70s and get a VT100-compatible terminal.

                                                                                                1. 1

                                                                                                  It’s not that I really desire support for it, I just like it when programs don’t rely on it or have an option not to.

                                                                                                  1. 4

                                                                                                    There’s no point arguing with legacy applications that require 70s’ VT100. Since you linked to 9term, below is something I use. This follows the same spirit of feeding a cat but replacing the cat with a supercharged nobs(1).

                                                                                                    #!/usr/bin/env rc
                                                                                                    . 9.rc
                                                                                                    fn printf{awk 'BEGIN{printf "'$1'";exit}'}
                                                                                                    b=`{printf '\b'}
                                                                                                    r=`{printf '\r'}
                                                                                                    ifs='' n=`{printf '\n'}
                                                                                                    sed -l '
                                                                                                    	:b
                                                                                                    	s/[^'$b$r']'$b'//g
                                                                                                    	t b
                                                                                                    	s/[ 	'$r']*'$r'$//g
                                                                                                    	s/[ 	'$r']*'$r'/\'$n'/g' \
                                                                                                    	$*
                                                                                                    
                                                                                                    1. 1

                                                                                                      Woah, thanks!

                                                                                                2. 4

                                                                                                  Most of the programs are “intelligent” enough, such that you only need to feed it to a cat to make the output plain.

                                                                                                  intelligent_app | cat
                                                                                                  
                                                                                                  1. 8

                                                                                                    Everyone always asks isatty, but no one ever asks howsatty