14 ms·
Structural pattern matching in Python 3.10
- leontrolski 5y agoA really nice collection of examples in their original and their refactored form - nice work. I'm similarly in two minds about the feature, it's cute, but is it worth it? I think it's indicative that the nicest use is in AST processing. As someone that works on the occasional parser-y side project it looks pretty cool, but also, 97% of professional Python development is in data-science/application development. I suspect this is a case of the core language devs having a bias towards features that are useful to them as opposed to the community as a whole.
- benhoyt 5y agoThanks! Yeah, that's how it seemed to me too. The AST processing examples really sell it. But the fact that Warehouse is a sizeable application (60kLoC) but didn't really have any good uses for pattern matching is telling.
- angelzen 5y agoPattern matching enable an entirely new class of features that are too tedious and error prone to implement otherwise. Specifically, anything that has to do with recursive structures. Are recursive structures useful? Perhaps, given that natural language is fundamentally based on recursive structures. Apps designed pre ubiqutous pattern matching say little about whether pattern matching has good uses or not. More likely features alluding to pattern matching were culled early in the design process.
- benhoyt 5y agoI think it's a bit of a stretch to say that "anything that has to do with recursive structures" is too tedious to implement with without pattern matching. I've written my share of recursion in Python, and have written a number of recursive parsers and language interpreters in Go (which also doesn't have pattern matching). I didn't find it bad at all. That said, I think your overall point is interesting. Will this new feature in Python mean that Python is used for certain domains it wasn't previously? I have my doubts, partly because it's a fairly slow byte-code interpreted language, and that limits its usefulness (I've seen a number of compilers written in OCaml, for example, which has pattern matching, but is also fast).
- BiteCode_dev 5y agoI'd say it's a good thing people don't try to use the feature in a context it's not useful. Don't use the shiny new toy just to play. Python has to cater to a vast crowd, and geographers don't have the same needs as data scientists, web devs, 3D artists or sysadmin. So it's logical some tools will be useful in some cases, and not some others. Amusingly yesterday I was doing something in JS, and though, "ah, I wish I has this new PM feature from python there". The day before, I had to deal with pedantic exception, and wish I had a pattern matching to make a case depending of the number of errors and their message. I had to do a hacky loop for something that had to do with structure, not repetition. Just like the walrus, I don't think it's something that will pop up everywhere, all the time. But when it is useful, it will make the code nicer.
- BiteCode_dev 5y ago> but also, 97% of professional Python development is in data-science/application developmen No. There is not a single field with " 97% of professional Python development". As a freelancer, I see python used for everything, everywhere. From education, to math, to biology, to geography, to web dev, to automation, to testing, to desktop app...
- WoodenChair 5y agoCan anyone comment on the performance of structural pattern matching in Python 3.10 for simple cases compared to if/elif? For example, say I am just checking for which of several cases from an enum to diverge based on.
- benhoyt 5y agoI did a quick test of match vs if...elif for a basic enum switch, as well as a slightly more involved class/structural matching test. Results and code: https://gist.github.com/benhoyt/f648d6dd13ce112ba1a4422b175e6163 https://gist.github.com/benhoyt/f648d6dd13ce112ba1a4422b175e... For the enum switch, match generates very similar bytecode (use dis.dis to see) and the execution time is almost identical. For the structural matching, match is significantly slower, which surprised me a bit (it's almost twice the number of bytecode instructions). That said, we're down in the nanoseconds range -- use of this feature shouldn't be about ns-level performance, but code clarity. I suspect "match" will get faster over time as they add optimizations or specialized bytecode for it.
- SavantIdiot 5y agoOdd that something this complex doesn't support regular expressions or even greater-than, less-than. I'm also not that good at Python so perhaps it is obvious and I missed it? I didn't RTFM but I did CFTFM (ctrl-F'd the FM).
- nerdponx 5y agoThose are supported via the `if` clause. But I wouldn't say they're "obvious" features, given that they're not present in the languages this idea is borrowed from (ML, Haskell, etc).
- SavantIdiot 5y agoThat's what I thought, it just feels weird to do a bunch of ifs, and then invoke this behemoth of a construct.
- gigatexal 5y agoI used to do this with a dict. Glad this is in Python 3.10.
- dehrmann 5y agoIt took way too long to get this considering how case has been around forever. Now I just want a do-while.
- jimminy 5y agoYeah, I think the author focused a bit too much on structural pattern matching being a replacement/alternative for if...elif blocks. It will be much more useful as an alternative to dispatch dictionaries, which are more a side-effect of the language lacking any case based control-flow.
- ufo 5y agoBy the way, does anyone here know how Python compiles the match statements under the hood? Are they converted into something equivalent to if-elif, which tries each option in sequence? Or does it do something more clever?
- mixmastamyk 5y agoThe author replied here that yes, the bytecode is simple, with the exception of the Class matching. https://news.ycombinator.com/threads?id=benhoyt https://news.ycombinator.com/threads?id=benhoyt
- kristjansson 5y agoYeah, there are several giant dictionaries (variously class to function, string to class, etc.) in just the project I’ve worked on most recently that fit that description. Though considered from that perspective, it’s actually a bit of a disadvantage that the new match statement is a part of the language. It’s nice to dynamically extend (either as a first party developer or third party user) that sort of dictionary, effectively adding new branches to the implicit switch statement. A match statement is going to be fixed as written. Probably a readability and consistency win to remove spooky-action-at-a-distance, but at the cost of a bit of (ugly, pragmatic) usability
- wallscratch 5y agoSo my dream is that eventually mypy (the optional python static typing module) will be extended so that python becomes a gradually typed language — able to detect if an entire program has valid static typing, and if so, use a much higher-performance python compiler to skip over the python object system to increase code speed by 10x. This would make python both a viable choice for rapid prototyping, as well as easy to convert to much higher performance code (just by handling some typing conflicts), and potentially making python a mega-language used even more pervasively.
- breuleux 5y agoI don't think typing is the main obstacle to Python performance, otherwise it wouldn't be that much slower than JavaScript. In fact, there are several alternative interpreters that are much faster, but they entail incompatibilities with popular packages. Static typing cannot fix this. Now, my dream would be for Python to actually enforce type annotations at runtime when they exist. Maybe add some kind of syntax to avoid doing it when it's expensive, e.g. `list[nocheck int]`, but for the love of god, enforce it, otherwise I feel like I'm just peppering my code with limp suggestions that only stand if some third party package can find all paths that lead to them, at which point I'd rather use a true statically typed language where the whole system doesn't look and smell like a janky afterthought.
- vlovich123 5y agoYou can’t compare to JavaScript as most JavaScript runtimes have a JIT. You’d have to compare against PyPy or something like that but it hasn’t seen anywhere near the amount of performance attention like any of the browser JavaScript engines. Finally, CPython is very old. That means it made decisions around multithreading it still has to live with to this day whereas the JavaScript implementations have always been single threaded and added multithreading much later (learning from the experiences of other languages making the transition). Dynamic typing is part of the problem but you’re right that it’s not the whole thing.
- codewiz 5y ago
- benhoyt 5y agodang, could we please merge the comments from https://news.ycombinator.com/item?id=28591173 https://news.ycombinator.com/item?id=28591173 into here (or vice versa)? Thanks for resubmitting, chmaynard!
- chmaynard 5y agoI usually do a quick check for duplicates by clicking on the domain name in parentheses. If there is an identical post with some activity, I delete mine. Forgot to do this, sorry. You can have my karma. :)
- benhoyt 5y agoNo worries! Yours was getting lots of votes, mine wasn't (possibly a time-of-day thing). Side note: I re-read my comment and "dang" sounded like I was annoyed. By "dang" I mean "HN moderators". :-)
- pvg 5y agoYou should email the mods if you need something tweaked, summoning from comments doesn't work reliably but email does.
- benhoyt 5y agoGood call, I emailed and he merged them!
- adsharma 5y ago> Python evaluates the match expression One other limitation from the perspective of people looking to transpile static python to other languages: match is a statement, not an expression in the language. I've been looking to define an extension for transpilation purposes that doesn't break match in 3.10 but provides an avenue to transpile code to rust and other FP languages.
- zeckalpha 5y agoI am a big fan of this but the class based matching is a weak example as each case could be implemented as a method call on the class.
- benhoyt 5y agoWhich specific class matching example are you referring to, and how would you implement the matches as method calls?
- _dain_ 5y agoYes, but what if you don't have control over the class definitions because you're importing them from elsewhere? It seems a bit overkill to subclass all of them.
- foxes 5y agoNow also add back lambda tuple unpacking. I wish Guido et al would totally get over the cringe aversion to functional programming concepts.
- canjobear 5y agoSeriously. I think Python 3 was a big improvement but removing tuple unpacking in function arguments (while adding it elsewhere!) was a huge regression.
- aix1 5y agoI wonder what the rationale was for the removal?
- the_mitsuhiko 5y agoI think to simplify `__signature__`.
- pansa2 5y agohttps://www.python.org/dev/peps/pep-3113/#why-they-should-go https://www.python.org/dev/peps/pep-3113/#why-they-should-go
- sambe 5y agohttps://www.python.org/dev/peps/pep-3113/ https://www.python.org/dev/peps/pep-3113/ "In order to get all of the details about the tuple from the function one must analyse the bytecode of the function. This is because the first bytecode in the function literally translates into the tuple argument being unpacked. Assuming the tuple parameter is named .1 and is expected to unpack to variables spam and monty (meaning it is the tuple (spam, monty)), the first bytecode in the function will be for the statement spam, monty = .1. This means that to know all of the details of the tuple parameter one must look at the initial bytecode of the function to detect tuple unpacking for parameters formatted as \.\d+ and deduce any and all information about the expected argument. Bytecode analysis is how the inspect.getargspec function is able to provide information on tuple parameters. This is not easy to do and is burdensome on introspection tools as they must know how Python bytecode works (an otherwise unneeded burden as all other types of parameters do not require knowledge of Python bytecode). The difficulty of analysing bytecode not withstanding, there is another issue with the dependency on using Python bytecode. IronPython [3] does not use Python's bytecode. Because it is based on the .NET framework it instead stores MSIL [4] in func_code.co_code attribute of the function. This fact prevents the inspect.getargspec function from working when run under IronPython. It is unknown whether other Python implementations are affected but is reasonable to assume if the implementation is not just a re-implementation of the Python virtual machine." I'm not very convinced without further information - it sounds like it was already solved in CPython, and bug in IronPython? The whole PEP reads as if it's looking for excuses for removal. I find this especially annoying for lambdas.
- kortex 5y agoThe biggest upset is that they didn't go the extra bit and implement match assignments. Such an insanely powerful, very functional feature. Helps reduce bugs simply by facilitating orthogonal branches of assignment that cannot interact, unlike if/else or for loops. Oh well, maybe in a few years someone will put in a PEP to use walrus := with match/case to give match assignment and give the old Python guard something to _really_ clutch pearls about.
- benhoyt 5y agoDo you mean like this? x = match expr: case 'a': 1 case 'b': 2 case _: 0 I think mainly it doesn't work very well in Python due to indentation problems. Kind of like how lambda is restricted to single expressions, instead of blocks. Here's what they say in the rationale PEP (https://www.python.org/dev/peps/pep-0635/ https://www.python.org/dev/peps/pep-0635/): > Statement vs. Expression. Some suggestions centered around the idea of making match an expression rather than a statement. However, this would fit poorly with Python's statement-oriented nature and lead to unusually long and complex expressions and the need to invent new syntactic constructs or break well established syntactic rules. An obvious consequence of match as an expression would be that case clauses could no longer have arbitrary blocks of code attached, but only a single expression. Overall, the strong limitations could in no way offset the slight simplification in some special use cases.
- sullyj3 5y agoI think they're right that it would be too foreign to python to be a good addition, but this really just goes to show that expression oriented languages, as opposed to statement oriented ones, are the way to go.
- marmaduke 5y agoThe debugging and instrumentation in Python is line and statement oriented, so there’d be a lot more work behind the scenes.
- deleted 5y ago
- oofbey 5y agoI’m a heavy professional python user, and I’ve read about this new feature maybe a half dozen times. And I still don’t get it. Sigh. Powerful? I guess so. Complicated? Definitely. Confusing? You bet. Good addition? Uhh, I really hope so.
- BiteCode_dev 5y agoGive a try to fastapi + vscode with pylance. Eye opening to what you can do if you use modern features right.
- mixmastamyk 5y agoThis is the best piece I've read on the subject, you might give it another try. I'm now lukewarm on the feature, whereas before I thought an abomination.
- rocqua 5y agoThe concept came over from Rust and Haskell. The value of the concept really comes out when you start designing your types to be case...match-ed against. I am not the best person to explain this, but the value I mean is allowing more 'algebraic datatypes' to be used in python. This way you can have the structure of your data(types) more closely resemble your business logic. Making code more readable, and also making it harder to represent invalid states, which reduces the need to validate data. (I recall an article called "parse don't validate" the same idea applies here) I think it will take a while for python users to start using this paradigm, but I expect it will be very useful for folks who know Rust, Haskell, or similar languages.
- umanwizard 5y agoThe concept is much older than Rust and Haskell. It was present in ML which is from the 70s and has strongly influenced most modern languages (and yes, Rust and Haskell particularly strongly).
- rocqua 5y agoof course. But within Haskel and Rust the concept gained traction with the wider developer community. I think especially Rust was important for getting python developers to consider adopting it. Since it is a 'serious' language rather than an 'ivory tower' language.
- thibran 5y agoToo many 'case' repetitions for my taste.
- samuel 5y agoOnce my favorite language by far, Python is starting to became too cluttered. Very few of the additions to the language in the 3.x branch are worth it IMO. I remember that in the early 00's people called it "executable pseudocode". I bet nobody would use now that expression for modern Python with decorators, comprehensions, walruses and the like.
- killingtime74 5y agoIs it not all optional? You don’t have to use it if it doesn't improve your code
- joelthelion 5y agoIt still ends up in other people's code, so it's hard to meaningfully contribute to python projects without learning at least the basics for all these new features.
- samuel 5y agoIt is. But stablished idioms became obsolete, and the code that used them becames unidiomatic. And you have to learn them if you want to read other people's code. Python doesn't need more features but better implementations, IMO. Edit: Just remembered the Zen of Python, I don't think modern Python is following it. ... Simple is better than complex. ... Readability counts. ... There should be one-- and preferably only one --obvious way to do it.
- el_oni 5y agoAnd yet i would argue that comprehensions and decorators are more readable and simple than wrapped functions and for-loops that append to a list. Having one way of doing something and sticking with it even when better ways emerge is nonsensical imo. f-strings are more readable (for me) and concise than string formatting or .format() I do agree on the implementation front though, many of the other implementations are still on 2.7 or 3.6 at most, and don't have mainstream appeal. Made more with interop in mind (like ironpython with .net and jython with the jvm)
- jb3689 5y agoI find it strange how obsessed people are with structural pattern matching while simultaneously putting little mind towards function head pattern matching e.g. Erlang/Elixir. These break up recursive functions so nicely. Maybe it is the lack of TCO in said languages?
- valzam 5y agoNot just recursion but also error handling. Gets all the if x = nil checks out of the way and the actual function only has Business Logic. Same for functions that need to operate differently based on input, no pollution of the body with if branches
- de_keyboard 5y agoI love this style of programming but it does not work well in Python, the language just isn't built for it. TCO is one limitation. Another is that performant Python code sends large chunks of work to native libraries and recursion inside of Python functions is pretty much the opposite of that.
- timzaman 5y agoWould be nice if we can just get out of this local minima of Python 3.30, and start working on Python 4 that's somewhat backwards compatible and has no GIL and has meaningful threading support.
- quietbritishjim 5y agoTo rehash my typical HN reply about GIL: I find that 99% of the time that you need to use threads for CPU work (not just IO), that means that you care enough about performance that your Python just calls into some C library (C extension libraries e.g. numpy, scipy, or even bits of the standard library e.g. zipfile operating on an in-memory buffer). The thing is, all these calls (almost) all release the GIL anyway. So threading support in Python is already meaningful, unless you want to run pure-Python CPU intensive code on multiple threads, which I'll admit does happen but in my experience is rare.
- ynik 5y agoThat only works if you can hide your inner loop in the extension module, and can get rid of all accesses to the Python object model inside the inner loop. This works great with numpy if you can work with sufficiently-large arrays so that the GIL can be released for a nontrivial amount of time. But if your algorithm doesn't have this structure, "call into C and release the GIL" just means the inner loop is constantly releasing+reacquiring the GIL, and multi-threaded execution won't be any faster than single-threaded execution due to the fights over GIL. Unfortunately we're mostly dealing with complex stuff happening during graph traversals. There is no "inner loop" for us -- just the "outer loop" of the graph traversal. So the only way to get our code to run in parallel is to port the whole algorithm to C. But that's 150k+ lines of codes, there will be barely any Python remaining :( IMHO Python is a trap, it's easy to get started with but you can stuck in a position you can't get out of without a full port to a different language. (and yes, we've already tried multi-processing and using shared-memory segments in the C code portions to avoid re-doing work in every process, ... but after more than a man-year of work, >80% of our application remains single-threaded thanks to the GIL, even though in any other language it would be trivial to parallelize the independent graph traversals) It's neat to have a scripting language for fast prototyping but we would be much much better off if we had picked Javascript instead of Python (the ability to have multiple interpreters in the same process running in parallel would solve our issues).
- choeger 5y agoThe author commits a logical fallacy, I think. The use cases aren't there yet, because pattern matching is missing. It's not the deconstruct statement that matters. But with it, you can work well with variants, which you couldn't really do before. There are so many natural real-world applications to tagged union structures that I bet the ratio will look very different in a couple of years.
- mixmastamyk 5y agoThis functionality has been around a long time in other languages, enough for use cases to be discovered, no?
- fqll100 5y ago"It’s tempting to think of pattern matching as a switch statement on steroids. However, as the rationale PEP points out, it’s better thought of as a “generalized concept of iterable unpacking”." This is the problem with the recently added features in Python. As the author of the blog post correctly notes, the features are unintuitive and full of special cases. You always have to know and recreate the steps that the unpacking machinery takes, there is nothing logical and declarative like in the ML family languages. Pattern matching in SML or OCaml is simple and obvious. These features are added to Python in order to give an impression that some "development" is happening. With the benefit that they prevent implementations like PyPy from catching up. Meanwhile a non-existing vaporware JIT from Microsoft is pushed as the future.
- _dain_ 5y agoA while ago, PEP 591 [1] made its way into the language. It introduced a "final" decorator / type annotation to indicate to mypy that a certain class shouldn't be subclassed, or a certain method shouldn't be overridden. At the bottom, there is the comment: >A related feature to final classes would be Scala-style sealed classes, where a class is allowed to be inherited only by classes defined in the same module. Sealed classes seem most useful in combination with pattern matching, so it does not seem to justify the complexity in our case. This could be revisited in the future. Has this been picked up? Replacing long if-elif blocks is only half the power of pattern matching. The other is to have exhaustiveness-checking by the static type checker. I have pieces of code that would really benefit from this, and I was looking forward to migrating it to the new pattern matching feature. But I can't find any word on whether this is being revisited. That's disappointing. [1] https://www.python.org/dev/peps/pep-0591/ https://www.python.org/dev/peps/pep-0591/
- 3pt14159 5y agoThis is precisely the thing I do not want from python. Subclassing is super useful in convoluted tests where fakes are superior to mocks. I don't like being told "you can't do this" by some library's code.
- scoopertrooper 5y agoIf it's enforced at the type-level then, don't check types during your test runs? shrugs
- _dain_ 5y agoIt would be enforced by the optional static type checker, not the language runtime.
- Spivak 5y agoAnd if you want to enforce it at runtime you already can! class Final(type): def __new__(cls, name, bases, dct): if any(isinstance(base, Final) for base in bases): raise TypeError("No!") return type.__new__(cls, name, bases, dct) class NoSubclasses(metaclass=Final): pass class WillThrow(NoSubclasses): pass
- qwertox 5y agoAlone the indentation makes the code clearer to read. Generally it seems to clean up the code quite a bit in comparison to the if-statements. I would like to have seen some benchmarks for it, though, specially for things like the gaming loop, where, compared to the if-variant, the type of the event has to be checked for every case, since grouping is not possible. This specific game loop is not adequate, since input events are rare, but if this were to be used with Scapy for example, it would really start to matter, like when iterating over raw socket events.
- benhoyt 5y agoSee my other comment with some quick benchmarks: https://news.ycombinator.com/item?id=28601862 https://news.ycombinator.com/item?id=28601862 Yeah, the match is slower than if-else in that case because they're not grouped. However, the PEP points out that faster implementations are possible -- it would not have to check the type each time if it already knows it can't match. I guess some of those optimizations are left for later.
- make3 5y agoit's amusing that Python is going from no switch case to this ultra powerful version of it
- jefftk 5y agoThe key benefit of pattern matching is not code that is more concise, but code that is more likely to be correct. Consider their first example, interpreting a command in a textual game. In many places the logic is divided into a few pieces: check that there are the right number of arguments, do something with some of them, pull off the rest, etc. It's really easy to make mistakes with this kind of code, where your conditions don't quite align. With pattern matching, you write a single pattern for a case, and I would expect this to give many fewer bugs.
- mikepurvis 5y agoOn the theme of skepticism, though, I would worry that there may only be a fairly narrow band of complexity for this type of logic where Python 3.10's pattern matching is the ideal solution, past which you want some kind of grammar and a proper parser that just spits out a polymorphic object with a do_thing() method.
- babel_ 5y agoI would say that the key benefit for this isn't really in making mature codebases nicer (though it can), but rather for rapidly-developing codebases, especially when doing prototyping or iterative development. The structured nature and reified syntax works alongside the ability to quickly change the spec, as otherwise you would need to pick apart and reverse-engineer someone's in-the-moment if/elif (likely nested) when there's a change. The structure being based on first-class concepts in the language means that its meaning is common to all code, whereas the post went out of its way to specify how you'd "organise this differently as if/elif", which is clearly something requiring skill and experience (which experts always overestimate the level of), and would produce varying results depending on the person. This will be taught at a more intermediate level of Python, leaving the complexity only skin-deep, akin to teaching pattern matching in Haskell or such. After all, the full complexity isn't necessary for most users, the vast majority of people will only read the tutorial PEP and not the full description and grammar, while those advanced users can make use of this to make life even easier. Combined with typing, this means tools can do more exhaustive checks and catch bugs pre-emptively, In my opinion, this will be a boon for clean programs that are easy to read and pleasant to write. In line with what the post says about usage settling down in a couple years, libraries and APIs will find the right balance with time, whilst making it easier and faster to write the thing you meant correctly, especially as this is a boon to tooling since you're quite literally indicating the structural intention of your code. I see this alongside decorators (used sparingly), comprehension (used one or two levels deep), and types as helping people write the code they want to write, what they mean to write, and the language helping them in that endeavour. Just as we finally have dict.__or__ and dict.__ior__, it's something that lets people write what they intend, rather than the scaffolding that is needed to support it. I personally think that's a positive, and the kind of feature that will become very natural for many people to use in Python even if they don't have a background in languages that have pattern matching.
- incrudible 5y agoType-safe tagged unions, one of the nicest features of Typescript: interface Foo { type: "foo"; name: string; } interface Bar { type: "bar"; size: number; } type Variant = Foo | Bar; function tell(x: Variant) { switch (x.type) { case "foo": // x now has type Foo console.log(`The name is {x.name}`); break; case "bar": // x now has type Bar console.log(`The size is {x.size.toFixed(2)}`); break; default: // statically unreachable } } Hope to see this in Python type checkers as well.
- NoThisIsMe 5y agoTypescript is so weird. Like this is cool I guess but I'd much rather just match on `Foo` or `Bar` directly. But Typescript doesn't have pattern matching so it compensates with this bizarre paradigm of enforcing dynamic type checks statically.
- jakear 5y agoYou can check instanceof of course, but the idea behind doing this is that object literals and raw data from JSON/whatever can be treated as a first class entity, rather than mucking around with all the boilerplate dataclass junk a lot of languages get tangled up in.
- azkae 5y agoYou can already do this without pattern matching: from typing import Union, NoReturn class Foo: name: str class Bar: size: int Variant = Union[Foo, Bar] # or `Foo | Bar` in Python 3.10 def assert_never(x: NoReturn) -> NoReturn: # runtime error, should not happen raise Exception(f'Unhandled value: {x}') def tell(x: Variant): if isinstance(x, Foo): print(f'name is {x.name}') elif isinstance(x, Bar): print(f'name is {x.size}') else: assert_never(x) mypy returns an error if you don't handle all cases.
- incrudible 5y ago
- madis 5y agoWtf is non-structural pattern matching? Pattern ~ structure. It's like saying eruptive explosion. Stop trying to look more important and smart by using more (unnecessary) words.
- de_keyboard 5y agoPattern matching can be done on run-time properties, see F# Active Patterns
- amyjess 5y agoHonestly I'm just disappointed that I can't match against random locals. I'm at the point where I'm willing to pay someone to write a preprocessor that'll let me put switch/case statements in my code and then run the preprocessor and have it convert them to if/elif/else statements.
- hda111 5y agoToo much complexity now. This will make languages like Go more relevant.