Pattern Syntax in Golang

162 views
Skip to first unread message

Nadim Kobeissi

unread,
Jun 5, 2019, 12:47:48 AM6/5/19
to golang-nuts
Hello everyone,

This is my first post to this list so please excuse me if I'm not following all of the proper traditions for this community (posting this in the wrong place, etc.)

I like Golang a lot and I think that it's a gift to people who love computer programming. I have written three softwares in Golang and I'm really having a great time with this language.

I was wondering if people would be interested in discussing the inclusion of pattern matching syntax in Golang. By "pattern matching" I do not mean regular expressions, but rather a feature that is seen in other languages such as OCaml.

Rust also has this feature, which it simply calls "Patterns". In particular Rust's implementation of this feature seems quite excellent actually.

I think adding patterns/pattern matching to Golang would allow it to be used much more seriously in situations like building a parser, transpiler, compiler etc.. I'm sure there are other uses as well.

Here is an example of what I have in mind:

// Just some code to later demonstrate my proposition
func getDayAndDate
() (string, int) {
    date
:= getDate()
   
if todayIsTuesday() == true {
       
return "tuesday", date
   
}
   
return "not tuesday!", date
}

var result string

// What I am proposing starts here (the below is currently not valid Golang code)
result
= match getDayAndDate() {
   
"tuesday", _: "wow looks like it's tuesday",
    _
, 5: "i don't know if it's tuesday but it's the fifth! nice!",
   
"not tuesday!", _: "not a tuesday my dude",
}

Wouldn't that be cool? I don't think that existing Golang syntax allows us to accomplish stuff like this so elegantly. We'd have to do something really convoluted. The following doesn't work since switch can't handle functions with multiple return values:

switch getDayAndDate() {
   
case "tuesday", 5:
        println
("cool!")
}

switch also can't handle the _ wildcard as a case value. So really there is no serious alternative to achieve pattern matching in Golang right now, as far as I can tell.

I tried searching the Internet, including this mailing list, for previous discussions of this topic, and the only thing I could find was a post dating to eight years ago with little follow-up.

I genuinely believe this is a great feature for Golang to pursue and I wonder if we can get the developers of this fantastic programming language and toolkit to take this feature more seriously. I'd be happy to help implement it myself if I can!

Thank you,

Nadim
Sent from my computer

Nadim Kobeissi

unread,
Jun 5, 2019, 1:22:53 AM6/5/19
to golang-nuts
Two more examples to show off some more cool ways match could be useful. Here, I just demonstrate how we can have logic inside matches thanks to anonymous functions:

result = match getDayAndDate() {
   
"tuesday", _: "wow looks like it's tuesday",

    _
, 5: (func() string {
       
if isItWednesday() == true {
           
return "well, at least it's wednesday!"
       
} else {
           
return "not wednesday either!"
       
}
   
})(),
}

Here's another interesting example which showcases destructuring as well as guards:

type date struct {
    day  
int
    month
string
    year  
int
}

func getDate
() date { /* Use your imagination */ }

var today string

today
= match getDate() {
    date
{day: d, month: m, year: y} if (m == 2) && (d > 29) : fmt.Sprintf("Today is impossible.", m, d, y),
    date
{day: d, month: m, year: y}: fmt.Sprintf("Today is %s %d, %d.", m, d, y),
}

Nadim
Sent from my computer

--
You received this message because you are subscribed to a topic in the Google Groups "golang-nuts" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/golang-nuts/JAcxQqVLqUI/unsubscribe.
To unsubscribe from this group and all its topics, send an email to golang-nuts...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/2699b3f4-f56d-4e04-bfdb-b00fe10390e0%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Nicholas Eden

unread,
Jun 5, 2019, 1:29:54 AM6/5/19
to golang-nuts
I am not a fan of the match syntax you're proposing.  It seems like a modified switch which does an assignment and doesn't have 'case' in the statements.  The keyword match would definitely conflict with variables names. To me this looks like a Pythonism where several lines worth of logic get shoved into one line.  It doesn't fit the standard simplicity of the language.

I think the potential of a switch that can handle multiple values would be interesting.  It follows and extends a syntax that we already know, as well as works in tandem with multiple returns.  It would be easy to explain and document because it is the natural next step.  I don't think there would even be a breaking change potential.

Nadim Kobeissi

unread,
Jun 5, 2019, 1:49:42 AM6/5/19
to Nicholas Eden, golang-nuts
Hello and thank you for your comments.

> The keyword match would definitely conflict with variables names.
This doesn't seem like a huge issue to me but certainly I'd be happy with expanding switch instead if it allows us to do the same sort of thing.

> To me this looks like a Pythonism where several lines worth of logic get shoved into one line. It doesn't fit the standard simplicity of the language.
Maybe in my second example that happens, but that was me trying to make some more advanced suggestions, and they're not really necessary to integrate my core idea.

> I think the potential of a switch that can handle multiple values would be interesting.
I think so too, but this wouldn't even completely implement my first example, which includes also usage of a _ wildcard. And it would be a shame to completely rule out destructuring and guards (seen in my third example) as a consequence.

Nadim
Sent from my computer

--
You received this message because you are subscribed to a topic in the Google Groups "golang-nuts" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/golang-nuts/JAcxQqVLqUI/unsubscribe.
To unsubscribe from this group and all its topics, send an email to golang-nuts...@googlegroups.com.

Ian Lance Taylor

