I think what he means is it is not just generally crawling and scraping, and uses a more targeted approach. Equivalent to a user going to each of those sites, just more efficiently.
I'm guessing that would ideally mean only reading the content the user would otherwise have gone through. I wonder if that's the case and if it's guaranteed.
Maybe some new standards and maybe a user configurable per site permissions may make it better?
> only reading the content the user would otherwise have gone through.
Why? My user agent is configured to make things easier for me and allow me to access content that I wouldn't otherwise choose to access. Dark mode allows me to read late at night. Reader mode allows me to read content that would otherwise be unbearably cluttered. I can zoom in on small text to better see it.
Should my reader mode or dark mode or zoom feature have to respect robots.txt because otherwise they'd allow me to access content that I would otherwise have chosen to leave alone?
Yeah no, nothing of that helps you bypass the ads on their website*, but scraping and summarizing does, so its wildly different for monetization purposes, and in most cases that means the maintainability and survival of any given website.
I know its not completely true, I know reader mode can help you bypass the ads _after_ you already had a peek at the cluttered version, but if you need to go to the next page or something like that you need to disable reader-mode once and so on, so its a very granular ad-blocking while many AI use cases are about bypassing viewing it at all by a human; and the other thing is that reader mode is not very popular so its not a significant threat.
*or other links on their websites, or informative banners, etc
And also, just to confirm, I'm to understand that if I'm navigating the internet with an ad blocker then you believe that I should respect robots.txt because my user agent is now a robot by virtue of using an ad blocker?
Is that also true if I browse with a terminal-based browser that simply doesn't render JavaScript or images?
If you are using an ad-blocker by definition you are intentionally breaking the intended behavior by the creator of any given website (for personal gain), in that context any discussion about robots.txt or any other behavior that the creator expects is a moot point.
Autoconfig of reader mode and so on its so uncommon that is not even in the radar of most websites, if it was browser developers probably would try to create a solution that satisfies both parties, like putting the ads at the end and required to be text-only and other guidelines, but its not popular, same thing happens with terminal-based browsers, a lot of the most visited websites in the world don't even work without JS enabled.
On the other hand, this AI stuff seems to envision a larger userbase so it could become a concern and therefore the role of robots.txt or other anti-bot features could have some practical connotations.
> If you are using an ad-blocker by definition you are intentionally breaking the intended behavior by the creator of any given website (for personal gain), in that context any discussion about robots.txt or any other behavior that the creator expects is a moot point.
I'm not asking if you believe ad blocking is ethical, I got that you don't. I'm asking if it turns my browser into a scraper that should be treated as such, which is an orthogonal question to the ethics of the tool in the first place.
I strongly disagree that user agents of the sort shown in the demo should count as robots. Robots.txt is designed for bots that produce tons of traffic to discourage them from hitting expensive endpoints (or to politely ask them to not scrape at all). I've responded to incidents caused by scraper traffic and this tool will never produce traffic in the same order of magnitude as a problematic scraper.
If we count this as a robot for the purposes of robots.txt we're heading down a path that will end the user agent freedom we've hitherto enjoyed. I cannot endorse that path.
For me the line is simple, and it's the one defined by robotstxt.org [0]: "A robot is a program that automatically traverses the Web's hypertext structure by retrieving a document, and recursively retrieving all documents that are referenced. ... Normal Web browsers are not robots, because they are operated by a human, and don't automatically retrieve referenced documents (other than inline images)."
If the user agent is acting on my instructions and accessing a specific and limited subset of the site that I asked it to, it's not a web scraper and should not be treated as such. The defining feature of a robot is amount of traffic produced, not what my user agent does with the information it pulls.
robots.txt is not there to protect your ad-based business model. It's meant for automated scrapers that recursively retrieve all pages on your website, which this browser is not doing at all. What a user does with a page after it has entered their browser is their own prerogative.
>It's meant for automated scrapers that recursively retrieve all pages on your website, _which this browser is not doing at all_
AFAIK this is false, and this browser can do things like "summarize all the cooking recipes linked in this page" and therefore act exactly like a scraper (even if at smaller scale than most scrapers)
If tomorrow magically all phones and all computers had an ad-blocking browser installed -and set as the default browser- a big chunk of the economy would collapse, so while I can see the philosophical value of "What a user does with a page after it has entered their browser is their own prerogative", the pragmatic in me knows that if all users cared about that and enforced it it would have grave repercussions in the livelihood of many.
> A robot is a program that automatically traverses the Web's hypertext structure by retrieving a document, and recursively retrieving all documents that are referenced.
There's nothing recursive about "summarize all the cooking recipes linked on this page". That's a single-level iterative loop.
I will grant that I should alter my original statement: if OP wanted to respect robots.txt when it receives a request that should be interpreted as an instruction to recursively fetch pages, then I'd think that's an appropriate use of robots.txt, because that's not materially different than implementing a web crawler by hand in code.
But that represents a tiny subset of the queries that will go through a tool like this and respecting robots.txt for non-recursive requests would lead to silly outcomes like the browser refusing to load reddit.com [0].
The concept of robots.txt was created in a different time, when nobody envisioned that users would one day use commands written in plain English sentences to interact with websites (including interacting with multiple pages with such commands), so the discussion about if AI browsers should respect it or if they should not is senseless, and instead -if this kind of usage takes off- it would probably make more sense to have a new standard for such use cases, something like AI-browsers.txt to make clear the intent of blocking (or not) AI browsing capabilities.
Alright, I think we can agree on that. I'll see you over in that new standardization discussion fighting fiercely for protections to make sure companies don't abuse it to compromise the open web.
If I buy a pencil and draw a copyrighted character, is that copyright infringement? No. If I sell that drawing? Yes.
Midjourney and other AI companies are not selling you the drawing, they're selling you the pencil. What you do with that pencil and the drawings you create with that pencil is on you and you alone.
Are you familiar with the DICE framework in terms of VR? Essentially, VR enables one to do things that are [D]angerous, [I]mpossible, [C]ostly, or [E]xpensive.
Your racecar example is a perfect example. It would be dangerous and costly. Would it be better than VR racing? I think so. Would I be able to actually do it? Hell no. I suspect most people would answer the same.
Yes, I know expensive and costly are basically the same thing.
This! I recently ditched Spotify and rediscovered radio in the past few weeks. There are so many great songs I've come across from bands I enjoy that I had never heard of because, as someone else said, Spotify's algorithm is way overfit.
It's also great sometimes to discover great music from genre you usually don't like, or... just be exposed to songs you don't like. This is what helps building a musical culture.
Please allow me to recommend FIP, as a human (it's a classic here but there's no such thing as recommending too much FIP) : https://www.radiofrance.fr/fip
FIP and NTS are my goto's. The discovery features for shows on NTS and the "in focus" specials are great, so many good opportunities there for serendipitous listening. Will def check out radio paradise
FIP is broadcasting in FM in France, so no big news on that one, for me.
But i will investigate NTS. I knew their radios streams, but it seems they also have some pretty niche podcasts !
And remember you can always get the audio steam through HTTP Live Streaming (HLS), on its M3U format, or others with better quality.
There are many Android apps like Transistor to enjoy the stream, and even VLC can open these, in order to avoid using a web browser.
Likewise, I prefer online radios than big tech algorithms that craft my music experience.
Did you know there exists languages that don't have run time errors? Languages that you can never crash outside of an OOM.
That means you can't find a language with no mistakes. But across all languages there are languages with astronomically more gotchas and mistakes then others.
Golang is one of these languages that is astronomical. I mean just compare it to the language with zero runtime errors.
It "succeeded" in that it delivers on its promise and some people still use it, but it is largely dead now due to the lack of development and the community's inability to push the language itself forward. There are forks that address that, but Elm itself seems unlikely to Lazarus any time soon.
It's definitely proof that software can be written in such a regime, though, and I hope we see something similarly dogmatic some day.
Gleam / Lustre are fantastic, and I hope to use them in anger at some point, but it's my understanding that they don't aim to be as "total" as Elm (quotation marks because I don't think Elm was total in the formal sense). That is, while Lustre is very much following in Elm's footsteps, both it and the language have not been designed around avoiding runtime failure at all costs. (Which makes sense, given the Erlang/BEAM heritage.)
It depends on what you consider failure. If you feel popularity is the main metric then golang is successful. Outside of that metric golang is pretty bad.
The proof is in the pudding. Here’s a quote from rob pike the creator of golang:
“The key point here is our programmers are Googlers, they’re not researchers. They’re typically, fairly young, fresh out of school, probably learned Java, maybe learned C or C++, probably learned Python. They’re not capable of understanding a brilliant language but we want to use them to build good software. So, the language that we give them has to be easy for them to understand and easy to adopt.”
Basically in a nutshell he’s saying they dumbed down golang so it’s useable by beginners. Golang is a step backwards. A failure in language development but a success in popularity.
You dumb down a language to a point where the language is so dumbed down it hits the largest demographic. You are part of that demographic. It’s similar to the demographic that voted for trump because he’s not fakeish like all the other candidates.
I understand what you are saying here but I think you've missed the point of what Pike was getting at.
I think Pike is acknowledging the practical realities of engineering at scale, and intentionally designed Go with simplicity in mind, which leads to more maintainable code and faster onboarding for new devs.
I'll also add that outside of the popularity metric, Go is not all bad. Fast compile times, readability, excellent standard library and toolchain, backward compatibility, to name a few things.
>I think Pike is acknowledging the practical realities of engineering at scale, and intentionally designed Go with simplicity in mind, which leads to more maintainable code and faster onboarding for new devs.
Doubt it. Read what he wrote. He's literally referring to people without much experience in programming. The stuff you said is literally NOT what he said.
>I'll also add that outside of the popularity metric, Go is not all bad. Fast compile times, readability, excellent standard library and toolchain, backward compatibility, to name a few things.
Pike didn't write it, he said it. (1) It is a talk about how Go was created to make concurrency simple. The "brilliant" language he refers to here is C++, which I'm sure you're aware has many of its own downsides.
Your argument that Go is a step backward because it was intentionally designed to be simple for novice programmers seems flawed. It's design was a deliberate tradeoff to address a specific problem. While I don't think it is a language that should be used for everything, it is good at the things it is good at.
What is it about Go that you have a problem with, specifically?
I understand he said it. But I can’t transmit voice over HN so I need you to read the transcript I made oof what he said rather then listen to it. I’m actually really confused why you couldn’t figure out this is what I meant. I could make a link and point you to the time like you did, but it’s easier to refer to it with an actual written version. Make sense? I hope so.
> The "brilliant" language he refers to here is C++, which I'm sure you're aware has many of its own downsides.
No. The brilliant language he’s referring to is a hypothetical one he could have created. Instead he created golang because he needed to create a language catered to people with less experience. That is what he is saying. I find it strange that you can literally read what is written and also reference the video and literally not understand what was literally said/written.
Maybe you’re just making up meaning subconsciously to cater to your own biases rather then facing the cold hard truth that pike created go to be not “brilliant”.
> What is it about Go that you have a problem with, specifically?
Oh there’s tons of stuff. One is that errors don’t have stack traces. You create an error that can’t be handled and so it bubbles up the stack until the only way to handle it is with a panic. You see the panic in your logs but now you have no idea where the error came from because no stack trace. You get the trace of the panic but no trace of the error. The whole thing is just poorly thought out.
The reason I emphasize that he said it and didn't write it is because it indicated to me that you weren't aware it was actually a talk he gave and you were just regurgitating a cherry picked quote that's been passed around since he said it.
That further indicated to me that you are not aware of the broader context of what he was saying. He literally spends the first 19 minutes talking about writing something in C++, then says the quote.
It seems it is you who is catering to your own biases by using a few sentences from a 20 minute talk to oversimplify what Pike I'd saying.
The interpretation I am giving is based on the entire talk, not just the quote. I acknowledge that he said Go was created for less experienced devs, but I don't think it that means it is a step backward as you said. It enables so much to be done by the "dumber" demographic, as you so eloquently put it. Go, like any other language, has its limitations. It shouldn't be used for everything, but should be used for the things it is good at (obviously).
> the language is so dumbed down it hits the largest demographic. You are part of that demographic. It’s similar to the demographic that voted for trump because he’s not fakeish like all the other candidates.
I've been a lot of places and done a lot of things but I've never had somebody liken me to a Trump voter because I like a programming language. Is this the new Godwin's law? Did panic() and nil kill your grandpappy?
> Basically in a nutshell he’s saying they dumbed down golang so it’s useable by beginners.
He's saying that developers can't handle Coq (the brilliant language), so they had to build a language that is like every other commonly used language, for better or worse.
> A failure in language development
As brilliant as Coq truly is, he's not wrong, is he? It is no coincidence that nobody is using Coq to build web servers. Which is, after all, what Pike said Go was designed for – that it was not intended to be a general purpose programming language. The vast majority of developers, even outside of Google, truly can't grasp it... And of even the scant few developers who can, they will tell you that the tradeoffs aren't worth it for something like a run-of-the-mill CRUD web server.
Your, being a researcher who does understand Coq, perspective is interesting from an academic angle, but Pike's point is that you don't understand the realities of engineering. This "Use Coq or you are no better than a Trump supporter" shows he was exactly on point. Cry as you might, nobody is going to be using Coq to build web servers, and for good reason.
No he's saying go is designed for people like you. You're obviously joking about COQ, but I'm not joking about you. This is literally what he's talking about. Take a step back out of your sarcasm and look at reality. You are the demographic Pike is talking about. And we both know Pike is not even referring to coq.
> No he's saying go is designed for people like you.
Stands to reason. It is true that I do spend my time on the engineering side of the industry. While I have great appreciation for the brilliant languages, they don't offer a whole lot for practical production work after you've weighed the tradeoffs. Especially in the particular niche Go is designed for. You are going to use a blub language like Rust for those types of problems, and for good reason.
> And we both know Pike is not even referring to coq.
Lean, then? The brilliant list isn't terribly long. We do know he isn't talking about Scala and Haskell, at least. He lumps them in with C++ and Java – albeit he has expressed that they are more beautiful. Not that anyone would consider them brilliant anyway. Well, maybe if you consider Trump to be also brilliant... There is always that guy.
It’s designed for people who don’t have much experience with programming. He literally said this. There is nothing said about coq or lean... that’s just trolling.
> It’s designed for people who don’t have much experience with programming.
Exactly. It follows the same basic "loop, variable, function" programming model as Java, C++, Haskell, PHP, Ruby, Rust, Python, LISP, Smalltalk, basically every language you've seen production code written in, that is familiar to early career beginners who have come out of traditional learning paths (e.g. college). Where once you understand one of them, you can jump into another with minimal overhead. None of these languages brilliant, but they are useful. Which is where he said they wanted Go to fit as well: A language that is useful and familiar.
That isn't what researchers and language theory enthusiasts want. They are enthralled by languages that think about programming in an entirely different way. The key point here is that it wasn't built for them. That is what he said.
That’s a stretch. Your saying he called golang not brilliant then you say basically every language from Haskell to Java is also not brilliant. Let’s be real here.
You also talk about looping for languages with no loops. And additionally pike never brought up looping at all. You just made this part up out of thin air. Your evidence is made up. He never said or referenced any of things you said.
> The key point here is that it wasn't built for them. That is what he said.
No read what he said again. He didn’t say golang was not designed for language experts. He did say it was designed for programmers just out of school with barely any experience with programming languages. He did not say he designed golang for an average engineeer who is not a PL expert he said he designed golang for literally people just out of school.
I don’t know how you can make stuff up out of thin air like this. Read what he literally said.
Most of the mistakes in this book and general mistakes you make when programming aren't about crashes or other runtime errors. They are about writing code that is overly complex or otherwise difficult to maintain.
I don't think Go is particularly esoteric to where these "gotchas" are a big problem.
In fact, I would argue that the gotchas are an intentional part of Go's design philosophy. I think it is strange to work in Go when coming from another language because of this, which leads people to think Go sucks.
That may be part of why they think Go sucks, but it is mostly because Go doesn't have many features to paper over poor design decisions. "Advanced" languages let you throw any old gobbledygook at them, and when you finally realize you screwed up, you can just monkey patch (or whatever feature of the day the language has) your way out of it and call it a day. Go is far less forgiving. You have to get the design right or pain will ensue. And pain does ensue for those who try it after being accustomed to having leeway in haphazard design, and thus they conclude Go sucks instead of acknowledging that their design sucks.
I mean, Go does suck. Maybe a language should be accommodating to bad designs. But still, those shouting "Go sucks" from the rooftops never seem to be willing to bring introspection into where they might have failed. It's always someone else's fault. (Something not limited to the case of Go, of course)
Go sucks not because it's accomodating to poor designs. It sucks because it is in itself poorly designed and that leaks over to the design of entire applications.
Why have functions return err, nil? Why even allow for a runtime error here? It's a really simple fix. You don't even have to make the language complex to support this. Instead the entire program is littered with holes and if statements you have to check in order to prevent a actual crash
Why not? It doesn't make any difference in practice. Without a complete type system you must write tests to ensure that error conditions (to stay with your example, although this also applies broadly) do what you need of them. If you somehow introduced a runtime error there, your tests would be unable to not notice. Whether your compiler cries or your test suite cries when you screw up is not a meaningful difference.
> You don't even have to make the language complex to support this.
A complete type system is insanely complex to implement and even harder to write against.
Without a complete type system, all you can have is silly half-measures. Maybe the error becomes an optional/result type with forced unwrapping, for example, but you still haven't asserted in the types what needs to happen with the error. So you still need to write the same tests that you had to write anyway. So, other than moving where you discover the problem – from your tests to the compiler – nothing has changed.
The half-measures are a cute party trick, I'll give you that, but makes no real difference when actual engineering is taking place. They might, however, give a false sense of security. They might even convince you that you don't need to write tests (you do). Maybe those make for desirable traits?
> Doesn't make any difference in practice meaning you never had a runtime error while running go?
I am not sure I have written enough Go to comment there, but I have worked extensively in other languages where runtime errors are possible, similar to Go in that regard. I have encountered runtime errors in said tests now and then, sure, but then you know about it and deal with it... So, in practice, no different than if the compiler told you that there is a possible runtime error.
> Who says you need a complex type system?
It is needed if you want to avoid the need for said tests. With a complete type system the type system can become your test suite, so to speak. But the languages people normally use, even those with "advanced" type systems, are nowhere near expressive enough for that. Meaning that you have to write the tests anyway. And then you'll know if there are any runtime errors as soon as you run your tests because how could the tests run without encountering the runtime error too? It is not like a CPU magically changes how it works if it detects that a test is being run. So, in practice, the type system doesn't change the outcome. But it is a cool party trick. I'll give you that.
That said, aside from these hand-wavy, make-believe stories, you are still very right that Go would benefit from sum types. For the reason that they map to the human model of the world very well, succinctly communicating structures that are often needed to be expressed. Languages are decidedly for humans. You can sort of work in the same basic idea in Go using interfaces, but it is far more confusing to read and understand than sum types would be. For a language that claims to value readability...
> So, in practice, no different than if the compiler told you that there is a possible runtime error.
If your program has runtime errors then that means you can deploy it to production and catch your errors in production.
If your compiler catches all possible runtime errors and refuses to compile. Then you will have no runtime errors in production guaranteed by proof. The program cannot even exist with runtime errors. It can only exist with no runtime errors.
So no difference catching errors in production vs. compile time? I beg to differ. Big fucking difference imho.
> It is needed if you want to avoid the need for said tests.
I’m referring to the fact that you don’t need a complex type system to design a language that will absolutely never have any runtime errors. You’re going off on a tangent here about how you need a type system to have less tests which is completely different from what I’m talking about. This entire paragraph you wrote here is like you’re responding to an irrelevant topic.
> I am not sure I have written enough Go to comment there
Honestly it seems that you haven’t just not written enough go. But basically any programming language . It seems that you’re not clear about runtime errors and you seem to have only encountered these types of errors during tests. So yes you don’t have much experience imho and rob pike deliberately targeted the language towards people like you.
> If your program has runtime errors then that means you can deploy it to production and catch your errors in production.
That questions: Why are you allowing your programs to be deployed when tests are failing? This is not a realistic scenario in the real world. Yes, you can invent contrived hypotheticals all day long, but it is meaningless. We've been clear that we are referring to practical settings.
But, but, what if there is a bug in your compiler that sees the runtime error slip through??? Who gives a shit? In some imaged world it may be possible, but it is not realistic. Not worth talking about.
> I’m referring to the fact that you don’t need a complex type system to design a language that will absolutely never have any runtime errors. You’re going off on a tangent here
What you are referring to is clear, but it cannot be considered in a vacuum. The alternative is to see the program keep trodding along, but do the wrong thing. In that case who cares if the program crashes instead? You're getting incorrect behaviour either way.
What you actually need is assurances that the program won't do the wrong thing top to bottom. That requires either a complete type system or, more realistically in the real world, testing. If you go the testing route, you'll know about any runtime errors when you run your tests.
> Honestly it seems that you haven’t just not written enough go.
There is nothing unique to Go here. Many popular languages suffer the same problem. But, if we want to place extensive Go experience as a requirement to speak to this then we have to defer to your experience. Perhaps you can choose an example of where you wrote code in Go that produced a runtime error, show us your tests, and explain how the condition evaded your checks and balances? – I'm fascinated to learn how your code ran perfectly while under test but then blew up in production.
> That questions: Why are you allowing your programs to be deployed when tests are failing? This is not a realistic scenario in the real world. Yes, you can invent contrived hypotheticals all day long, but it is meaningless. We've been clear that we are referring to practical settings.
Tests don’t catch everything. You can have a billion tests and there can still be uncaught runtime errors.
If you had a language that probably does not have runtime errors you don’t even need one test. Your program cannot fail in that way.
I honestly don’t think you know what you’re talking about. I didn’t make up a single hypothetical. This is real. Production errors can happen in spite of tests. Are you not familiar with this happening? It just means this: no experience.
Your compiler having a bug or not is orthogonal to the topic. Again you don’t know what you are talking about. If our compiler allows for runtime errors but is fully correct then no amount of tests can guarantee a runtime error will never happen. Golang as a fully correct compiler cannot be gauranteed to have no runtime errors with tests ever.
> What you are referring to is clear, but it cannot be considered in a vacuum. The alternative is to see the program keep trodding along, but do the wrong thing. In that case who cares if the program crashes instead? You're getting incorrect behaviour either way.
You’re writing this because you don’t have experience with programs that can never crash. A program that doesn’t crash doesn’t mean you never exit the program. The program can exit if you want it to. You just need to deliberately tell the program to exit. In golang if you do a division by zero, the program crashes. If you had sum types all divisions return an optional. Both paths of the optional must be handled by exhaustive matching so you must handle the case where the division yields a number or its undefined. If you want the program to exit when it is undefined you can do so. In golang the compiler doesn’t force you to handle both outcomes It just crashes. It’s the same with out of bounds access of an array.
Again real world testing doesn’t guarantee shit. A “complete type system” can be as extensive as dependent types like COQ or much simpler like rusts where you just have sum types and exhaustive pattern matching.
> Perhaps you can choose an example of where you wrote code in Go that produced a runtime error, show us your tests, and explain how the condition evaded your checks and balances?
Oh easy. we had a function that calculates velocity from a stream of input data. That’s (p2 - p1 / t2 - t1). Our integration tests and unit tests have dozens of tests that never yielded an error and we never saw an error in production for years. We switched to a new iot device that sometimes sent identical measurements to our system. Division by zero. We had a crash in production.
> I'm fascinated to learn how your code ran perfectly while under test but then blew up in production.
You’re inexperienced that’s why you’re fascinated. If you have formula involving velocity there an almost infinite amount of combinations that will never produce a runtime error and an infinite amount of parameter combinations that do. True full coverage that completely proves the function works with tests involves infinite tests. Better to prove the function works via proof with a simple extension to the type system. Sum types.
Again, they will catch your runtime errors if your behaviour is covered. If your behaviour isn't covered, then you're just shifting the problem to the program doing the wrong thing instead of crashing. That is not a win. It might even be worse! So, this doesn't matter in practice. Your purely academic view of the world doesn't work with the discussion taking place, I'm afraid.
> If you had a language that probably does not have runtime errors you don’t even need one test.
Go on.
Here, let's use your example:
> That’s (p2 - p1 / t2 - t1).
Traditionally, the calculation is (p2 - p1) / (t2 - t1). I'll assume you had a non-standard situation that necessitated a different formula, but this could have equally been a mistake. It wouldn't be too hard to forget the inner parentheses. We'll assume that divide by zero was already eliminated by the type system, but now show us how sum types would avoid someone from making that mistake.
Maybe you did need tests after all...
> You’re writing this because you don’t have experience with programs that can never crash.
Not so. I spend most of my days writing code in programming languages that do provide such guarantees. It is a cool party trick, but doesn't really matter at the end of the day because they still don't offer the expressiveness to ensure that the program does what is expected of it. I still have to write tests, and once I've written the necessary tests to ensure all the behaviour is correct, there is no practical way you can miss a crash situation.
> Our integration tests and unit tests have dozens of tests that never yielded an error and we never saw an error in production for years.
And had you avoided the crash you'd get erroneous results from the function instead. You're not really any farther ahead. You still need assurances that the function actually behaves correctly. And if you had those assurances, you'd have caught the divide by zero condition.
You're not going to convince me that a complete type system is academically better. I already agree with that. But absent a complete type system, you're going to have to resort to tests. Once you've written those tests, you're going to uncover the runtime errors anyway.
> Division by zero. We had a crash in production.
Your fuzz tests never tried passing in values that would lead to division by zero? For such a simple function that has many possible states that can lead to that condition, that seems completely inconceivable. Hell, I just tried it for fun and it found the issue in less than 100 tries! This must have been the time you were talking about where you deployed to production without running the tests?
But let me be try to be clear: The compiler warning you that you haven't considered a division by zero case does not mean you've handled it correctly. Absent a complete type system, you still need tests to ensure that the behaviour is consistent with expectations even in those edge cases. But with those tests, runtime errors can't go unnoticed anyway, so you didn't really need the type system.
> Better to prove the function works via proof
Agreed. Complete type systems are unquestionably better theoretically. Writing tests is tedious. But it remains that with the languages people actually use, even those with "advanced" type systems, you can't prove much. You have to fall back to testing, and at that point you're going to uncover the runtime errors too.
>But, again, they will catch your runtime errors if your behaviour is covered. If your behaviour isn't covered, then you're just shifting the problem to the program doing the wrong thing instead of crashing. That is not a win. It might even be worse! So, this doesn't matter in practice. Your purely academic view of the world doesn't work with the discussion taking place, I'm afraid.
So you're saying write tests that cover every possible behavior. Makes sense right? It's like saying write code without any bugs. Simple! You're not getting it. You can go run around telling people to write tests that eliminates 100% of bugs and that if you think that will eliminate all bugs from the world, well you're just not experienced.
>Go on. To continue with the original example, I have a function that tries to write to a file. If that fails, the caller is to try to write to a file on a different device. If the caller does anything else the program is broken with serious consequences and should not be shipped to production. Express that expectation using sum types. Hell, express it using any type construct available in popular languages. Good luck!
You can do this on rust. Literally it's the core of the rust sum type system. Good luck? Have you done basic programming with rust? Here's some psuedo code:
match getFile(fileName) {
Some(file) => do someghing
Error => match getFile2(fileName2) {
Some(file) => do something
Error => exit()
}
}
The above is psuedo code. The thing with the match operator is that the program DOES not compile if you do not handle both SOME and ERROR. For golang you can handle the Some and then it crashes if there's a problem. You aren't required to explicitly handle it.
>Not so. I spend most of my days writing code in programming languages that do provide such guarantees. It is a cool party trick, but doesn't really matter at the end of the day because they still don't offer the expressiveness to ensure that the program does what is expected of it. I still have to write tests, and once I've written the necessary tests to ensure all the behaviour is correct, there is no way you can miss a crash situation.
There is a way. You're just not getting it. there's about infinite ways to crash a program that has runtime errors.
>Your fuzz tests never tried passing in values that would lead to division by zero? For such a simple function that has many possible states that can lead to that condition, that seems inconceivable. Hell, I just tried it for fun and it found the issue in less than 100 tries! This must have been the time you were talking about where you deployed to production without running the tests?
Hell I used a programming language with no run time errors and I didn't write a single test. Amazing! There are tons of functions complex enough such that your fuzz test will miss it. Again we had this code working for years because we implictly assumed said devices will never pass duplicate data.
Also we don't write fuzz tests. We just do basic testing. Fuzz testing is something our start up doesn't have time for. We would prefer guarantees without the need of extra testing/work/time in this area.
>Traditionally, the calculation is (p2 - p1) / (t2 - t1). I'll assume you had a non-standard situation that necessitated a different formula, but does serve as a great example of how behaviour is your real concern. One could easily input the formula you gave where they expected (p2 - p1) / (t2 - t1) and sum types wouldn't care one bit.
Nope your formula is correct. I just assumed you were intelligent enough to know what I meant even though I didn't put in all the parenthesis (I'm typing on my phone afte rall). I thought wrong.
>Agreed. Complete type systems are cool. Writing tests is tedious. But we await your proof to my case for a realistic setting where one uses a typical production programming language. If all you have is silly half-measures that only cover a small number of cases, you're not really proving much. All you are doing is giving yourself a false sense of security.
Yes rust. Jesus. You're so inexperienced you don't even know when it's standing in front of your face. You don't need the borrow checker from rust. You only need the sum type. Then take the sum type apply it to division by zero and out of bounds array access and all IO calls. Boom that's it. No more runtime errors.
>There's a good way to change that. Let's see your code!
just look at elm man. Yuo don't even know what I'm talking about because you literally don't have experience. You want to see code that never crashes? Get some experience with Elm and you'll see why it never crashes and you'll see it doesn't take a "complete" type system to make it that way. Elms type system is woefully simplistic.
Rust is like 80% of the way there... the reason why people don't use it is lifetimes and the borrow checker and the complexity associated with it. Additionally rust left some holes so it can crash (like division by zero), but it has all the primitives needed to prevent it.
> Good luck? Have you done basic programming with rust?
Have you? I am sorry that the good luck did not shine upon you. With the types remaining intact, I modified the (pseudo)code:
match getFile(fileName) {
Some(file) => do someghing
Error => do something else unintended
}
It still compiles. You failed.
> The thing with the match operator is that the program DOES not compile if you do not handle both SOME and ERROR.
But as you come off your hubris, you can now see above it will compile even when you screw up the error handling. So you haven't gained anything. You still need to write tests to ensure that you are actually doing the right thing. And once you've ensured you are doing the right thing, how do you think crashes are going to go beyond that? Right. Not going to happen.
> Fuzz testing is something our start up doesn't have time for.
Testing, is testing, is testing. If you have time to write tests, you have time to write fuzz tests where they are appropriate. To throw a test out the window just because it has a slightly different execution model (as provided by the language; not something you have to build yourself) is bizarre. In fact, in your case it seems it could have supplanted the other tests you wrote, actually saving you time not only while writing the code, but also later when you had to waste time dealing with the issue. Time clearly isn't as constrained as you let on.
> For golang you can handle the Some and then it crashes if there's a problem. You aren't required to explicitly handle it.
Technically, in Go 'Some' should always be valid, regardless of whether or not there is an error. That is a fundamental feature of the Go language. Given (T, error), the values are not dependent. You don't need to explicitly handle the error. That is a huge misunderstanding. The same would not be true in Rust, which does consider them to be dependent by design, but Go is a completely different language. You can't think Go as being Rust with different syntax. There is a lot more to languages than the superficial.
>Have you? I am sorry that the good luck did not shine upon you. With the types remaining intact, I modified the (pseudo)code:
Your modification makes no sense. "do something else unintended" Wtf does that even mean? What are you doing? Why don't you spell it out? Because in golang you can do this:
v, err := getFile(fileName)
v.read()
And that's a fucking crash. You understand examples are used to illustrate a point right? And that your example shows you missed the point. Hey why don't I insert some psuedo code called "blow up the earth" in my program and that disproves every point ever made by anyone and I'm right. Genius.
>But as you come off your hubris, you can now see above it will compile even when you screw up the error handling.
Think of it like this. The point I'm illustrating is that in rust, you have to handle an error or the program won't compile. In go, you can forget to handle an error and your program will compile. You're going to have to write a bunch of tests to only POSSIBLY catch a missed error handling case. Understand? I don't think you do.
>Testing, is testing, is testing. If you have time to write tests, you have time to write fuzz tests where they are appropriate. To throw a test out the window just because it has a slightly different execution model (as provided by the language; not something you have to build yourself) is bizarre. In fact, in your case it seems it could have supplanted the other tests you wrote, actually saving you time not only while writing the code, but also later when you had to waste time dealing with the issue. Time clearly isn't as constrained as you let on.
It's not bizarre. It's again, lack of experience from your end. Why do I want to spend time writing generic test code that executes off of fuzzed input? I can write test specific code for specific use cases and that's much faster to write then attempting to write tests that work for generic cases.
Also how about not writing tests all together? I mean that's the best solution right? Honestly not to be insulting here, but it's not at all bizarre that you're not seeing how a better type system is better then tests that check for runtime errors. The root of it is that you're just stupid. Like why jump through a bunch of hoops and just call what I'm saying "bizarre" and just be straight with me. We're both mature right? If I think you're truthfully stupid and you think of me the same, just say it. We can take it. Why dance around it by calling my points "bizarre". No your points aren't "bizarre". They are stupid and wrong.
>Technically, in Go 'Some' should always be valid, regardless of whether or not there is an error.
That's why go is bad. You don't need to handle an error if err is not nil. V will be a nil here. And you know what's the only thing you can do with a nil besides check if it's a nil? Crash the program. Literally.
With rust, you can do this:
match getFile(fileName) {
Some(file) => do someghing
Error => {}
}
and do nothing. Which is the same effect as golang. But rust at least tells you to explicitly watch for it.
>You can't think Go as being Rust with different syntax. There is a lot more to languages than the superficial.
It's not about what I think of the language. It's about the intention of the designers. Go was made for people with not much experience. Straight from the horses mouth. Pike is saying he designed it for you.
>That is a fundamental feature of the Go language.
I think you're kind of not getting it. Seriously like the feature of golang is to allow you to unintentionally crash the program and you think that's a good thing?
v, err := getFile(fileName)
doSomething(v)
Take some time to think here. I know you think you're smart, but you need to hit the brakes for a second. Think: What is the purpose of the above code? If err actually is not a nil, and v ends up being a nil. What is the purpose of this type of logic to even exist? Is it for v to crash somewhere in doSomething? Are you saying that a fundamental feature for golang to crash somewhere inside doSomething?
Really think about this. You literally said it's a feature for golang to not handle an actual error and for v to still be "valid." So if err is not nil, v is a nil. What happens here? You think this is a feature? Or are you just not thinking straight? Just pause for a second.
Another thing to help you along: You know the inventor of the null/nil value called it his billion dollar mistake right? Have you thought about why it's a huge mistake? Here's a hint: You can't do anything with a null/nil except check if it's a null or crash the program by using it improperly. The existence of a nil/null signifies the existence of feature that you can only use to crash your program unintentionally.
Why doesn't elm crash? Why is rust safer then most languages? A big part of the reason is both languages don't have nulls or nils. And that doesn't have anything to do with a "complete" type system.
Hopefully you get it now. If not I can't help you.
The earlier comment already spelled it out. Hence why it wished you luck as we knew you would not be able to deliver. Yet right on cue you hilariously tried anyway.
I take that you haven't actually read anything in this discussion? If you have read it, you haven't understood it. Slow down, comprehend before posting. It seems you've become so fixated on telling us how sum types work – something we understood decades ago – that you have missed the forest for the trees.
> Why do I want to spend time writing generic test code that executes off of fuzzed input?
Remember when you mistakenly wrote (p2 - p1 / t2 - t1)? That's why. A complete type system would negate the need for testing there, but if all you have is sum types... There is no difference between a fuzz test and any other test other than the tooling will feed it 'arbitrary' inputs. It is not like they take more time to write or something. Testing is testing is testing.
In fact, it took me like ten seconds to write the fuzz test for your function when I tried it out earlier. This time argument is disconnected from reality. You have 10 seconds to spare to ensure correctness, especially when you admitted to writing a bunch of useless tests instead. One good test would have gone further and saved you time.
> I think you're kind of not getting it.
Let's change that. Consider your code:
v, err := getFile(fileName)
doSomething(v)
Presumably your requirements dictate that your code must do something when getFile fails, so you are obviously going to write a test for that scenario. How do you envision that potential crash condition evading the test? The CPU steps through until getFile fails, then checks if you are running a test and if it so it invents a valid file handle, but if it notices you are in production it returns a corrupt file handle and then crashes? That doesn't make any sense. What does make sense to you that explains how your code will pass tests but fail in production?
If what you are struggling to say is that you have no such requirement to deal with the failure so it is unspecified behaviour, and thus you didn't feel the need to write a test for it, all you can do with sum types, to keep the compiler happy, is purposefully panic. It is unspecified behaviour. Anything else but crashing would be nonsensical – something that is true even if it were written in Rust. Is the source of the panic significant?
> Seriously like the feature of golang is to allow you to unintentionally crash the program and you think that's a good thing?
It doesn't matter in practice. When the program is going to do the wrong thing, it makes little difference how it goes about doing it wrong. But if you really have to choose, crashing is better than silently corrupting data, yes. The latter is far more scary.
However, better is to ensure that your program doesn't do the wrong thing in the first place. If you have a complete type system, that's you best bet. But that isn't realistic. No language you are going to encounter in the real world has that. Meaning, prepare to learn how to write tests. They aren't easy to do right, but you're going to have to do it anyway because without a complete type system you have no other choice.
Anything else is running on hopes and prayers. If you honestly believe that hope and prayer is sufficient, then why are you so worried about crashing?
>Presumably your requirements dictate that your code must do something when getFile fails, so you are obviously going to write a test for that scenario. How do you envision that potential crash condition evading the test? The CPU steps through until getFile fails, then checks if you are running a test and if it so it invents a valid file handle, but if it notices you are in production it returns a corrupt file handle and then crashes? That doesn't make any sense. What does make sense to you that explains how your code will pass tests but fail in production?
Sigh. You said it was a feature. You said v being nil was a feature lol. Now you want to test it to see if it crashes? I'm saying it should be tested, but YOU said it was a feature for golang to always return a valid v. Now I know you're just not aware of what you're talking about.
>If what you are struggling to say is that you have no such requirement to deal with the failure so it is unspecified behaviour, and thus you didn't feel the need to write a test for it, all you can do with sum types, to keep the compiler happy, is purposefully panic. It is unspecified behaviour. Anything else but crashing would be nonsensical – something that is true even if it were written in Rust. Is the source of the panic significant?
I don't need to specify the difference here. You're just being stubborn. You already know that in rust you need to explictly panic vs. golang you can panic mistakenly with a hidden nil. This discussion is over.
I would recommend getting started with lazyvim (lazyvim.org). Once you're comfortable with the editor, you can change the config to kickstart.nvim and start customizing it to your liking. That's what I did and I have no regrets. LazyVim allowed me to switch without sacrificing productivity. I was on it for a year before I decided to make my own config
Don’t know about you, but personally I want the extensions I create to be available widely. The fact that vs code market place is used as an easy place for me to distribute it only to limit the reach based on the business needs of Microsoft sure does feel like being embraced extended in the attempt of extinguishing usecases that I do in fact support.
Can’t fault cursor for letting people install extensions when most of those, if not all of those, developers want their extensions on cursor.
This is about closed-source extensions created by Microsoft, and those always had strings attached which Cursor apparently ignored.
I would rather ask Cursor why they decided to fork VSCode when they could simply have written yet another VSCode extension to provide the same functionality. Seems shady AF tbh.
Doesn’t Microsoft handicap extensions by not giving them the full access that co-pilot gets? You’d be crazy to compete when the other side literally owns the platform.
They couldn't have done and it gets tiresome to repeat the technical limitations on extensions for vscode again and again (which don't apply to Microsoft owned extensions like Github Copilot) when you can google it yourself.