I mean, all types are "entirely fictitious" as far as the computer is concerned. Yeah they usually have fewer layers than JS does, but that's a pretty arbitrary line to draw.
Curious what your issue was with duck-typing. Were you effectively looking to create ADTs that are required to go through a specific step-by-step process, not simply 'look like' the thing that was expected?
This isn't typical application code, but either proof-of-concept or library code. What you'd instead get is the type error, which in turn would explain itself well enough- that it expected a certain type, and got a different type.
The reason you wouldn't want a cross-compiler for that other language is that there are true semantic differences between languages, and many languages simply cannot fully support the JS runtime- and if your primary application is still in Typescript, trying to cross-compile for a single feature is downright ridiculous.
> The invention, support and defense of Typescript baffles me. It feels like an intensely wasteful work-around for poorly written interpreter error messages concocted by comp-sci grads who think compiled languages are superior to interpreted ones in all situations and they want to bring this wisdom to developers of loosely typed languages.
I sincerely don't think statically typed languages are superior, but I'd argue a large part of the increase in quality over the last few years of the ecosystem is due in large part to Typescript.
Is it going to fix all, or even a majority of the issues? Probably not. But if it can improve upon the situation I don't see why we'd make perfect the enemy of good.
Go's type system is inferior to Typescript's in every possible way. About the only saving grace it has is that it didn't start out in a non-typesafe ecosystem, but most of those issues have been alleviated in Typescript for years.
At this point, folks are seeing how far they can push the Typescript type system because it's capable of expressing so, so much more with its types than is seen typically(including in most other languages).
Taking a look at it now, and how it interacts with Enhancer for Youtube.
The one thing I'm absolutely desperate for, is a fix to Youtube's Watch Later playlist issues.
If you ever hit maximum on it, it seems permanently broken afterward to not delete watched videos- which means the only way to delete videos is manually, behind a 3-dot menu per video. Since the playlist max size is 5000, that'd be a minimum 10,000 clicks, and since the 3 dot menu only shows up once you're over a video, a certain level of hunting too.
I tried to make an extension for this once, but bungled it pretty bad so it'll take another effort sometime. Youtube's my primary content source outside of games, so for me it hurts pretty bad.
My pet peeve is that if you start playing a video by clicking on it in the watch later playlist it will start wherever you left off, but then if you let it proceed to the next video it will start at the beginning of that one, forever erasing your watch position for that video.
In general the saving of watch position is very frustrating on YouTube. There are a lot of bugs. They need an explicit way to see exactly which parts you've watched.
Has anyone made a "watch later" queue that is site-agnostic? I'd love to be able to add Twitter videos, Spotify podcasts, YouTube clips, etc to a single "watch later" queue.
Honest question: Do you ever actually watch them later? I've been bookmarking things on the internet to Read Later (TM) for 26 years. I might bookmark multiple things in a day. The Later never comes - and often the link rots in just a decade or two.
I've recently begun using Ctrl-W to mark items to Read Later. It saves some disk space at the very least, and frustration years down the line at the very most.
Yes, I watch about half of them. Usually while doing the dishes or working out. Mostly listening, as I usually save interviews or lectures or podcasts. I never read the things I bookmark for later reading, but I have extra time to listen to things.
might just consider caching them to a thrash-drive with yt-dlp and one of those browser-exntensions that caches a webpage for offline use; then watch later without linkrot, ect
can even throw that behing something as simple as darkhttp and serve it to your tablets easier too
but of course the downside is the required regular spring cleaning
having an AIO system for that would be pretty nice though
Linkrot isn't that big of an issue for the stuff I save. I'm fine watching/listening on the web, I just wish there was a way to make a playlist that works over multiple sites. Really it should be a browser feature, part of the bookmarks manager, if browsers were still innovating.
a) Browse when I have a few minutes, and add interesting videos to Watch Later
b) Watch them in the evening when my family has gone to bed.
I don't watch everything the same day, so over time it builds up. Sometimes I have more time, so I catch up then. I try to keep it less than 50 items, and if it ever goes over I'll prune it.
I rarely watch movies or TV shows - I watch YouTube.
> I rarely watch movies or TV shows - I watch YouTube.
Same here. For all its faults—the search function is my personal peeve—it has really turned into a fantastic platform. By allowing anyone to upload videos of any length, giving those videos permanent URLs, and enabling people to make money from their videos, they have encouraged a wealth of content creation on every topic under the sun.
I wish YouTube had a dozen strong competitors, though. Too many valuable eggs are being entrusted to that one basket.
I would love better playlist controls for Youtube. I do a lot of playlist shaping and even their web interface is broken -- for instance, if you have a playlist with 100 items on it and you drag-n-drop to re-order, the visual order doesn't match the saved playlist order. I then re-load the playlist and have to scroll back down.
I'd also like to shuffle certain playlists, not in playback, but the way it's stored.
I cant fathom why you'd let that list get so long... I tend to max it out at about a dozen.
but
also any video that you mark as watch later, but then gets pulled... its hidden and messes with the play list order. you have to go find the menu option that shows hidden videos so you can remove them from the list manually before the list will start to behave
There is a "Removed watched videos" option in the three-dot-menu for the playlist itself on desktop at least. I have to do this every so often, and this is a very welcome feature as I used to do it as you describe.
Do you mean that NULL <> NULL and NULL infects boolean logic?
NULL is always an awkward thing to deal with - how you want to handle it depends on the specific thing you're trying to accomplish. I'd probably prefer it if NULL equaled NULL when dealing with where conditions but it actually makes join evaluations a lot cleaner - if NULL equaled NULL then joining on columns with nulls would get really weird.
At the end of the day IS NULL and IS DISTINCT FROM/IS NOT DISTINCT FROM exist so you can handle cases where it'd be weird.
I think that's just a question on syntactic sugaring here - so, concretely, what would that mean for comparison operators? If I wanted to `id = id` and both were nullable would I need to express that as two layers of statements where I tried to unwrap both sides first or would we have a maybe vs maybe comparison operator - if we had such an operator what would it do in this case?
You’d have to unwrap, usually with convenient mechanism for it —pattern matching
The problem is that id = id is fundamentally incorrect for a nullable column. You should have done id is not null and id = id. And you shouldn’t have been allowed to do the first anyways, because nothing good can come of it (there is no sane semantics to stuffing a trinary logic into a boolean algebra, and SQL chooses one of the many insane options, leading to both false positive and false negative matches depending.) the only correct answer is not to do that.
I can understand how that would make things more explicit - but given how common nullability is in the realm of databases I think it'd be a bad idea to force that much syntax in a situation where id=id is essentially what we want to discuss - especially since columns becoming potentially null is so trivial to achieve (even when impossible due to model constraints) as soon as you start throwing left joins in the mix.
Sometimes you really want explicit, rather than dealing with the errors caused by implicitness. And with a language that has proper support for things like Maybe, there isn't that much syntax.
It's true that you have to adopt a completely different language, but when that language saves you from potentially expensive bugs, it becomes appealing.
I think it handles all the 3VL problems I've encountered in SQL, but that doesn't mean it handles all possible 3VL problems. It also might not make any sense to anyone except me.
It's been a while since relational algebra so I don't feel confident saying "Yes" or "No" (I guess you could say my reply is Null) - but that seems like a really good base approach - especially having a state for being uncertain whether something is nullable or not... having an operator embeded fallback approach also seems to be a lot more usable for the developer.
Also, this is an aside, but is your thing named after Snake Plissken?
Yeah, kind of. I have seen Escape From New York but I don't really remember it. I was more aware of the character via the reference/homage in Metal Gear Solid 2. In any case, I don't love the name but the obvious choice (Racquel) was already taken and "Plisqin" had zero Google results so I said "meh, good enough."
Python will let you use float division on integers. Compiled type languages won't do that. This would be solved by using a double data type. But python doesn't have it.
You prooobably don't want to use doubles with financial data. Even in Java. Go for BigDecimal instead, for arbitrary precision instead of floating-point math.
And if you're doing that, python has the Decimal class for the same thing.
Look, I like static type systems, but not all type systems are created equal, and some(with the easiest example being Go) are downright awful for helping encode business logic, forcing you to write immense amounts of code just to work around their awful type system decisions, code that often introduces bugs because of those issues.
We have services in Python and C# at $dayjob, and my experience is that Python has mostly left C# behind here - what is something you can express in the C# type system that MyPy cannot statically check?
Conversely, I find myself constrained by C#'s typesystem not having features now widely popular from Rust and Typescript and available in modern Python: const generics / literals, protocols/structural interfaces and matching over algebraic datatypes, to name a few examples.
Was bewildered when reading this message. How come? Python and TypeScript by definition don't have a concept of const generics the way it applies to C++ templates or Rust.
Nor "matching over algebraic datatypes" made any sense - sure sounds slightly below average fancy but comes down to just using C# pattern matching effectively, which the author may have never done. But then it struck me "structural interfaces sure sounds familiar", I go check the pinned repositories in the github profile and it all made sense immediately - the pinned ones are written in Go, which explains the author's woes with confidently navigating something more sophisticated.
> Python and TypeScript by definition don't have a concept of const generics the way it applies to C++ templates or Rust.
Can you help guide me where I'm misunderstanding the type system aspect of const generics that's missing in Python? What I meant was that in Python I can say something like this:
import typing as t
class FooEater[NUM_FOOS: int]:
def eat_foo(self, num_foos: NUM_FOOS):
print("nomnom")
one_foo = FooEater[t.Literal[1]]()
one_foo.eat_foo(2) # type error, NUM_FOOs for one_foo only allows literal '1'
And a PEP695-compatible typechecker will error at build time, saying I can't call `eat_foo` with `2`, because it's constrained to only allow the value `1`.
I admit to not being a type system specialist, but at least as I understand Rust's "const generics" the type system feature is: "Things can be generic over constant values". Isn't that the same as what Python supports?
Sorry - can you put the snark aside and answer the question then, it seems given my lack of understanding here as a mere Go simpleton it should be trivial for you.
The question I responded to said: "Better static analysis, for one."
I asked: "What is something you can express in the C# type system that MyPy cannot statically check?"
Can you provide some examples where C#'s type system can express something that modern well-typed Python cannot type-check?
I didn't say anything about financial analysis. But static typing is a good defense mechanism against type errors at runtime (I don't think anyone would argue against that). When you're running a financial services product, the cost of a type error in production can be dramatically higher than in non-financial code. Speaking from firsthand experience.
I don't think it's specific to financial services. He just meant that financial services is an area where you really don't want bugs! And one of the easiest ways to eliminate entire classes of bugs is to use static typing.
Pick something. I don't care. Let's say failure for reasons of having no return statement in a function that declares itself to return something. If you could flip a switch to see that code still compile somehow, knowing that the program is not correct, would you deploy it to production?
> Go literally does not warn you until it hits the error at runtime for these exceptions.
True, but only because the Go compiler isn't very smart. It trades having a simpler compiler for allowing some programmer faults to not be caught until runtime. But if there was such a thing as an ideal Go compiler, those exceptions would be caught at compile time.
When it comes to exceptions, the fault is in the code itself, unlike errors where the fault is external to the program. Theoretically, those faults could be found before runtime. But it is a really hard problem to solve; hence why we accept exceptions as a practical tradeoff. We are just engineers at the end of the day.
Except we could just treat them the same, and we could have a type system that makes that possible. Multiple languages before Go had a solution to this, that could've been used. Or, it could've written said sufficiently advanced compiler itself.
We could, but we learned from those attempts that came before Go that it is a bad idea. There is good reason why the languages newer than Go, including Rust, also keep a clear division between errors and exceptions.
We already lived through the suffering. The new age of recognizing that exceptions and errors are in no way the same thing and should not be treated as such is a breath of fresh air.
> why the languages newer than Go, including Rust, also keep a clear division between errors and exceptions.
There are also languages older than Go that make this distinction. Java for example. Like Rust (and in contrast to Go) they even have syntax for convenience, and the compiler checks that you handle them.
You know how you can immediately spot old Java APIs and code? The one that was designed and written while we lived through the suffering? Whenever you encounter checked exceptions. Turns out there is no (or even negative) value in this rather arbitrary separation.
Obviously every language can make that distinction. As far as the computer is concerned, errors are no different than email addresses and phone numbers, which are equally representable in every language. Even Java could have errors.
With respect to the bits and bites, exceptions only stand out in that they carry stack trace information. That is useless for email address, phone numbers, and errors. A hard drive crash doesn't happen at line 32. It happens in the hard drive! But knowing that the fault lies at line 32 is very useful for resolving programmer mistakes. If you get a divide by zero exception at line 32, then you know that you missed a conditional on line 31. Exceptions are compiler errors that the compiler missed.
By convention, Java does not acknowledge the existence of errors. It believes that every fault is a programmer mistake, with some programming mistakes needing to be explicitly checked for some reason. Which, of course, questions why you let programmer mistakes ship given that you know that there is a programmer mistake in your code? That doesn't make any sense. But as you point out, everyone these days agrees that idea was nonsensical.
> Java does not acknowledge the existence of errors. It believes that every fault is a programmer mistake
Oh, you're distracted by the stack traces, of which you have a strong opinion, but it's exactly the opposite. What modern Java code does is (in the wake of Exceptional C++) it accepts failure as a given. It does not matter what's the _cause_ of a failure, be it the programmer's fault or failure of a pre-dependend system. It's the job of the dev to ensure that the process can never leave a defined state. And the way to do that is to write exception safe code, and not to handle-all-errors (TM).
Well, there is nothing else. Capturing the stack in a value along with some metadata is all that there is to an exception. Were you wanting me to say something about the weather?
> It does not matter what's the _cause_ of a failure
Except when it does. Let's say the failure is that the user is a child when your requirements demand that they are an adult. age < 18, which produces an error state, doesn't create, let alone raise an exception. Hilariously, you have to resort to Go-style error handling:
if (age < 18) {
// Do something with the failure.
// Are we writing Go now? I thought this was Java.
}
> It's the job of the dev to ensure that the process can never leave a defined state.
If the developer ensures that the process doesn't leave a defined state, then this discussion is moot. You will never encounter an exception. Exceptions are raised when the process enters an undefined state.
> Exceptions are raised when the process enters an undefined state.
Exceptions are raised _before_ a process enters an undefined state. A thread that's unrolling the stack is still in a well defined state.
> age < 18
In real code, the 18 is probably coming from the DB, is the result of resolving the user's location and happens in 5 nested layers of thread pools, logging and transaction management. None of those layers care about age or height of the user. If it's an external API, there is a layer on top that converts some useful exceptions into error codes for the JSON response. Also, there's a catch-all the maps the rest to 500. If it's an internal API, the exception might be serialized in full, to preserve the stack trace across systems.
> Exceptions are raised _before_ a process enters an undefined state.
There is no exception to raise if the state is defined. Why bother? If you know how to divide by zero, just do it! Except you probably don't know how to divide by zero, so you have found yourself in an undefined state and need to bail.
> If it's an external API, there is a layer on top that converts some useful exceptions into error codes for the JSON response.
So you have an exception, that you convert into an error, that you then (on the Java client) handle as if you were writing Go to turn it back into an exception...? I take that you didn't take a moment to read what you wrote? You must have misspoke as that would be the dumbest idea ever.
Of course. And, sadly, one of those systems I once helped with was built on Javascript, which made the whole thing even sillier.
There you had an exception, resorting to as if Go to convert it to an error, handled as if Go to convert back into an exception, and then, when the exception was caught, it was back to 'writing Go' again to figure what the exception was! At least Java does a little better there, I'll give it that.
It is completely ridiculous. I guess that's what happens when you let bootcamp completionists design software.
If a language really wants to embrace the idea that errors and exceptions are the same thing, fine. Maybe it would even prove to be a good idea. But then we should expect that language to actually embrace the idea. This "errors are exceptions, but only sometimes, because we can't figure out how to represent most errors as exceptions" that we see in Java and languages that have taken a similar path is bizarre – and for developers using the language, painful. That has proven to be a bad idea.
They could. The halting problem is solved (well, worked around) by adding a complete type system, which the compiler is free to implement.
But with respect to this discussion the compiler does not need to solve the halting problem. It can assume the program always halts. It makes no difference if the program actually halts or not.
> If customers think this is a feature and not a bug, then I have a very different understanding about what serverless/FaaS is meant to be used for. My division is pretty much only looking at edge networking scenarios. Can I redirect you to a CDN asset in Boston instead of going clear across the country to us-west-1? We would definitely NOT run Lamba out of us-west-1 for this work.
I'm not sure how you're misunderstanding, but why would it go across the country when it's guaranteed to run from the same parent? Just deploy the app in the region you want, and now its Flame pools will be deployed in the same region.
If you want to switch the region it runs in, you can also easily just contact the other cluster to tell it to pick up the work.
Yes, I understand, I do distributed systems for a living, after all. But if you keep adding stipulations without actually describing the problem you're not actually looking for an answer, you're looking to be contrarian.