unread,
Jun 5, 2019, 10:07:52 AM6/5/19
to Nadim Kobeissi, golang-nuts
On Tue, Jun 4, 2019 at 10:22 PM Nadim Kobeissi <na...@nadim.computer> wrote:
>
> Two more examples to show off some more cool ways match could be useful. Here, I just demonstrate how we can have logic inside matches thanks to anonymous functions:
>
> result = match getDayAndDate() {
> "tuesday", _: "wow looks like it's tuesday",
> _, 5: (func() string {
> if isItWednesday() == true {
> return "well, at least it's wednesday!"
> } else {
> return "not wednesday either!"
> }
> })(),
> }
>
> Here's another interesting example which showcases destructuring as well as guards:
>
> type date struct {
> day int
> month string
> year int
> }
>
> func getDate() date { /* Use your imagination */ }
>
> var today string
>
> today = match getDate() {
> date{day: d, month: m, year: y} if (m == 2) && (d > 29) : fmt.Sprintf("Today is impossible.", m, d, y),
> date{day: d, month: m, year: y}: fmt.Sprintf("Today is %s %d, %d.", m, d, y),
> }

There are a lot of complex ideas being mixed together here. Let me
try to write these examples in the existing language.

result = func() string {
day, date := getDayAndDate()
switch {
case day == "tuesday":
return "it's Tuesday"
case date == 5:
if isItWednesday() == true {
return "well, at least it's wednesday!"
} else {
return "not wednesday either!"
}
}
return ""
}()


today = func() string {
d := getDate()
switch {
case d.month == 2 && d.day == 29:
return fmt.Sprint("Today is impossible.", d.month, d.day, d.year)
default:
return fmt.Sprintf("Today is %s %d, %d.", d.month, d.day, d.year)
}
}()

The code with match is a little shorter, but it doesn't seem to
provide any capability that we don't already have. Any new language
feature of this complexity should be orthogonal to other features. To
my eyes match seems to have a significant overlap with switch.

Ian

Nadim Kobeissi

unread,
Jun 5, 2019, 12:03:12 PM6/5/19
to Ian Lance Taylor, golang-nuts
Hello, and thank you for your response.

I never intended to suggest that adding pattern matching would allow Go computational capabilities that it did not previously have. I agree that switch can be wielded to achieve the same logic in a syntax and structures that roughly resembles my suggestion. Let me attempt to explain my actual reasoning behind this proposal.

Imagine that I am building a lexer, a parser or a compiler. If I am to follow your syntax, I would need to repeat a variant of this line from your example quite a few times: day, date := getDayAndDate()

That indicates the necessity of declaring and allocates variables -- the memory pollution is secondary to the namespace and code elegance pollution there -- quite often throughout my code as it goes through the AST or whatever else structure I could be considering. In pattern matching the `day` and `date` variables *are not declared unless used for purposes other than pattern matching*: if I needed them, I'd write: `x, y:`, otherwise I'd write `"tuesday", 5:`.

In addition to the above I would then very likely need to have nested ifs within nested ifs -- and dealing with each potential pattern that I'm trying to match would necessitate so much cruft that the resulting code would be very ugly. Indeed it's my view that Golang is currently not a suitable language for expressing any program that involves the treatment of an AST due to these syntactic limitations, i.e. the lack of real pattern matching.

It's true that in the examples we're discussing, this pollution is minimal, but that's because they're simple examples. In the context of more complex parsing or transpiling, using switch as it currently is causes the code to become quite cumbersome, repetitive and nested. It's really a huge problem when dealing with actual languages and I can say that from experience.

I agree that the `if` guard in my third original example is superfluous, so let's put it aside. I would still like to argue for the `match` keyword because I think that aside from the infinitely more elegant method and syntax for pattern matching, the benefits of wildcards (expressed with `_`) and also of struct type deconstruction (as seen in my third original example). I believe that `_`s are already ubiquitous around Golang and are used amply for very similar purposes as the ones they'd be used for here.

This indeed could be a new direction for Go to consider, I don't claim to know. I don't mean to step on anyone's toes here or to dictate what the language should look like. I just sincerely think that `match` would make Golang a better language, not by allowing it to strictly *do things* it couldn't do before, but to do *a class of things elegantly* whereas it couldn't do them elegantly before.

Nadim
Sent from my computer

Michael Jones

unread,
Jun 5, 2019, 1:23:05 PM6/5/19
to Nadim Kobeissi, Ian Lance Taylor, golang-nuts
Nadim, from what you have written I sense that you appreciate (or will enjoy learning about) the style of programming that emerged with SNOBOL some time ago. The notion of programming not just by saying "do this, then this, then..." but at a higher and more conceptual level of matching situations using rules and progressing to conclusion by repetition and potentially backtracking. The general area of parsing, rewrite systems, rule-based programming, and automata is large and not understood by programmers to the degree that it deserves. (Exceptions being anyone who has worked on SSA-style optimizing compilers or symbolic math software such as Maple, Macsyma, Reduce, etc.)

The key ideas around string matching, such as notions of success and failure, backtracking, greedy matches, following sets (and other new at the time notions: garbage collection, type inference) were in the Bell Labs language SNOBOL (and related, SNOCONE as well as Ralph Griswold's subsequent icon). I suggest that you read about this work. People have been inspired to add "SNOBOL pattern matching" to various other languages including Ada and Python. Maybe the result of your interest could be something of this nature for Go. 

There is a similar respect/lust felt by a different set of people for the PARSE statement of REXX. Some tools are so powerful that they change user's ideas of possible and impossible. I believe that the general area of parsing/matching/understanding/translating holds unfulfilled promise of this kind.

Michael

--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/CAK-38xW91-o5qCGZ5dPU-HsQZv74%3D_i2QA%3DuTy%2B8_jD3d04FGA%40mail.gmail.com.

For more options, visit https://groups.google.com/d/optout.


--
Michael T. Jones
michae...@gmail.com
Reply all
Reply to author
Forward
0 new messages