11 ms·
Why would you write Python like it’s Rust? I really fundamentally do not understand the purpose. Ain’t `is Null` checks and try except good enough?
by impoppy 5y ago
Why would you write Python like it’s Rust? I really fundamentally do not understand the purpose. Ain’t `is Null` checks and try except good enough?
- DandyDev 5y agoBecause you'd like use the Python ecosystem, for example for writing ML code, but you'd also like to write typesafe code (or rather typechecked, using mypy)
- rmbyrro 5y agoCame here to say the same thing...
- IshKebab 5y agoYeah this sort of thing is necessary in statically typed languages like Rust and C++ but in Python (and e.g. Typescript) you can just use anonymous type unions like `str | None`. There's no need to construct a static type to hold both possibilities because variables can already hold all types.
- hackandtrip 5y agoGood luck checking for `None` equality and indent your code like 5 times... a sort of railway programming[0] avoids the awkward checks for values, making functions work with higher order types. 0: https://www.greenbird.com/news/railway-oriented-programming-in-kotlin#:~:text=Railway%20Oriented%20Programming%20(ROP)%20is,can%20be%20of%20any%20type https://www.greenbird.com/news/railway-oriented-programming-....
- ReleaseCandidat 5y agoThe original Railway: https://fsharpforfunandprofit.com/rop/ https://fsharpforfunandprofit.com/rop/ And his 'Against Railway-Oriented Programming': https://fsharpforfunandprofit.com/posts/against-railway-oriented-programming/ https://fsharpforfunandprofit.com/posts/against-railway-orie...
- impoppy 5y agoHow is this different from match case ok case err or from if result.val?
- hackandtrip 5y agoWell, the most basic pro is to avoid indentation and have pure function which are clear and have less assumption to take into account; if I know that my pipes always return me a result such as the one I want, and the "bad path" is discarded automatically, code is way cleaner. Imagine a code without `if result is not None` basically!
- IshKebab 5y agoOk if a is None: raise Exception() if a.b is None: raise Exception() if a.b.c is None: raise Exception() One of the advantages of Python/Typescript style type hinting is that it avoids the mega-nested `if`s that you often have to resort to in Rust. In Rust the above would not work: if a.is_none() { bail!(); } if a.b. // nope! a is still Option<>. It may be possible to fix that when enum variants are distinct types but as it stands you often have to do lots of indenting.
- dragonwriter 5y agofoo | None is not a tolerable replacement for Maybe(foo) When None is a valid value of type foo. Which is obviously true when foo is NoneType, but more to the point is true when foo is (bar | None). Maybe composes, “... | None” does not.
- impoppy 5y agoa) do Optional[Union[foo, bar]] b) why do you expect this from a duck typed language? None of options you listed or the library is offering saves you from mismatched types. Mypy is still as good as it can possibly be using only vanilla type hints
- dragonwriter 5y ago> None of options you listed or the library is offering saves you from mismatched types. Even if true, so what? The utility of Maybe/Result datastructures isn't limited to their use in typechecking, though with a proper static typechecker, that is part of their use.
- btown 5y agoI've definitely hacked my way around this with sentinels. `foo | sentinel | None` is a passable replacement for Maybe(foo), and it arises naturally from dict.get("key", SENTINEL). Absolutely not fun to need to check, but if you're using it within a single function e.g. an implementation of `deep_get` or something like that, the code is readable.
- dragonwriter 5y agoYeah, there's lots of things that work good enough for localized use to approximate something like Maybe or Result and a lot of times that's all you need, and (in Python) more convenient than the real thing when that's all you need. Wanting something that's ergonomic for free composition where you aren't anticipating all the potential uses where it is defined is where real monadic Maybe/Result types shine, and once you pull them in to a code base it sometimes makes sense to use them for the local cases, too.
- impoppy 5y agoI let myself do a little bit of thinking and I guess this might be helpful when you are doing functional style pipes/chains but you can wrap the whole chain into a try except block. But the question is still there: why would you do that? Why the one would write functional code in a language that ain’t very good with maps and filters, has no lazy calculations and has no constants on language design level? Why would you set `Maybe[int]` type for a function argument? That’s an obvious overcomplication imo. Go and write some F# or Haskell. Well, the variety of options and flexibility is always good, but the language is fundamentally not meant to do it. From what I can see, it only makes sense in recreational programming, making some eye-pleasing code, but it all is just a workaround on a language that would not benefit from that code style. All above is strongly imo of course since I only write Python and am just learning Zig.
- dragonwriter 5y ago> Why the one would write functional code in a language that ain’t very good with maps and filters, has no lazy calculations and has no constants on language design level? Python is fine with maps and filters, and has lazy calculations.
- impoppy 5y agoPlease provide links so I can read on this
- muxator 5y agoThe map() function is already lazy (in python 3 it returns a generator, and not a materialized list). You can also have a look at "generator expressions", which are the lazy counterpart to a list comprehension (hint: use " ()" instead of "[]").
- dragonwriter 5y ago> Please provide links so I can read on this https://docs.python.org/3/library/functions.html#map https://docs.python.org/3/library/functions.html#map https://docs.python.org/3/library/functions.html#filter https://docs.python.org/3/library/functions.html#filter https://docs.python.org/3/howto/functional.html https://docs.python.org/3/howto/functional.html
- deleted 5y ago[deleted]
- btown 5y agoSay you're given a Python function in a large codebase that doesn't have documentation but does have type annotations, say, to indicate it returns Optional[str]. Does this tell you that you just need to check for None, and otherwise it's a string? Nope, it could throw. What could it throw? We don't know. There are many applications where this magnifies the dangers of any existing technical debt. One could desire strong exception-proofing of results without needing to go "all in" to a borrow-checked regime like Rust. The Koda approach is lightweight and doesn't enforce this, but one could imagine a static checker that says "any function that returns a Result, and calls any function that does not itself return a Result or does any other risky operation, must have an exhaustive top-level try-except block, or be wrapped by a decorator that does the same." Then, you could guarantee that all code explicitly handles exceptions, while still accessing the full Python library ecosystem - you can use non-Koda-wrapped code at any time, you just need to handle its exceptions. Is this overkill? Possibly. But I can think of a handful of bugs offhand that this would have caught in our codebase if enforced.
- impoppy 5y agoNow this is an answer I was waiting for. Thank you for explaining the real benefits of sticking to koda style. I guess this would be obvious if I used statically typed languages since there is no try except clauses in most of them
- btown 5y agoI'll add that caveats do apply to these benefits. Many of them are outlined in https://fsharpforfunandprofit.com/posts/against-railway-oriented-programming/ https://fsharpforfunandprofit.com/posts/against-railway-orie... - which is a response to an excellent functional programming talk (see slides or video linked at https://fsharpforfunandprofit.com/rop/ https://fsharpforfunandprofit.com/rop/) that walks through why you'd want a Result-type thing to exist in the first place... and eases you into the larger world of monads!
- ReleaseCandidat 5y ago> and eases you into the larger world of monads Yes, just begin reading at page 29 https://www.slideshare.net/ScottWlaschin/railway-oriented-programming https://www.slideshare.net/ScottWlaschin/railway-oriented-pr...
- deleted 5y ago[deleted]
- keithasaurus 5y agoI think the discussion is far enough along here to cover a lot of the bases. Just to add a bit of clarity, Scala's APIs were a bit more influential than Rust, but, yeah, it's similar to both.
- throwamon 5y agoNo, they're not. And I wouldn't say it's writing it like Rust; rather, it's writing it like you can sleep at night. These concepts weren't born in Rust, they were born in functional languages and category theory and they're all about making sure you don't get away with sloppy code and billion-dollar mistakes[0]. [0]: https://en.wikipedia.org/wiki/Tony_Hoare#Apologies_and_retractions https://en.wikipedia.org/wiki/Tony_Hoare#Apologies_and_retra...