[HN Gopher] C++ Pattern Matching Proposal [pdf]
       ___________________________________________________________________
        
       C++ Pattern Matching Proposal [pdf]
        
       Author : je42
       Score  : 149 points
       Date   : 2020-01-02 07:25 UTC (1 days ago)
        
 (HTM) web link (www.open-std.org)
 (TXT) w3m dump (www.open-std.org)
        
       | rb808 wrote:
       | Its seems all languages are just copying each other at this
       | point. I know C++ hates to be left out of anything so maybe this
       | is appropriate, but to me its really destroying the ecosystem.
       | 
       | It was great to have different languages having different
       | paradigms but now you can do everything in everything and code
       | bases I'm working on are a confusing mess.
        
         | jokoon wrote:
         | This is a codebase problem, not a language one.
         | 
         | If there's a good idea, why not use it?
        
         | emodendroket wrote:
         | I think it's great. No need to switch languages when you just
         | need some feature here and there.
        
         | agumonkey wrote:
         | > each other
         | 
         | by each other you mean the ml world right ? :p
        
           | vmchale wrote:
           | Functional programming seems to be taking on the world (J
           | inspiring NumPy, ML features being used everywhere).
        
             | gdxhyrd wrote:
             | Functional languages are nowhere to be seen compared to the
             | rest.
             | 
             | Some subset of features inspired in them are used in some
             | languages, but that has nothing to do with functional
             | programming taking over.
        
               | agumonkey wrote:
               | Honestly even if we're far from FP as mainstream (which I
               | don't even wish). I woudln't have bet a dollar that so
               | much features from lisp/ml would have crossed over this
               | fast (I mean destruct, lambda, rest args, immutable let
               | by default, option chaining ..).
        
               | vmchale wrote:
               | > option chaining
               | 
               | Where'd that come from? I thought that was monadic-do
               | from Haskell.
        
               | agumonkey wrote:
               | well I include haskell is the ml family (I admit it's
               | twisting the words)
        
               | dnautics wrote:
               | With Hooks, React has gone full FP, so, basically, the
               | war is lost. Try finding a bootcamp programmer that
               | wasn't taught React.
               | 
               | Sure, you can still build object components, but it's
               | informally frowned upon.
        
             | agumonkey wrote:
             | Yes, haskellers will soon be celebrities.
        
         | oefrha wrote:
         | What's the downside of copying the good stuff? I think the
         | examples aren't confusing at all and are perfectly readable by
         | anybody.
         | 
         | Honestly I'll be deeply ashamed as a Python programmer writing
         | cascading ifs when even C++ gets pattern matching. (Yeah, I
         | know all the arguments against it.)
        
         | typon wrote:
         | This logic doesn't make sense. If something increases
         | productivity and code quality, why wouldn't languages copy it?
         | Ideally languages should also remove unnecessary features,
         | which is actually the thing that makes C++ a confusing mess:
         | it's prioritization of backwards compatibility over keeping
         | complexity low.
        
           | pjc50 wrote:
           | > languages should also remove unnecessary features
           | 
           | Languages are effectively immutable. Unless you can reach out
           | and edit every single piece of code that breaks when you
           | remove a feature, you can't remove a feature from a language.
           | You can only create a new, almost identical language, and
           | then spend a decade migrating people. This is what happened
           | to Python2/3.
           | 
           | Very few things have been successfully deprecated in C or
           | C++. Even massive security holes in the standard library.
        
           | vmchale wrote:
           | > it's prioritization of backwards compatibility over keeping
           | complexity low.
           | 
           | There _are_ other languages on less-shaky foundations, but
           | people don 't use them for various legitimate and
           | illegitimate reasons.
        
         | de_watcher wrote:
         | C++ was always the language for constructing paradigms you
         | choose with underlying mechanism you want.
        
           | pjmlp wrote:
           | Just like PL/I, Object Pascal, Ada, Lisp,...
           | 
           | C++ wasn't the first multi-paradigm language, and it won't be
           | the last.
        
         | dgellow wrote:
         | But in this case, pattern matching seems way easier to follow
         | and evaluate mentally than the verbose visitor approach already
         | in the language, or something based on switches/if statements.
         | That seems to be a good way to reduce the amount of confusing
         | mess, at least for new developments.
        
         | specialist wrote:
         | We design our languages which then design us. Variant of
         | Churchill's quote about rebuilding their parliament chambers
         | exactly as before.
         | 
         | Maybe think of language design as a search thru an n-dimension
         | problem space.
         | 
         | There's the perennial trilemma of functional (LISP), imperative
         | (APL), and object oriented (Simula), where your new language
         | lands somewhere within that triangular design space.
         | 
         | Then add extra dimensions for type systems. Nominal vs
         | structural vs whatever.
         | 
         | Then add some more for ideas swiped from declarative (SQL,
         | VRML, LINQ), stack-based (Forth), REPLs (Logo), constraints
         | (Prolog), and whatever else people cook up.
         | 
         | Ya, the churn is nutty making. But it's also awesome at the
         | same time.
        
         | [deleted]
        
         | vmchale wrote:
         | > all languages are just copying each other at this point. I
         | know C++ hates to be left out of anything so maybe this is
         | appropriate, but to me its really destroying the ecosystem. It
         | was great to have different languages having different
         | paradigms but now you can do everything in everything
         | 
         | I don't think you _can_ do everything in everything. Try
         | working with lazy immutable data structures in Rust, for one.
         | 
         | Or look at Dart - now has "non-nullable types," monadic error
         | handling (sort of), but of course the whole thing is on shaky
         | foundations so what's it worth?
        
           | [deleted]
        
           | ChrisSD wrote:
           | > Try working with lazy immutable data structures in Rust,
           | for one.
           | 
           | Why is that an issue?
        
             | vmchale wrote:
             | Well, it doesn't have the runtime to support laziness
             | properly.
        
               | fctorial wrote:
               | Why would lazy data structures need a runtime? Some kind
               | of GC is necessary for immutable data structures, but
               | wouldn't iterators and generators be enough for
               | implementing laziness?
        
               | vmchale wrote:
               | > wouldn't iterators and generators be enough for
               | implementing laziness?
               | 
               | If you can implement lazy finger trees with iterators I'd
               | love to see it :)
        
               | ChrisSD wrote:
               | Sure, it doesn't have much of a runtime at all but Rust
               | does give a firm foundation to build on. Using an
               | `Option` or the `once_cell` library is pretty ergonomic.
               | At worse you use a function call to get a reference to
               | the value instead of using it directly.
        
               | DougBTX wrote:
               | Agreed, Rust can certainly handle lazy evaluation. All
               | the iterator types for example are lazy, hence the
               | .collect() method which eagerly evaluates a lazy
               | collection.
               | 
               | Hiding the fact that a lazy value needs to be mutated to
               | initialise it is a little more work (since a nice API
               | lets the user treat the value as if it doesn't need to be
               | mutated), but is certainly possible.
        
               | vmchale wrote:
               | > All the iterator types for example are lazy,
               | 
               | It's not proper laziness as defined in Okasaki's
               | thesis/book. One needs more complex things like lazy
               | finger trees.
        
           | derefr wrote:
           | > Try working with lazy immutable data structures in Rust.
           | 
           | I don't think this is _that_ hard; you "just" need to
           | construct the data structures as elements of an object-graph
           | data structure, and then retrieve your data through an
           | explicit thunk of the object-graph itself.
           | 
           | In lazy languages the object-graph data structure is
           | implicit, but that doesn't mean that the Rust version of the
           | _call site_ code needs to be any more verbose. It's just the
           | definitions of the data structures themselves that would be
           | more unwieldy. (And you could probably build some generic
           | lazy container types and mostly work with those.)
           | 
           | Think: what Objective-C does with autorelease-pool objects.
        
           | steveklabnik wrote:
           | Here's what immutable data structures look like in Rust:
           | https://docs.rs/im/14.1.0/im/
        
             | vmchale wrote:
             | None are lazy, however.
        
         | nn3 wrote:
         | It's like human languages. They adopt useful words from each
         | other all the time too. Why shouldn't programming languages do
         | the same?
        
           | smitty1e wrote:
           | Restated, nobody under the sun can write "The last, final
           | language anyone could ever need."
           | 
           | Think of programming languages as a seminar where designers
           | are crafting that Ur-language between themselves, and folks
           | like me in the peanut gallery look on.
        
         | Ragnarork wrote:
         | What is destroyed exactly by adding a feature to a language
         | that could easily improve readability (which said language
         | reaaaally needs), which you can also opt not to use if you
         | don't like?
        
           | jarfil wrote:
           | You can't opt not to use it if you have to work with someone
           | else's code which does use it.
        
             | Ragnarork wrote:
             | True, I should have been more precise.
             | 
             | What I meant is the language does not force this on you as
             | The Right Way To Do Things(tm) and thus it mostly boils
             | down to organizing with peers and agreeing on a consistent
             | set of guidelines (which goes well beyond language
             | features...)
        
           | MaxBarraclough wrote:
           | There's a very good answer to that question: simplicity,
           | minimalism, and stability.
           | 
           | C++ is a huge, complex language. It's probably its greatest
           | downside. Making it _even more_ complex, should only be done
           | with very good reason.
           | 
           | If you doubt this, consider the continued popularity of C, a
           | thoroughly anaemic language by today's standards, with no
           | clear advantages over C++ except for its simplicity,
           | minimalism, and that the language changes _very_ slowly.
           | Well, that and its existing adoption levels. It 's not quite
           | the case that every feature C has is also in C++, but it's
           | very close, and I can only name one exception: variable-
           | length arrays (an unpopular addition to C) are not officially
           | supported in C++.
           | 
           | C++'s complexity means that:
           | 
           | * It's very difficult to learn. It's extremely difficult to
           | learn well. It's just about impossible to learn in its
           | entirety. This isn't an exaggeration. (Andrei Alexandrescu
           | might be the closest we have to someone who knows _all_ of
           | C++. He 's a world famous C++ expert. Mortals don't stand a
           | chance.)
           | 
           | * Different C++ programmers know (and write in) different
           | subsets of the language. Good C programmers know essentially
           | all of C. (I'll admit I'm weak on C's bitfields, and I
           | couldn't tell you every subtlety of its memory model, but
           | when it comes to C++, there may be areas of the language I've
           | never even heard of.)
           | 
           | * C++ style guides (such as Google's one, or LLVM's one) are
           | long and complex documents, by necessity
           | 
           | * We will never have a fully complete C++ compiler that truly
           | matches the language spec. This undermines the spec; the
           | language you're _really_ using depends on your C++ compiler.
           | To put that another way: portability is harmed because
           | different C++ compilers cannot be relied upon to support the
           | same language features.
           | 
           | * C++ compilers are more prone to arcane bugs, than C
           | compilers
           | 
           | * Different C++ compilers have different arcane bugs, harming
           | portability
           | 
           | * It's far easier to develop tools for C than for C++
           | (compilers, IDEs, etc)
           | 
           | * There are more C compilers out there than C++ compilers,
           | especially for targets like PIC, or for very obscure
           | platforms, or for particular needs such as safety-critical
           | work. There's even a formally verified C compiler
           | ('CompCert') with near-complete support for C99's features. I
           | doubt there will ever be a formally verified C++ compiler.
           | 
           | * C is easier to mechanically reason about; there are more
           | static-analysis tools for C than for C++
           | 
           | * If C++ were simpler it might have given rise to stable
           | ABIs, the way C has. Instead, even different versions of the
           | same C++ compiler might not be interoperable.
           | 
           | * It's less predictable regarding performance. Template
           | metaprogramming can bloat your binaries for seemingly no
           | reason. In C however, all features of the language map
           | naturally to assembly; the programmer can generally predict
           | roughly what assembly will be generated. This matters to
           | those working with operating systems, graphics, high-
           | performance programming, or where side-channel attacks are a
           | security concern.
           | 
           | C++ is also faster-moving than C, meaning:
           | 
           | * It takes more work to maintain your skills for reading
           | other people's code
           | 
           | * Code can age. Old code looks different from new code,
           | unless it's actively maintained, which means work and risks
           | new bugs. If the language rarely changes, this problem goes
           | away.
           | 
           | * If you're developing a compiler, you'd rather a stable
           | language like C, so that you don't have to make a career out
           | of keeping up with the latest additions to the language.
           | Keeping up with the additions to C++ is more than any one
           | compiler-engineer could hope to do.
           | 
           | There are very few 'conservative' languages like C (there are
           | also Scheme and Forth), but it can be a language's greatest
           | strength. Zig is hoping to be another such language, but
           | we'll have to see if it succeeds.
           | 
           | With all of that said, I tend to favour C++ over C, and I
           | _really_ like pattern-matching. It 's something that cannot
           | really be 'faked' with templates or macros. (Another personal
           | favourite feature of mine, named arguments, is similar in
           | that regard.) I think it's rather silly that the major OOP
           | languages have until recently completely ignored this
           | brilliant language feature from the functional programming
           | world, as if it adds nothing over switch/case. Even D, an
           | extremely feature-rich language, still lacks pattern
           | matching.
        
         | bluGill wrote:
         | Almost all languages are turning complete. The only questions
         | is the syntax: convenience of writing it and how fast it runs
         | on the machine (either/both compile time and run time)
         | 
         | When you have a syntax that you like for whatever reasons
         | (including because you have a lot of legacy code written in it)
         | it makes sense to extend the syntax where possible to make it
         | more convenient if you can do so within the constraints of
         | performance.
        
       | jokoon wrote:
       | I don't understand why some people don't like C++.
       | 
       | It almost seems like they forget what it means to compile to
       | machine code.
       | 
       | I can say I have some sort emotional attachment to python, but I
       | can't deny that C++ is just a more capable language, but at least
       | I can admit that I'm just not always competent to always write
       | C++.
       | 
       | Like most people say "just use the parts of C++ you need".
        
         | zyxzevn wrote:
         | C++ is for real men https://i.redd.it/s6q46do7ce841.png
        
         | dullgiulio wrote:
         | Thankfully C++ is far from the only language that compiles to
         | native.
         | 
         | Many others don't even have the same insane "features".
        
           | jokoon wrote:
           | There are not that many languages with good support that
           | compile to native.
        
             | pjmlp wrote:
             | Java (yes it does, since around 2000), .NET (NGEN since
             | v1.0, Mono AOT, IL2CPP, .NET Native), D, Eiffel,
             | FreePascal, Delphi, RemPascal, Swift, OCaml, Haskell, Lisp,
             | Ada, Scheme, Basic, Go, Fortran.
             | 
             | Just a couple of possible languages, there are many more if
             | we take out the good support constraint.
        
         | pjmlp wrote:
         | I love C++, just would rip off the copy-paste compatibility
         | with C89 if a genie would give me a wish about what to take out
         | from the language.
        
       | greg7mdp wrote:
       | Love this proposal! C++ is getting better in leaps and bounds.
        
         | vunie wrote:
         | It's amazing what credible competition can do. If only C had
         | the same kind of pressure.
        
           | eps wrote:
           | Don't you even dare. C is near-perfect in the simplicity of
           | its core. You want bells and whistles, you hook up a library.
        
             | weberc2 wrote:
             | Could you refer me to a good/standards-compliant library
             | for typesafe generic lists, hashmaps, pattern matching,
             | closures, etc?
        
               | huhtenberg wrote:
               | You are missing the main strength of C - the transparency
               | and predictability of what machine code gets generated
               | from the source code.
               | 
               | When you write "a + b", you won't end up with kilobytes
               | of machine code just because someone in some header
               | overloaded the + operator.
               | 
               | Ditto for template-style generics and overloaded
               | functions. If you call a function and it doesn't exist,
               | it won't get auto-generated for you on the fly. You get
               | an error. You want a function, you define that function.
               | That's not the flaw of the language. That's its strength.
               | 
               | Ditto for switch-case constructs.
               | 
               | Ditto for closures.
               | 
               | All of these constructs, should they be added to the
               | language, will result in a compiler generating heaps of
               | code from a simple code snippet. But this will no longer
               | be C, because in C what you see is what you get.
        
               | Jataman606 wrote:
               | If you call function and it doesnt exist you get a
               | warning "implicit declaration of function". Unless you
               | use additional compiler flags.
        
               | huhtenberg wrote:
               | Not since C99.
               | 
               | But even regardless of that you still get a linking
               | error.
        
               | weberc2 wrote:
               | I'm not missing anything, I'm responding to a specific
               | claim--that libraries allow C to compensate for missing
               | language features. This is patently false irrespective of
               | the merits of the features in question.
               | 
               | That said, I think your entire criteria for determining
               | whether a language or feature is good boils down to its
               | intuitiveness to experienced C programmers, which seems
               | like a particularly poor, subjective criteria and it
               | probably doesn't actually even hold for C considering all
               | of the security issues and undefined behaviors that are
               | introduced by and continue to surprise experienced C
               | programmers.
               | 
               | For my money, closures, pattern matching, and templates
               | (not any implementation in particular) are easy enough to
               | reason about and much better than the corresponding bugs
               | they address, but to each his own.
        
               | reggieband wrote:
               | > I think your entire criteria for determining whether a
               | language or feature is good boils down to its
               | intuitiveness to experienced C programmers ...
               | 
               | I see this tired argument over and over. It is especially
               | thrown out when some esoteric language syntax is
               | criticized.
               | 
               | In this case it seems to miss the authors point entirely.
               | My understanding of his argument is that the C language
               | maps reasonably well to machine code. Adding new features
               | to the language could hamper that intuitive mapping
               | between the language syntax and the actual machine code
               | generated.
               | 
               | A valid criticism (which others have made) is that the
               | actual mapping between C code and machine code on modern
               | machines is far less intuitive than one might expect.
               | Another valid response would be a demonstration that
               | "closures, pattern matching, and templates" can be
               | intuitively mapped directly to machine code.
               | 
               | I would be happy if I never see the "you are too blinded
               | by your own language to understand" argument ever again.
               | It borders on ad-hominem and extends no benefit of doubt
               | to the original author.
        
               | hayez1 wrote:
               | >For my money, closures, pattern matching, and templates
               | (not any implementation in particular) are easy enough to
               | reason about and much better than the corresponding bugs
               | they address
               | 
               | Then write C++ only using closures, pattern matching and
               | templates outside of the C feature set.
        
               | weberc2 wrote:
               | Oh no, did my previous comments read as an exhaustive
               | list of issues with C?
        
               | atilaneves wrote:
               | > the transparency and predictability of what machine
               | code gets generated from the source code.
               | 
               | This gets said a lot, but unless you're writing C code
               | for a microcontroller (or a PDP11), that isn't even close
               | to being true.
               | 
               | > When you write "a + b", you won't end up with kilobytes
               | of machine code just because someone in some header
               | overloaded the + operator.
               | 
               | You can't overload "+" for integers or floats. If you add
               | two numbers together, you get what you expect, always. If
               | they're not numbers, and somehow you expected `a + b` to
               | work without an overloaded operator, then I don't know
               | what to say.
               | 
               | > You want a function, you define that function.
               | 
               | Then you define it again for another type, then again,
               | then again...
               | 
               | Then you write a macro and now your colleagues hate you.
               | 
               | > All of these constructs, should they be added to the
               | language, will result in a compiler generating heaps of
               | code from a simple code snippet
               | 
               | Not necessarily.
        
               | huhtenberg wrote:
               | > _This gets said a lot,_
               | 
               | No, this actually doesn't get said a lot, however the
               | simplicity of C compilation semantics is one of its
               | biggest strengths.
               | 
               | > ... _but unless you 're writing C code for a
               | microcontroller (or a PDP11), that isn't even close to
               | being true._
               | 
               | Do humor us with an example of a C code that compiles
               | into something that is "not even close" to what you'd
               | reasonably expect.
        
             | jupp0r wrote:
             | No, you write macros (duck and hide).
        
             | doboyy wrote:
             | Typesafe generics via a better void* would make me super
             | happy. There are definitely other quality of life
             | improvements that could be added or reworked that wouldn't
             | affect the simplicity too much.
        
               | sdegutis wrote:
               | I'd say Rust is the improvements to C that I've always
               | been wanting: better type safety, real generics, first-
               | class closures, and OOP without inheritance, only using
               | structs to structure data, leaving code execution to just
               | functions. It's what I hoped Go would become. (Take with
               | grain of salt, I'm just starting to learn Rust.)
        
               | doboyy wrote:
               | I really don't like the monomorphization approach to
               | generics (I think that's the concept?), where the
               | function/struct essentially gets duplicated for each
               | type. It seems to mess with linkage, increase binary
               | sizes, and increase compile times.
               | 
               | Other than that, Rust does seem to be an improvement and
               | less... stressful to program in.
        
               | tick_tock_tick wrote:
               | You can always role dynamics dispatch yourself
        
               | twic wrote:
               | Dynamic dispatch is in the language too.
               | use core::fmt::Display;                  fn
               | show_monomorphic<T: Display>(first: T, second: T) {
               | println!("{} then {}", first, second);         }
               | fn show_polymorphic(first: &dyn Display, second: &dyn
               | Display) {             println!("{} then {}", first,
               | second);         }                  pub fn main() {
               | show_monomorphic(17, 23);
               | show_monomorphic("fnord", "slack");
               | show_polymorphic(&42, &"quirkafleeg"); // mixed types!
               | }
               | 
               | There are things you can do with each that you can't do
               | with the other, but they are often both viable choices.
        
             | billfruit wrote:
             | C has many rough spots too, especially in organising large
             | and complex programs. There is always scope for innovation
             | and improvements.
        
               | user5994461 wrote:
               | >>> There is always scope for innovation and
               | improvements.
               | 
               | but not in C because C has no scope
        
           | vmchale wrote:
           | > If only C had the same kind of pressure.
           | 
           | ATS :p
        
             | fluffything wrote:
             | Who is using ATS in production?
             | 
             | When I learned it I wondered why would somebody use it
             | instead of Rust or Idris.
        
       | antiquark wrote:
       | Their example #4.3 won't always produce the same result as the
       | "if" version, because x==x and y==y could return false due to
       | operator overloading.
        
         | wereHamster wrote:
         | If you overload the == operator such that x==x is false then I
         | call UB. Reading and understanding such a codebase would be a
         | nightmare.
        
           | 0xffff2 wrote:
           | Is it actually UB or just stupid? I've never tried to dig in
           | and understand C++ at the standards level, so I don't know,
           | but you don't get to just "call" UB; it has to be UB by the
           | standard.
        
             | Karliss wrote:
             | By itself it is just stupid. Standard defines
             | "EqualityComparable" property and which parts of STL
             | require it to be satisfied. There even some places where it
             | notes that EqualityComparable property isn't required. It
             | is much easier to get UB by having bad < operator.
        
           | fyp wrote:
           | NaN == NaN is always false (at least in other languages I
           | know).
        
             | kibwen wrote:
             | This will be the case in any language that confirms to IEEE
             | 754 (so, hopefully, all of them (because the only thing
             | more confusing than properly implementing IEEE 754 is
             | improperly implementing your own bespoke subset)). This
             | property of NaN is required by the spec (and is, for
             | example, why Rust's default HashMap refuses to accept
             | floating point numbers as keys).
        
         | greg7mdp wrote:
         | There is no x==x in example 4.3. This is like structured
         | binding where x binds to the first element of the tuple.
        
       | specialist wrote:
       | I _really like_ the proposal for matching values (integral,
       | strings, tuples). It 's very lispy. Explicit representation
       | (intrinsics?) of a map used as an expression.
       | 
       | Though I would prefer the keyword 'choose' over 'inspect'.
       | 
       | --
       | 
       | I have noob questions about pattern matching on (polymorphic)
       | types. Please humor:
       | 
       | It's syntactic sugar for std::is_base_of<> (Java's instanceof),
       | right?
       | 
       | This is a consequence of C++ (and Java's) nominal type system,
       | right?
       | 
       | So is pattern matching on types necessary (useful) for structural
       | type systems?
       | 
       | I ask because a friend has been advocating structural typing.
       | He's more of a language theorist whereas I'm more of a language
       | mechanic (I don't even rate as a language engineer). While I'm
       | totally on board with whatever he says, I just hope to better
       | grasp the changes.
        
       | toolslive wrote:
       | compare this proposal to the pattern matching you get from
       | Haskell or OCaml and weep.
       | 
       | for example (OCaml):                   let imply = function
       | | (true,false) -> false            |   _          -> true
        
         | macintux wrote:
         | Pattern matching across multiple function heads (ML, Erlang) is
         | incredibly liberating. I hear Haskell has it but it's not
         | idiomatic, and I think Elm doesn't support it at all.
         | Frustrating.
         | 
         | I've found half-hearted pattern matching solutions like Scala
         | quite disappointing.
        
           | nv-vn wrote:
           | OCaml, F#, ReasonML don't support that, I think it's unique
           | to SML in the ML family.
        
             | macintux wrote:
             | Interesting, thanks. SML is my only direct exposure to the
             | family, and I recall a conference speaker mentioning that
             | ML (perhaps SML) programmers weren't fond of the feature.
        
           | lalaithion wrote:
           | Can you give an example of the pattern matching in ML and
           | Erlang that is not idiomatic in Haskell?
        
             | macintux wrote:
             | It's the multiple function heads which (again, I've been
             | informed, no direct knowledge) is discouraged.
             | 
             | e.g. https://github.com/macintux/advent-of-
             | code-2019/blob/master/...
        
               | p0llard wrote:
               | You mean a piecewise definition of a function? I don't
               | think this is unidiomatic or discouraged in Haskell at
               | all.
        
               | macintux wrote:
               | There's some indirect discussion here that seems to
               | contradict that, but I certainly could be wrong.
               | 
               | https://github.com/elm/compiler/issues/973
        
               | Iceland_jack wrote:
               | That's in the context of Elm, Evan gives his reasons but
               | in the context of Haskell such multi-line equations are
               | very common and normal Haskell style.
        
       | typon wrote:
       | Why call it inspect instead of match?
        
         | Sharlin wrote:
         | Inspect breaks less existing code.
        
           | kevin_thibedeau wrote:
           | They ought to use "_Inspect".
        
         | de_watcher wrote:
         | Because of regex.
        
           | mkl wrote:
           | The regex header doesn't seem to define anything called
           | "match". It is probably a common variable name though. To me
           | "inspect" implies the wrong action, so it would be nice if
           | there was a better keyword.
        
       | crazypython wrote:
       | How does this work compared to ML's signatures?
        
       | thurn wrote:
       | anything in here about exhaustiveness checking? In my mind that's
       | half the value of pattern matching.
        
         | SloopJon wrote:
         | From the Exhaustiveness and Usefulness section:
         | 
         | "inspect can be declared [[strict]] for implementation-defined
         | exhaustiveness and usefulness checking."
         | 
         | "having a __: case makes any inspect statement exhaustive."
         | 
         | "any case that comes after a __: case would be useless"
        
           | jobstijl wrote:
           | Why wouldn't they make it [[strict]] by default?
        
             | atilaneves wrote:
             | Because it's C++, and the defaults must suck
             | (std::vector::at anyone?)
        
       | amelius wrote:
       | Does the D language have pattern matching?
        
         | [deleted]
        
         | atilaneves wrote:
         | No.
         | 
         | But it can be done as a library. Granted, it's not the same as
         | 1st class support, but it's pretty good:
         | 
         | https://github.com/pbackus/sumtype
        
       | ape4 wrote:
       | I know this is different than the regex library but just thought
       | I'd mention...
       | 
       | Declaring regex's like javaScript with be cool.
       | var myre = /^hello\w*/;         std::regex myre("^hello\\\w*");
        
         | tambre wrote:
         | Use raw strings.                   std::regex
         | myre(R"(^hello\w*)");
        
         | bstamour wrote:
         | You can add a literal operator:                   auto operator
         | "" _r(char const* str, unsigned long) {           return
         | std::regex{str};         }
         | 
         | To avoid all the backslashes, you can use a raw string literal:
         | int main() {           auto myre = R"(^hello\w*)"_r;         }
        
       | 0xffff2 wrote:
       | Just skimming section 4, this really just looks like _even more_
       | syntax being added to the language without enough benefit to
       | justify the additional complexity. At this point, I think I 've
       | made the decision to just stick with C++11 indefinitely and
       | backport the rare useful feature. I don't want to have to
       | memorize all of this extra stuff.
        
         | xscott wrote:
         | What we need is a compiler flag that says, "give me the good
         | parts of C++11/14, but leave out the bad stuff from C++98, and
         | fix some of the inconsistency quirks from trying to be
         | compatible with C89".
        
           | 0xffff2 wrote:
           | Even given the inevitability of disagreements about which are
           | the "good parts", I'm pretty sure this would be my "standard
           | version" of choice if it was available.
        
             | zozbot234 wrote:
             | The "C++ Core" guidelines get pretty close to standardizing
             | the 'good parts' of C++.
        
               | 0xffff2 wrote:
               | I'm aware of the guidelines and apply them, but that's
               | only a small fraction of the problem. What I need is a
               | compiler flag that _enforces_ the guidelines so that I
               | can write it into my software management docs in place of
               | "-std=c++11".
        
           | [deleted]
        
           | karlicoss wrote:
           | I think core guidelines [0] are aiming that. Some of it is
           | already supported by tools like clang-tidy, but as far as I
           | understand the ultimate goal is to have some sort of flag
           | (e.g. --sane) that would only accept 'reasonable' subset of
           | c++ and reject legacy stuff.
           | 
           | However this document is a bit raw, lots of todos, so I'm not
           | sure how close are we to such flag.
           | 
           | [0]
           | https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines
        
             | mlvljr wrote:
             | There is something even better: http://www.open-
             | std.org/jtc1/sc22/wg21/docs/papers/2019/p188...
             | 
             | cheers from the shadowland :)
        
             | ATsch wrote:
             | I think the only good way to do this is off of the back of
             | C++ Modules. Having it as a compiler flag means that all
             | files in a project, including libraries, must be compliant.
             | 
             | With C++ modules putting an end to the naive #include,
             | translation units could specify the C++ specification they
             | are compliant with, and hence gracefully remove or add new
             | features on a translation-unit level.
        
               | steveklabnik wrote:
               | This is the idea for the 'epochs' proposal https://vittor
               | ioromeo.info/index/blog/fixing_cpp_with_epochs...
        
           | harikb wrote:
           | This works so long as entire build is your own code. Once you
           | get to libraries written by someone else who happens to have
           | a different "wish list", I would guess this flags idea
           | wouldn't work well.
        
             | falcor84 wrote:
             | Could you please explain more about the process you're
             | using? Are you compiling external dependencies as an
             | integral part of building your own code?
        
               | petters wrote:
               | This is the only sane way of using C++. All C++
               | dependencies in the same repo, because there is no
               | standard C++ ABI.
               | 
               | I am compiling my C++ codebase with gcc, clang,
               | emscripten to wasm, visual studio. Impossible if all
               | dependencies are not present in a "third-party" folder.
               | 
               | Google's Abseil library is intended to be used this way.
               | 
               | Otherwise, use the C ABI between dependencies.
        
               | gpderetta wrote:
               | > standard C++ ABI.
               | 
               | All major OS have a standard, very stable C++ ABI. Some
               | of them also guarantee a stable ABI for the library
               | components.
               | 
               | Of course you cannot use a library built for, say,
               | Windows on Linux but that's true for all languages.
        
               | johannes1234321 wrote:
               | Assuming all things use the same rtti and exception
               | settings and all are using same C++ standard library
               | (libstdc++ vs libc++)
               | 
               | And then there are other flags - for instance when
               | gcc/libstdc++ broke std::string in order to switch from a
               | recounted string to a non-refcounted with small string
               | optimisation in order to be C+11 compatible ...
               | 
               | Sure, there are system defaults, but things vary and
               | often recompiling everything and statically linking
               | avoids those issues.
        
               | jdsully wrote:
               | For windows that is a _very_ recent change. The ABI used
               | to change with every compiler rev.
               | 
               | Further without buyin from the actual standard there's no
               | gurantee a breaking change won't be forced by the
               | standard at some point.
        
               | pjmlp wrote:
               | Not for libraries exposed as DLL or COM.
               | 
               | Although one might argue that is only a C++ subset.
        
               | jdsully wrote:
               | COM is based off of the C ABI not C++. This was done
               | specifically because C++ does not have a stable ABI.
        
               | pjmlp wrote:
               | There is no such thing as C ABI, rather Windows ABI,
               | which you can even select several calling conventions,
               | including Pascal based one.
               | 
               | COM is based on the way Visual C++ lays out the VMT, and
               | only masochists use it from bare bones C.
        
               | derefr wrote:
               | They're using some header-only libraries, presumably.
               | Which, after all, is one of the only _unique_ benefits of
               | C++ that would lead you to choose it for a green-field
               | project over, say, Rust. Header-only template libs +
               | link-time WPO = inlining of template-instantiated
               | monomorphized methods to their type-strict callers. This
               | is the feature that leads e.g. LLVM to be written in C++.
        
               | steveklabnik wrote:
               | Rust doesn't have headers, but can still do this.
        
               | CreRecombinase wrote:
               | Anything in your headers is (more or less equivalent to
               | being) copy-pasted into your own code. Many dependencies
               | are header-only (which is the only option I'm aware of if
               | the code is templated).
        
             | 0xffff2 wrote:
             | It's just another standard option. Do libraries that are
             | compiled with std=c++14 work with application code compiled
             | with std=c++11? What about the other direction? (I don't
             | actually know because I do build everything from source.)
             | You would basically just be adding a new `std=good` option.
        
               | CJefferson wrote:
               | The problem with c++ is many libraries are mostly header
               | files, and they are combined with your code basically by
               | cut+paste, so you can't rewlly seperwte libraries from
               | your own code usefully.
        
               | asveikau wrote:
               | I have seen with clang++ that if I mix and match .o files
               | built with -std=c++11 and -std=c++17 [something I have
               | occasionally done by accident] and they reference the
               | same classes, sometimes they fail to link, not due to
               | standard library types differing but ones I defined
               | myself that can compile with either standard.
        
         | Sharlin wrote:
         | Interesting. To me there's very little totally new syntax, and
         | the benefits are considerable. It's basically just being able
         | to match on the existing structured binding patterns, as well
         | as on type tags when the expression is polymorphic.
        
           | stinos wrote:
           | _the benefits are considerable_
           | 
           | Exactly. Admittedly with enough modern C++ experience and
           | having used pattern matching I find the syntax pretty
           | readable and clear. But even if it weren't I'd probably still
           | be +1 pattern matching.
        
         | voldacar wrote:
         | If they added proper metaprogramming, people could make their
         | own pattern matching and other compile time goodies and they
         | wouldnt have to keep shoving cruft down our throats every 3
         | years.
        
         | SamReidHughes wrote:
         | The consequences of using an inspect statement are local to the
         | statement. So the syntax is a thing to learn, but probably not
         | a harbinger of language complexity. It's a leaf node.
        
       | rightbyte wrote:
       | Does this proposal have any support?
       | 
       | At first it seems nice, but is it realistic to add so much new
       | syntax to the language?
        
         | de_watcher wrote:
         | Structured bindings need to get rid of the mandatory dummy
         | variables in case of the unused parts of the structure. So
         | something has to be added.
        
           | gumby wrote:
           | Something has to be added but it could just be an empty
           | comma, which IIRC parallels initialization: use `auto& [a, ,
           | c]` to match the first and third elements of a tuple.
        
       | mikepurvis wrote:
       | Reading over the examples, it seems like there's a lot of good
       | stuff here, though I wondered how possible it would be to extend
       | switch with some of this capability vs adding a new keyword. It
       | looks like this possibility was considered and is addressed in
       | SS7.2-- basically the flexibility of case labels and break
       | statements being able to appear inside control structures leads
       | to all kinds of chaotic corner cases for switch (Duff's Device
       | and friends) that are incompatible with the proposed semantics
       | for inspect, with no obvious way to signal from the source which
       | one you want.
        
         | ramenmeal wrote:
         | c# has been adding pattern matching capabilities to the switch
         | statement and I think it's created a mess. Both syntax wise and
         | possible bug prone. Switch went from choosing a distinct case
         | to matching multiple cases. I'm sure Mads knows more than me
         | though, so it's probably a safe change.
        
         | jupp0r wrote:
         | Seems like `inspect` would turn `switch` into a deprecated
         | practice, which is preferable imho. This way, it's easier to
         | write clang-tidy rules for conversion and to raise red flags in
         | PRs.
        
           | mikepurvis wrote:
           | Yeah, it makes sense. It's just a bummer when switch feels
           | like a much better-named keyword for the functionality, in
           | the long term.
           | 
           | You almost wonder if they could do something like how `enum`
           | got fixed up with proper scoping as `enum class`. Like, could
           | `switch` retain the legacy functionality with the new stuff
           | triggered when you do `switch from`, `switch if`, or similar.
           | Or there could be new keyword added after the parenthesis,
           | something like:                   switch(<thing>) cases {
           | <opt1> : ...;            <opt2> : ...;            __ : ...;
           | }
           | 
           | This has a clear connection back to the legacy command in
           | terms of a switch always having either case labels or a cases
           | _structure_. And zero chance of breaking existing code, given
           | that the `cases` keyword would only be valid in that position
           | and could still be used as an identifier elsewhere (though
           | obviously that would be discouraged).
        
             | twic wrote:
             | Or even just have a rule that if a switch uses patterns, it
             | can't have any of the weird legacy misfeatures.
        
           | edflsafoiewq wrote:
           | switch is an extremely useful control structure, though
           | needed rarely. It's basically a kind of computed goto,
           | something not found very often outside C/C++ anymore.
           | 
           | If there's a real inspect, people will be able to stop
           | treating switch as a deficient approximation to one, and
           | maybe appreciate it for what it is.
        
       | kabdib wrote:
       | "It must be our great task, gentlemen, to keep the monkeys away
       | from the typewriters."
       | 
       | -- H. L. Mencken
        
       | quizotic wrote:
       | This seems so much more clear to read, with less typing.
        
       ___________________________________________________________________
       (page generated 2020-01-03 23:01 UTC)