Isaac Harris-Holt

Isaac Harris-Holt

Subscribe for programming content and a British accent!

Astro for Impatient Devs

Astro for Impatient Devs

Gleam for Impatient Devs

Gleam for Impatient Devs

Zig for Impatient Devs

Zig for Impatient Devs

HTMX for Impatient Devs

HTMX for Impatient Devs

Go for Impatient Devs

Go for Impatient Devs

Python for Impatient Devs

Python for Impatient Devs

Пікірлер

  • @iKyroja
    @iKyroja7 минут бұрын

    It ain't typesafe if it is compiled to JS

  • @Hersatz
    @Hersatz3 сағат бұрын

    I never understood the reason to catch errors. If there is an error in the system, the code shouldn't catch it and handle it in some weird workaround ways. The code should be fixed so that the error cannot occur anymore. When is a try catch actually truly useful and not due to bad code?

  • @IsaacHarrisHolt
    @IsaacHarrisHoltСағат бұрын

    There are always things that can go wrong that are outside of your control. You might be trying to open a file that doesn't exist, or your internet connection might drop out in the middle of a HTTP request, or a million other things. You can't prevent every error

  • @dayvie9517
    @dayvie951722 сағат бұрын

    Have you ever heard of logging? 😂

  • @IsaacHarrisHolt
    @IsaacHarrisHolt22 сағат бұрын

    Sure, what about it? Logging complements good error handling - it doesn't replace it.

  • @Greenmarty
    @Greenmarty2 күн бұрын

    I heard Crowdstrike has been experimenting with offensive programing lately ...

  • @IsaacHarrisHolt
    @IsaacHarrisHolt2 күн бұрын

    😳

  • @user-wz7eo9on4n
    @user-wz7eo9on4n3 күн бұрын

    I'm a newbie though. But I'm wondering, can we just combine "error as value" & "exceptions"? 1. compiler forces we to handle all of the errors ( for code readable & reliable, no need to debug in runtime ) 2. we can use try...catch... in any position ( for convenience just like scripting ) 3. no need something like `?` in rust, to convert error types ( for convenience just like scripting ) some draft example: // define error enums error ApiError { NotFound, TimeOut, BadRequest, } error FileError { NotFound, NoPermission, Locked, } // merge errors into one error WriteError { ..ApiError, .. FileError, } // interfaces fn getData(url: String) throws ApiError; fn getFile(path: String) throws FileError; fn writeData2File(url: String, path: String) throws WriteError { let data = getData(url); let file = getFile(path); // writing data to file... } fn main() { try { // some operations may throw errors writeData2File(url, path); // some operations may throw errors } catch e { ApiError => { // error handling }, FileError => { // error handling }, _ => // handle all of other errors } } // or just try { } catch e { // cover all types of errors }

  • @IsaacHarrisHolt
    @IsaacHarrisHolt3 күн бұрын

    This looks fine in theory, but could have some of the same issues. You'd be better off speaking to some language designers :)

  • @kartickchakraborty9135
    @kartickchakraborty91354 күн бұрын

    HI Sir, I'm Kartick from Kolkata, India.001) Can I run Python on Android Studio to develop any kind of apps or games for Android and see the Live Preview of how it looks like on Android Phone when it will be installed? 002) Will I be able to freelance as a Mobile App Developer using Python on Upwork or Fiverr Site?

  • @IsaacHarrisHolt
    @IsaacHarrisHolt4 күн бұрын

    I don't know if you can use it in Android Studio, but you can see a live preview like I showed in the video. As for using it for Fiver work, it'll depend on what the work is. At the time of this video, BeeWare was still very early, and not really suitable for production software. I don't know if that's changed.

  • @loganhodgsn
    @loganhodgsn4 күн бұрын

    It depends on the error. If you bubble an error up the stack, more and more tracing data will have to be stored and passed around. On the other hand, panics allow you to perform an autopsy on the stack without incurring any runtime penalties (because all panics are assumed to never occur, because if they do, it's lights-out for the program anyways).

  • @IsaacHarrisHolt
    @IsaacHarrisHolt4 күн бұрын

    Yes, I agree, but panics and exceptions aren't the same, which I think is something a lot of people seem to miss. And adding that context is what Snag is useful for

  • @3x10.8_ms
    @3x10.8_ms4 күн бұрын

    i don't like indent of 2 spaces, how do i change it to tab size 4? in gleam, it is automatically on save formatting to 2 spaces

  • @IsaacHarrisHolt
    @IsaacHarrisHolt4 күн бұрын

    That's just the way the Gleam formatter is

  • @3x10.8_ms
    @3x10.8_ms4 күн бұрын

    @@IsaacHarrisHolt well that's a bad news

  • @IsaacHarrisHolt
    @IsaacHarrisHolt4 күн бұрын

    You'll get used to it as you write more Gleam :)

  • @mh-tr5fb
    @mh-tr5fb4 күн бұрын

    pardon me, the pink smiley star... is it for a language?

  • @IsaacHarrisHolt
    @IsaacHarrisHolt4 күн бұрын

    It's Gleam's logo!

  • @mh-tr5fb
    @mh-tr5fb3 күн бұрын

    @@IsaacHarrisHolt thank you.

  • @SillySussySally
    @SillySussySally4 күн бұрын

    This looks unreadable af 😢

  • @IsaacHarrisHolt
    @IsaacHarrisHolt4 күн бұрын

    Depends what you're used to! And syntax is something you get used to very quickly

  • @NickCombs
    @NickCombs4 күн бұрын

    More libraries for syntactic sugar... nah I'll pass. I'm good with wrapping functions in try-catch

  • @IsaacHarrisHolt
    @IsaacHarrisHolt4 күн бұрын

    No libraries here (except Snag), all pure Gleam!

  • @TheArchCoder
    @TheArchCoder4 күн бұрын

    When i run "maturin init" it says error: unrecognized subcommand 'init' I am using kubuntu. Any idea whats going on?

  • @IsaacHarrisHolt
    @IsaacHarrisHolt4 күн бұрын

    The command has changed to `maturin new`!

  • @TheArchCoder
    @TheArchCoder4 күн бұрын

    @@IsaacHarrisHolt Still says error: unrecognized subcommand 'new' Maturin version is 1.3.2 This error is really weird, Also you replied INSTANTLY! What? Dw if you dont know what this is ill switch to c/c++ or maybe go. Just reply "idk" or smth atleast to tell me. Maturin help returns: Build and publish crates with pyo3, rust-cpython and cffi bindings as well as rust binaries as python packages Usage: maturin <COMMAND> Commands: build Build the crate into python packages list-python Search and list the available python installations develop Install the crate as module in the current virtualenv sdist Build only a source distribution (sdist) without compiling help Print this message or the help of the given subcommand(s) Options: -h, --help Print help -V, --version Print version

  • @IsaacHarrisHolt
    @IsaacHarrisHolt4 күн бұрын

    Ah it's `maturin new` in 1.7.0, which is the latest version. I'd probably recommend not using Go bindings - while I absolutely love Go, the interop with Python is a massive pain in the ass to get set up correctly, and the types don't map that well.

  • @TheArchCoder
    @TheArchCoder4 күн бұрын

    @@IsaacHarrisHolt Oh, I think i know why that happened and it didint the latest version. Thanks man! Edit: Yeah its fixed, it was caused by a number things actually mainly due to the fact that i use linux and pip is a bit different here. I installed 2 versions, 1. globally using sudo apt install python3-maturin which was outdated. Couldn't use pip to install it globally because of Linux. 2. The version in a venv environment. Since i could use pip, i did pip install maturin which gave me the latest version. But running maturin in the terminal still gave me the outdated version. Thanks!

  • @TheArchCoder
    @TheArchCoder4 күн бұрын

    Ran into another error (i ran into this previously but the following was something i thought was a fix but that gave me the same error.) During maturin develop: 🔗 Found pyo3 bindings ⚠ Warning: Failed to determine python platform 💥 maturin failed Caused by: Unsupported Python interpreter for cross-compilation: /home/thearchcoder/Documents/Programming/Python/Trilent/venv/bin/python; supported interpreters are pypy, graalpy, and python (cpython) Ill just open a github issue for this. I searched on google, No fix. Caused by the fact its looking in the venv directory and seeing the link, that link is just a shortcut to the actual python interprator

  • @Mistoffeleess
    @Mistoffeleess5 күн бұрын

    It's irony that JS is getting similar to Java and vise versa.

  • @IsaacHarrisHolt
    @IsaacHarrisHolt5 күн бұрын

    Yeah it's definitely interesting. Hopefully it'll get the good bits of Java and not the bad ones

  • @smokingant
    @smokingant5 күн бұрын

    Issac is to Gleam what Akademiks is to Drake

  • @IsaacHarrisHolt
    @IsaacHarrisHolt5 күн бұрын

    I'm hoping this is a good thing 😅

  • @ahuman32478
    @ahuman32478Күн бұрын

    Isaac is to Gleam what NoBoilerplate is to Rust

  • @luisotero5123
    @luisotero51235 күн бұрын

    Is Gleam good for scripting and test automation? I use Python and love Python but I do miss proper static typing. I could use TypeScript but unsure

  • @IsaacHarrisHolt
    @IsaacHarrisHolt5 күн бұрын

    It's not intended to be a scripting language, but you can run parts of modules if they have a main function. However, like Rust and other similar languages, you do need the project scaffold each time

  • @cosmochaosmaker
    @cosmochaosmaker5 күн бұрын

    Using errors as values instead of exceptions feels like trying to reinvent the wheel, but using triangles instead. 🤷‍♂️ Exception handling is crucial for creating robust and maintainable applications and libraries, particularly in environments that have evolved over many years or decades. In such environments, development errors are more likely, especially when incorporating dynamically linked third-party code at runtime. Exceptions provide a structured and standardized way to handle unforeseen situations that can arise in these complex systems. While using errors as values can be appropriate in specific scenarios, such as in performance-critical code that has been thoroughly tested and is unlikely to encounter unexpected issues, it is not a one-size-fits-all solution. Exceptions generally offer a more reliable and maintainable approach for the majority of applications, enabling better error propagation and handling.

  • @IsaacHarrisHolt
    @IsaacHarrisHolt5 күн бұрын

    I agree with some points here, but I disagree with exceptions handling being more readable. If I have to go function hunting to find where a particular exception is coming from, I'm having a bad time. Also, in most languages, you lose type safety when dealing with exceptions, which negatively impacts your ability to correctly identify and handle errors as they arise, leaving you playing catch up while your software's in production.

  • @cosmochaosmaker
    @cosmochaosmaker4 күн бұрын

    @@IsaacHarrisHolt That is mostly true, but what I wanted to say was that a hybrid approach will get the desired result. Combine exceptions and error return types for robust error handling. Use exceptions for critical infrastructure and initialization errors that require halting the system, ensuring immediate resolution and preventing instability. Employ error return types for business logic and non-critical errors, explicitly managing and propagating them to enhance type safety and predictability. This hybrid approach balances the concise control flow of exceptions with the explicit error management of return types, optimizing performance and reducing complexity. Clearly define boundaries for each method, document guidelines, ensure consistent handling, and implement thorough testing. This strategy supports maintainability, type safety, and efficient error management in complex systems.

  • @IsaacHarrisHolt
    @IsaacHarrisHolt4 күн бұрын

    That's basically what Gleam does with a panic. It's not an exception, because you can't catch it, so it's only used to stop the program. I wouldn't say that's a hybrid model.

  • @Tuniwutzi
    @Tuniwutzi4 күн бұрын

    @@IsaacHarrisHolt I don't see how the erros as values are solving the "function hunting" problem. You say in the video that most of the time, you'll just be propagating errors up to the caller, which I agree with. But then, a few layers up, when you actually handle the error - how do you know where it originated? You have to go function hunting as well, no? Maybe it'll be a specific type that you can associate with a particular function. But then, if you call multiple different functions, how do you propagate all of their different error types upwards? There would have to be some common error type which can hold all of the specific functions error types. And then we're back at the question: how do you find the function this error came from? This weakens the type safety argument as well. With errors as values, if a function wants to propagate errors up, it'll need to use a common type for all errors that could occur within it. In many exception-based languages there is a common base class/interface that's enforced for all exceptions. Is there really such a big difference in type safety?

  • @IsaacHarrisHolt
    @IsaacHarrisHolt4 күн бұрын

    There's a huge difference in type safety. It's unlikely that you'll just have a single error type that everything uses - if you look at the stdlib, you'll see that the functions there generally have their own special error types, and that's generally encouraged. I see your point about the function hunting argument, but you also know that the functions above will HAVE to handle the error in some way, even if that is just returning it up the call stack. With exceptions you don't get that guarantee. When you're writing a function that throws an exception, you're making the assumption that everyone who then calls that function will handle the exception somewhere and it won't crash the program. With errors as values, you're FORCING callers to handle the error somewhere.

  • @chiubaca
    @chiubaca6 күн бұрын

    I wanna learn gleam cos the star looks cute

  • @IsaacHarrisHolt
    @IsaacHarrisHolt6 күн бұрын

    Lucy is adorable and we love her

  • @chiubaca
    @chiubaca6 күн бұрын

    @@IsaacHarrisHolt 🤩

  • @bjornericcom
    @bjornericcom6 күн бұрын

    Been wanting to check out Gleam more, so happy I found this channel, thanks! :)

  • @IsaacHarrisHolt
    @IsaacHarrisHolt6 күн бұрын

    Awesome! Let me know how you find it :)

  • @Bwmat
    @Bwmat7 күн бұрын

    So, does anyone who uses C++ & wants their process to survive new failing actually do this in practice?

  • @IsaacHarrisHolt
    @IsaacHarrisHolt6 күн бұрын

    I'm not sure I understand the question

  • @Bwmat
    @Bwmat6 күн бұрын

    @@IsaacHarrisHolt Sorry, it's not quite relevant to your video, other than the idea of eschewing exceptions in favour of error values. I spend most of my time writing C++, and in that context, I see people recommending such a coding style, but I've never been given a satisfactory answer as to how to do that in that language without it becoming extremely verbose. The reason is that for my purposes, I want to write code that goes into a shared library that gets used by external programs. In that context, I never want to crash or corrupt the process (except for doing the former if I detect the latter), so that means I _do_ want to handle out-of-memory conditions (i.e. `new SomethingImpl()` throwing std::bad_alloc or `new (std::nothrow) SomethingImpl()` returning nullptr) by gracefully unwinding the stack, and then returning an error code via the C API that the shared library is called via by the host program, not simply assume that it can never happen, or just calling exit(1) or abort() or something, which is what I usually hear suggested. The problem is that almost EVERYTHING other than 'mathy' functions probably needs to allocate internally to do its job, at least sometimes, and that allocation _can_ fail, so it makes almost EVERY return value an std::optional<T> or something equivalent. By writing my code using exceptions for error handling, and 'simply' assuming that ANYTHING (other than a few well-known things which are _documented_ to not throw) can throw, and using proper RAII everywhere possible and a 'transactional' style, I find that doing this is relatively straightforward without polluting too much of my code.

  • @thisismissem
    @thisismissem7 күн бұрын

    Ha, the description initially about state is literally identical to how Dan Abramov talked about redux in like 2015/14.

  • @IsaacHarrisHolt
    @IsaacHarrisHolt7 күн бұрын

    Interesting! That's well before my time I'm afraid

  • @thisismissem
    @thisismissem6 күн бұрын

    (Unfortunately I couldn't give you the direct URL to another KZread video in response because KZread thought it was spam 🤦🏻‍♀️

  • @IsaacHarrisHolt
    @IsaacHarrisHolt6 күн бұрын

    Ah that's annoying. I'll find it :)

  • @thisismissem
    @thisismissem5 күн бұрын

    @@IsaacHarrisHolt there's also a really interesting talk from Mark Erikson at React Summit 2024 that gives the history of redux & shows the diagram I was talking about which originally came from a thing called Flux Architecture from Facebook.

  • @IsaacHarrisHolt
    @IsaacHarrisHolt4 күн бұрын

    Interesting! I do think that, while the idea behind Redux was good, there are better alternatives in the React space that fit React's rendering model better. It works well in Lustre and Elm because they were built from the group up for this approach, but iirc Redux would cause a lot of unnecessary rerenders

  • @lesarXD
    @lesarXD7 күн бұрын

    5:05 "its just a function, no special syntax required" 5:19 "luckily for us, gleam has a special syntax" edit: @ 5:50 this is literally just (imo) uglier ? syntax. ill stick with a singular way of declaring variables

  • @IsaacHarrisHolt
    @IsaacHarrisHolt7 күн бұрын

    Use isn't for declaring variables! It's for flattening out callbacks :)

  • @IvanKleshnin
    @IvanKleshnin7 күн бұрын

    It's shocking to see so many commenters who don't get it, even after a good explanation. I'll add my 5 cents. With exceptions you have your SUCCESS logic paths typed, but ERROR paths remain untyped. Compilers do not enforce exception handling and, in JS especially, there's no typesafety with try/catch whatsoever. So if you're into static types - congratulations, but without errors as values you get at most 1/2 of the whole type safety. And if you're not into static types... my condolescences to your career.

  • @IsaacHarrisHolt
    @IsaacHarrisHolt7 күн бұрын

    Finally someone who gets it 😅

  • @EdouardTavinor
    @EdouardTavinor7 күн бұрын

    i know other functional languages have it, but pattern matching against multiple variables at once always makes me think of COBOL :) i'll take a look at the concurrency model of erlang/beam/gleam. i hope it's ok. i'm starting to worry that go has spoiled me for every other language here .

  • @IsaacHarrisHolt
    @IsaacHarrisHolt7 күн бұрын

    You'll find it very similar! Like in Go, you don't have to deal with function colouring, you can spawn short lived or long lived tasks, etc.. Take a look at my concurrency video and let me know what you think

  • @EdouardTavinor
    @EdouardTavinor7 күн бұрын

    @@IsaacHarrisHolt ok, thanks for the video. for me i really like your pacing and the way you build things up to include real-world scenarios. in my opinion the number of functions for dealing with concurrency in gleam/beam is just huge. i also haven't seen a way to organize shutting down of actors. this is one of the things go makes trivial with close(chan) which will cause all listeners to exit their foreach(chan) loops. the way i see it, go offers more functionality with fewer primitives. i imagine i *could* learn to do concurrency with gleam/beam, but i'd be unsure how to build up a dag and then cleanly power it down, for example.

  • @IsaacHarrisHolt
    @IsaacHarrisHolt7 күн бұрын

    This is a fair point - it's a lot to learn, but in exchange you get a very powerful concurrency model that doesn't have all the same footguns as Go channels (which, sadly, do ruin the experience sometimes). In terms of closing an actor, you'd just have a Shutdown variant of your message that the actor handles by returning an actor.stop() (I think that's what it's called). It's ultimately very similar to closing a channel except you don't have the extra function.

  • @EdouardTavinor
    @EdouardTavinor7 күн бұрын

    @@IsaacHarrisHolt yep, one needs to know best practices for concurrency in go. Though it's related to best practices in any language with mutable state, I think. The advantage of close for go channels is that it disconnects all listeners, not just one.

  • @IsaacHarrisHolt
    @IsaacHarrisHolt7 күн бұрын

    That's true! Don't get me wrong, I love Go 😁

  • @Mnementh-ub8md
    @Mnementh-ub8md7 күн бұрын

    I have to say, I think this whole discussion is borked. The video claims exceptions bad with stuff that is solved in some exception languages. Sure, if you compare with Javascript it will be bad. But other languages do exist, and they do stuff better. Similarly I could claim that errors as value are bad, because it is shit in C (the whole reason exceptions were invented is how bad it is). But I do not. Because I use both exceptions and errors as value. And I do that even in one code base. For instance in Java or Kotlin I can (and I did) build types that can contain an error. But I can also use exceptions beside them. The only problem here is, that the function decides in which way it relays errors. But in a error-as-values language I have difficulties to emulate exception when they are the better solution (and they can be). At least since Go the defer keyword exists, which solves at least one problem, as it brings the finally-block of exception-languages into error-as-value languages. Does Gleam support defer? Anyways, I wish for language support in which the caller could decide what way to use. It wouldn't even that difficult to begin with. The function declaration has to contain an indication if it can error. Then the caller can either call it in a way, say like this: val optional_result = ?example(); This syntax could automatically wrap the result into an union or option (or whatever the language has): either an error or the correct result. You could unwrap after checking for the error-state. Alternatively we could use an exception syntax: val result = !example(); In this case result already contains the unwrapped result but in the case of an error it goes to the next catch or if not present the function with this call has to declare to be able to error itself to bubble it up. That doesn't seem too complicated, why does nobody do it? Are people too much wrapped up in their thinking that one way of error handling excludes the other?

  • @IsaacHarrisHolt
    @IsaacHarrisHolt7 күн бұрын

    Firstly, sure, Java and Kotlin have something, but while you're forced to show that your function throws, are you forced to handle it? If you are, that's basically errors as values 😅 Gleam supports defer via `use`, if you write a defer function. The reason language creators don't implement both is because it would add complexity to programs, and errors as values are generally preferred these days. Sure, C got it wrong, but that doesn't mean the whole concept is bad. That said, the whole concept of exceptions? Pretty bad 😁

  • @Mnementh-ub8md
    @Mnementh-ub8md7 күн бұрын

    @@IsaacHarrisHolt Yes, if a function throws, you have to either handle it or bubble it up (by declaring the current function also throws). Well, what you say about C is my argument, only because JS has a terrible implementation that doesn't mean Exceptions are bad. And if you say that Java and Kotlin are basically like error-as-value you see that these concepts aren't as antithetic as you paint it. But you get back to claiming Exceptions are bad, based on nothing. And as you say, modern error-as-value has become a lot better since it adopts more and more ideas of exception handling and both get closer. So implementing both interchangeable as I described shouldn't be that difficult.

  • @IsaacHarrisHolt
    @IsaacHarrisHolt7 күн бұрын

    Java and Kotlin makes two languages, and it's still not a great approach. Java has unchecked exceptions like JS, which arguably makes things worse, as checked exceptions lull you into a false sense of security thinking you've handled everything when you might not have done.

  • @thribsilva
    @thribsilva7 күн бұрын

    try-catches are the devil

  • @IsaacHarrisHolt
    @IsaacHarrisHolt7 күн бұрын

    100%! Errors as values are the way forward

  • @jsonkody
    @jsonkody7 күн бұрын

    I started with Java and kind of hate it and its approach to OOP. I work in JavaScript, and while it offers more freedom, the language has a lot of drawbacks (A LOT! 😄). Over the years, I've explored many languages and have a deep interest in the evolution of programming languages. Now, I am learning Elixir, and for the first time, I feel that this language is almost perfect-or to rephrase it-it's the closest to perfect I've discovered so far. Later, I also discovered the amazing superpowers of BEAM, which further solidified my appreciation for Elixir. PS: I still have some other candidates that I haven't explored too deeply, such as OCaml, Haskell, Lisp, or Smalltalk. Elixir was a match for me because, aside from being interesting, it's also very practical for writing backends and distributed systems. OCaml seemed interesting but quite alien to me, and I don't need to write compilers; when I do, I'll look into it again. Haskell is very elegant until you encounter its excessive strictness, which is also a deal breaker. Smalltalk interested me because it's essentially OOP according to Alan Kay, but I had no other reason to learn it, which is not enough. Similarly, Lisp offered me too little beyond my curiosity.

  • @IsaacHarrisHolt
    @IsaacHarrisHolt7 күн бұрын

    If you think Elixir is great, you should check out Gleam! 😁

  • @pesiok
    @pesiok7 күн бұрын

    Looks interesting, I've been following Gleam development for some time now. I'm bound to try it out at some point. For the time being though it looks like a watered down and less mature version of Scala.

  • @IsaacHarrisHolt
    @IsaacHarrisHolt7 күн бұрын

    Interesting take, for sure. Have a go and let me know what you think :)

  • @edmundas919
    @edmundas9197 күн бұрын

    I disagree from my (C++) perspective for at least 3 reasons: 1. If functions calls another functions and in the deep end you get an error, to propagate the error back now you need to check for error at each level. 2. If your function calls multiple functions you'll need to check for error after each call. This becomes very error prone when you need to release resources manually. 3. If you pass callback to 3rd party library (e.g. standard library) and callback returns error, there is no way for it to handle error to propagate it back.

  • @IsaacHarrisHolt
    @IsaacHarrisHolt7 күн бұрын

    I don't think that "having to" handle errors is a bad thing. It forces programmers to understand the error surface of their APIs and will ultimately promote a better understanding of their program as a whole. Also, I don't see how checking for errors is error prone? You're literally forced to deal with them. 3 can be an issue, I agree, but this is mostly solved by generics and good API design.

  • 2 күн бұрын

    @@IsaacHarrisHolt imagine you check the current 3 types of errors that some call can throw. Tomorrow the API adds a fourth error and your code is not updated (because reasons).

  • @IsaacHarrisHolt
    @IsaacHarrisHolt2 күн бұрын

    If you're using a language with errors as values and exhaustive pattern matching, you can't get into this situation in the first place, because your code won't compile!

  • @MoguMasso
    @MoguMasso2 күн бұрын

    ​@@IsaacHarrisHolt If you're code is linked dynamically, which is most of the time, it can happen.

  • @IsaacHarrisHolt
    @IsaacHarrisHolt2 күн бұрын

    You don't link code dynamically in Gleam :)

  • @white_145
    @white_1457 күн бұрын

    everyone gangsta until Optional<T> option = null

  • @IsaacHarrisHolt
    @IsaacHarrisHolt7 күн бұрын

    😎

  • @dadlord689
    @dadlord6897 күн бұрын

    Like there were not enough null ptr problems, so founders have developed the concept of error so generation to come have proper suffering routine even when coding becomes easier.

  • @IsaacHarrisHolt
    @IsaacHarrisHolt7 күн бұрын

    I'm not sure what you're saying here

  • @vasudevmenon2496
    @vasudevmenon24967 күн бұрын

    For faster package dependency resolution there is uv made by astral sh makers of ruff

  • @IsaacHarrisHolt
    @IsaacHarrisHolt7 күн бұрын

    Yes! uv is great, but it came out after this video :)

  • @vasudevmenon2496
    @vasudevmenon24967 күн бұрын

    @@IsaacHarrisHolt yeah. I started using pipenv,mamba. uv is still in development so I am very excited about all in one tool for python from development to release.

  • @ledkicker2392
    @ledkicker23928 күн бұрын

    So, do you mean the widely known and traditional C-way? int err = getaddrinfo(SERVER_HOSTNAME, SERVER_PORT, &hints, &result); Not sure why the need to present it in a light of a new language

  • @IsaacHarrisHolt
    @IsaacHarrisHolt8 күн бұрын

    The C way works, but it's nicer to have named errors in the form of enums rather than having to try and decode an int

  • @MegaICS
    @MegaICS8 күн бұрын

    4:33 what's the difference here with try/catch (other than syntactical)?

  • @IsaacHarrisHolt
    @IsaacHarrisHolt8 күн бұрын

    Case statements will force you to handle every variant. With try/catch and exception-style systems, you're never forced to even acknowledge the error exists. In Gleam and other error-as-value languages, you have to face the error down when it arises.

  • @IvanKleshnin
    @IvanKleshnin7 күн бұрын

    Type safety.

  • @radumotrescu3832
    @radumotrescu38328 күн бұрын

    Seems like older C/C++ API's got it right the first time. We use a lot of async boost in our server application and we just default to the error_code version of the methods unless we specifically need to handle exceptions. Its much easier to reason about an error code, especially in callback based code.

  • @IsaacHarrisHolt
    @IsaacHarrisHolt8 күн бұрын

    100%, but it's also nice to have named errors in the form of enums!

  • @yoshi_mel
    @yoshi_mel8 күн бұрын

    erlang is offensive, got it

  • @apestogetherstrong341
    @apestogetherstrong3418 күн бұрын

    gleam is stinky doodoo defensive programming. Erlang doesn’t need static typing. Also Gleam runs on BEAM but didn’t adopt OTP. Trash.

  • @IsaacHarrisHolt
    @IsaacHarrisHolt8 күн бұрын

    I think you'll find that Gleam did, in fact, adopt OTP. You can check out the gleam_otp package to find out how wrong you are :)

  • @apestogetherstrong341
    @apestogetherstrong3418 күн бұрын

    @@IsaacHarrisHolt Have you read the README for the same gleam_otp package you mention? «This library does not currently replicate all of the Erlang/OTP functionality». Just use elixir. It's alive and well. "Type safety" cancer is not what is needed for distributed systems. Joe Armstrong would've sighed with disappointment if shown this idiotic language with no point whatsoever, with no contribution whatsoever to the BEAM ecosystem or the distributed programming experience. It's not even a lisp. Cringe.

  • @IsaacHarrisHolt
    @IsaacHarrisHolt8 күн бұрын

    Of course gleam_otp doesn't have feature parity with Erlang. It's a much younger language. Thinking it's going to be exactly the same is naive. And on your point about typing, yes it introduces some challenges, but it also fixes a whole host of issues you would otherwise see in your programs, distributed or not. I would implore you to actually try Gleam for a reasonably-sized project and see how you like it. Badmouthing something without trying it is close-minded.

  • @apestogetherstrong341
    @apestogetherstrong3418 күн бұрын

    @@IsaacHarrisHolt I have erlang and elixir experience, and I tried gleam. It's nothing new. Elixir fixes many aches with erlang, including type aches if there are some in your case. And it has macros. What is the availability status of modules that contain behaviours and macros from other beam langs? Does gleam still need the same fat layer of glue code to fix its inherent incompatibility with libraries that contain too much "let it crash"?

  • @IsaacHarrisHolt
    @IsaacHarrisHolt8 күн бұрын

    Gleam is absolutely okay with "let it crash". It still supports supervisors, process monitoring and most of the requisite stuff there.

  • @MatheusOliveira-er4gq
    @MatheusOliveira-er4gq9 күн бұрын

    Lets see when it gets more mature. Usually we need to speed up small parts of python code

  • @IsaacHarrisHolt
    @IsaacHarrisHolt8 күн бұрын

    True! It's an interesting language for sure

  • @seasong7655
    @seasong76559 күн бұрын

    How is it less complex than a try catch? You still have to handle the error cases. It has the same amount of logic behind it. In Java the functions that throw errors also have to be annotated, so you also see what error the functions throw in the same way as error return types.

  • @IsaacHarrisHolt
    @IsaacHarrisHolt9 күн бұрын

    True, but not every language is like Java. And complexity has nothing to do with how many lines of code you need to write, it's about being able to reason through your program. If I'm reading a Java function, and I see something that throws but isn't immediately handled, I have to look at all that function's callsites, and all those functions' callsites, etc. all the way up the call stack to figure out where it's going to get dealt with, or even if it's going to get dealt with at all.

  • @jakedewey3686
    @jakedewey36869 күн бұрын

    I just want something like Python but with Rust's type system and exhaustiveness checking, so error handling without exceptions becomes idiomatic.

  • @IsaacHarrisHolt
    @IsaacHarrisHolt9 күн бұрын

    Sounds like you want Gleam 😉

  • @georglauterbach8972
    @georglauterbach89729 күн бұрын

    „This pattern is very similar to the way the question mark operator works in Rust. But in Gleam, it’s just a function - no special syntax required. However, call-back based code like this can become quite nested. In the world of JS, this is often referred to as „callback hell“. […] Luckily for us, Gleam has a special syntax for flattening out callbacks.“ Do you want the special syntax now, or don’t you?

  • @IsaacHarrisHolt
    @IsaacHarrisHolt9 күн бұрын

    Fair point! The `use` syntax in Gleam is used for more than just error handling though, and it's completely optional. But yeah, I see where you're coming from :)

  • @georglauterbach8972
    @georglauterbach89729 күн бұрын

    I thought it was funny that the video does not seem to recommend special syntax first, but then proceeds to use it. Either way, I like both. To be fair, the `?` Is optional as well and just syntactic sugar for a match expression. I‘m quite curious how Gleam compares to Rust. Seeing that it is built on top of Rust (nice), I would expect to be able to do all that Gleams aims to do with Rust as well; at least this is my initial impression. Maybe a video about Gleam vs Rust would be interesting too :)

  • @IsaacHarrisHolt
    @IsaacHarrisHolt9 күн бұрын

    Gleam is built using Rust, but they're fundamentally different languages. You're not the first person to compare the two though, so it's probably worth making some sort of video to clear that up 😅

  • @Axman6
    @Axman69 күн бұрын

    WOW, IT’S ALMOST LIKE HASKELL HAD THIS RIGHT THIRTY YEARS AGO. *cough* sorry, had something stuck in my throat.

  • @IsaacHarrisHolt
    @IsaacHarrisHolt9 күн бұрын

    Never said it didn't! But the rest of the industry is finally catching up

  • @Daniel_Zhu_a6f
    @Daniel_Zhu_a6f4 күн бұрын

    every normal low-level language has type unions, calm down. exceptions are much better than values when you work in a REPL though, that's why even functional scripting languages use exceptions. as somebody who works with python (for data processing) i can tell that the trick about working with exceptions is not to catch them, unless you really need to, and not to throw them, unless the error is so big that it should reset execution to the most recent checkpoint (eg drop a record from a table, cancel/redo a task). then exceptions become quite manageable. but in standalone programs exceptions get out of hand very quickly indeed

  • @IsaacHarrisHolt
    @IsaacHarrisHolt4 күн бұрын

    I'm curious, what do you do in the case where you have a small error? Do you return it as a value? In which case, you're doing it the Gleam way already! You're effectively using exceptions to crash and reset your process, which is offensive programming and would be managed in Gleam using a supervision tree.

  • @Daniel_Zhu_a6f
    @Daniel_Zhu_a6f4 күн бұрын

    ​@@IsaacHarrisHolt depends on a case. may just log it (eg. when iterative algorithm does not converge, but there is still some sort of result). i also just log any unexpected exceptions when i batch-process a lot of files, so that a script won't stop because of one bad file. when error is very much expected (parsing, validating) may want to return a type union ( i usually use pair of int/enum + value, to indicate what value means, kind of like one would normally do type unions in C) then there are less common options: collect information about errors (input values, error messages) into array and return it / store in a global variable. this is just like logging, but you can easily use this data further down the line, eg select only those table records that give rise to a certain type of error. of course, this can be done with well-structured logging system, but list approach is much simpler. it is possible to feed errors to an impure error-handling function that does something complex. eg if you may want to have email/telegram notifications + save broken data separately, but this is more of a standalone program territory, than a repl session/script. however, a handler function may be useful in other scenarios in a repl context: i often use handler functions for plot post-processing (appying certain common adjustments, saving, deallocating) -- this way, i don't need to write same piece of code over and over again, but at the same time have several radically different behaviors, that i can switch on the fly by reassigning a global variable to a different function.

  • @Daniel_Zhu_a6f
    @Daniel_Zhu_a6f4 күн бұрын

    @@IsaacHarrisHolt depends on a case. may just log it (eg. when iterative algorithm does not converge, but there is still some sort of result). i also just log any unexpected exceptions when i batch-process a lot of files, so that a script won't stop because of one bad file. when error is very much expected (parsing, validating) may want to return a type union ( i usually use pair of int/enum + value, to indicate what value means, kind of like one would normally do type unions in C) then there are less common options: collect information about errors (input values, error messages) into array and return it / store in a global variable. this is just like logging, but you can easily use this data further down the line, eg select only those table records that give rise to a certain type of error. of course, this can be done with well-structured logging system, but the list approach is much simpler. it is possible to feed errors to an impure error-handling function that does something complex. eg if you may want to have email/telegram notifications + save broken data separately; this is more of a standalone program territory, than a REPL session/script. however, a handler function may be useful in other scenarios in a repl context: i often use handler functions for image/plot post-processing (applying certain common adjustments, saving, deallocating) -- this way, i don't need to write same piece of code over and over again, but at the same time can have several very different post-processors, that i can switch on the fly by reassigning a global variable to a different function.

  • @Qrzychu92
    @Qrzychu929 күн бұрын

    The only thing that exceptions have over errors are values is the fact they always come with a call stack. When something goes wrong, you know exactly which file to open and in which line to look, or at least where to put a breakpoint. I would say until your lang supports adding stacktrace to the errors, it becomes much harder to determine the reason for an error

  • @IsaacHarrisHolt
    @IsaacHarrisHolt9 күн бұрын

    You can use something like Snag to add context to your errors in Gleam, or Go has the ability to wrap errors. That provides enough context as long as you're diligent, I think. But yes, they don't come by default.

  • @user-uf4lf2bp8t
    @user-uf4lf2bp8t8 күн бұрын

    This is true for older languages like ocaml and haskell where the norm is just to use options, but result types with an error type and an ok type are better because the error variants come with info. These are more popular in rust and gleam.

  • @AGeekTragedy
    @AGeekTragedy9 күн бұрын

    "throw is just a fancy goto". I mean yes, but all control flow mechanisms are just fancy goto.

  • @IsaacHarrisHolt
    @IsaacHarrisHolt9 күн бұрын

    True, but most are predictable. Throw could take you anywhere

  • @user-uf4lf2bp8t
    @user-uf4lf2bp8t8 күн бұрын

    Gleam doesn't have those, other than panic. No if else, no loops, no early returns, no exceptions.

  • @AGeekTragedy
    @AGeekTragedy8 күн бұрын

    ​@@user-uf4lf2bp8t I'm pretty sure pattern matches and function calls both have gotos in them if you strip off enough layers of abstraction To be clear, i think the abstractions are good and was mostly just being silly saying everything is a goto.

  • @oracleoftroy
    @oracleoftroy7 күн бұрын

    ​@@IsaacHarrisHolt Throw could take you anywhere in the same way return could take you anywhere. In reality, throw works like a super return, it is only going to take you up the call stack, not to some random place in the code that has a try/catch. Saying it can take you 'anywhere' always makes me assume the person has never actually worked with exceptions.

  • @IsaacHarrisHolt
    @IsaacHarrisHolt7 күн бұрын

    Yes, it can only take you up the call stack, but unless you have visibility on the whole call stack, you can't see where that error is going to pop out. Also, you don't KNOW which functions are going to throw, which is the whole problem.

  • @OmegaMusicYT
    @OmegaMusicYT9 күн бұрын

    I do not agree with the premise of this video. You know what else is just another word for goto? Return. Each exception doesnt create a new control flow, there is a flow for correct values (return) and a flow for errors (raise). All correct values are returned to the function call and all errors are raised to the try/except block. There are no other flows besides those two. Also, the "you no longer have to litter your code with try/except blocks" claim is technically true, just that you litter it with if statements and match cases instead. Finally, with exceptions I can simply write the only correct path for my code, and if any of the calls I make fails, If its well coded it will rise an exception and I can catch that from the caller. With errors as return values I must check each return value for errors at any step, whereas try/except allows me to handle all possible errors through the caller with a single try/catch statement. Try/catch statements are great because they can cover an entire function call, and I don't care where the function breaks, I can simply code the correct path and handle any errors later. Its a much more effective approach and its only confusing when people use error values in return in languages with try/except statements or when people dont declare which exceptions their code throws for each case, and return values as errors solve neither of those problems.

  • @IsaacHarrisHolt
    @IsaacHarrisHolt9 күн бұрын

    Writing try/except over your entire function is a terrible way to write code. You won't know which part of your function is breaking, meaning debugging will be ten times harder. Also, you don't know which functions are gonna throw, so you have to wrap EVERY function call with try/except unless you have full access to the source and the source of every function it calls. That's what I meant by the littering comment. At least with errors as values you only need to add extra handling when you KNOW there's going to be an error.

  • @TurnerXei
    @TurnerXei7 күн бұрын

    @@IsaacHarrisHolt In any language with stack traces or exception values you definitely know exactly where an error occurs. I've never seen anyone wrap every function in an exception handler, but I have seen nearly every function have a conditional that checks for error values. Any half-decent API doc generator should tell you if the a function throws exceptions, you don't need access to the source code.

  • @IsaacHarrisHolt
    @IsaacHarrisHolt7 күн бұрын

    Most API doc generators can't tell you if it throws because most languages don't have anything to mark that. The doc generator would have to crawl your source code and the source of every function you're calling. Also, yes, stack traces give you the location, but only AFTER the error has occurred. So you know what WENT wrong. Errors as values tell you every single thing that COULD go wrong.

  • @Mnementh-ub8md
    @Mnementh-ub8md7 күн бұрын

    ​@@IsaacHarrisHolt You won't write an try-catch over your function, if you intend to just keep it as error-condition. You just throw it up. Also you know which function throw an exception, because exceptions are part of the functions signature in most languages with exception-handling and the compiler will enforce that you handle the exception - but only if one is thrown in the code you call.

  • @IsaacHarrisHolt
    @IsaacHarrisHolt7 күн бұрын

    There are relatively few major languages where exceptions are part of the function signature. I know Java has the option of doing it, as does Swift, but iirc it's not always enforced. And in languages where you don't have it, your tooling would need to recursively check every function call down to the native layer to see all the kinds of exceptions that can be thrown.

  • @aLfRemArShMeLlOw
    @aLfRemArShMeLlOw9 күн бұрын

    Tom's a genius.

  • @IsaacHarrisHolt
    @IsaacHarrisHolt9 күн бұрын

    We're all just quiche eaters under his gaze