Live data from Hacker News

"14 Years of Go" by Rob Pike

codereliant.io

61–70 of 75 posts

Re: "14 Years of Go" by Rob Pike

#61

Go is brilliant for what I don't have to do. Go doesn't have a build system, so I don't have to learn that. (I spend every second I'm using Gradle to curse it's very existence -- and wish I had `go build`) Go cross compiles natively, so I don't have to think about the toolchain. Go has go:embed, so I don't have to think about bundling/packaging as a separate step. Go has fantastic backwards compatibility, so I don't…

Very well said. As someone who rarely touches Go (only used it for a couple of simple web servers, something like a WebSub subscriber), you've named much of what I like about it. I'd love to see more languages achieve all these features, or even make that a goal.

I'd also mention how great the documentation is. Truly best in class. For instance, see https://pkg.go.dev/net/http

* Has enough examples to fully understand how to use the package.

* Links to the individual source code files so you can read those if needed.

* Has a highly visible link for reporting vulnerabilities.

* Has a great search tool accessible with a keyboard shortcut.

* Clearly marks deprecated functions.

* The page even works without Javascript enabled.

Re: "14 Years of Go" by Rob Pike

#62

Earlier quoted context omitted.

Plenty of people are choosing Go because they neither have nor want the C++ cake. The OP was explicitly looking for a simple language, and C++ is the very opposite of that concept. So yes, you can have efficient nice abstractions, but only at the cost of an extraordinarily complex base language.

My point was that operators don't exclude the possibility of fusion. C++ expression templates were just an example. Numba does fusion in Python.

They don't, but require significantly more machinery in the language than just operator overloading (especially if you want it to work at compile time).

Re: "14 Years of Go" by Rob Pike

#63
post #17

Lack of support for operator overloading is a bit sad. As a result, Go can't get used in numerical applications, unless you like writing `matrix_plus(A, B)` instead of `A + B`. Is there a programming language that has a "simple" design like Go but which supports some operator overloading?

CLU

https://en.wikipedia.org/wiki/CLU_(programming_language)

Re: "14 Years of Go" by Rob Pike

#64

Earlier quoted context omitted.

You can have your cake and eat it. E.g. C++ expression templates allow you to fuse application of multiple operators.

How can you? Genuinely asking. You can overload operator + or operator *, but how could you make a dedicated ternary (three-way) operator that combines those two operations into something like std::fma? I guess you could overload the function call operator, but that doesn't offer much over just defining a function.

You can have the result of * not be the actual multiplication, but a MultiplicationExpression. Then, the result of MultiplicationExpression + Matrix is a MultiplyAddExpression.

Finally you overload the dereference operator of MultiplyAddExpression to actually run std::fma. With some template magic, this can all even be done at compile time.

You can look at boost::phoenix and boost::qi to see this taken to a huge extreme, overriding all of the C++ operators to write parsers using regex-like syntax (e.g. `parser = *a | +b;` generates a parser which recognizes "" or "aaa" or "bb", equivalent to the regex "a*|b+").

Re: "14 Years of Go" by Rob Pike

#65

Earlier quoted context omitted.

How can you? Genuinely asking. You can overload operator + or operator *, but how could you make a dedicated ternary (three-way) operator that combines those two operations into something like std::fma? I guess you could overload the function call operator, but that doesn't offer much over just defining a function.

You can have the result of * not be the actual multiplication, but a MultiplicationExpression. Then, the result of MultiplicationExpression + Matrix is a MultiplyAddExpression. Finally you overload the dereference operator of MultiplyAddExpression to actually run std::fma. With some template magic, this can all even be done at compile time. You can look at boost::phoenix and boost::qi to see this taken to a huge extr…

That makes a lot of sense, thanks. I hadn't even thought about that. I guess you could also have MultiplicationExpression have an implicit coercion operator so you can use it in places where a matrix is expected, which would just compute the multiplication without any corresponding addition. That's pretty interesting.

Re: "14 Years of Go" by Rob Pike

#66

Earlier quoted context omitted.

You can have your cake and eat it. E.g. C++ expression templates allow you to fuse application of multiple operators.

How can you? Genuinely asking. You can overload operator + or operator *, but how could you make a dedicated ternary (three-way) operator that combines those two operations into something like std::fma? I guess you could overload the function call operator, but that doesn't offer much over just defining a function.

You define operators on your e.g. Vector types to construct a type that represents lazy evaluation of the expressions and reflect the operations at the type level. So for a * b + c you would get a type like Add, Mul>.

The evaluation then happens as assignment or Vec construction when you have something like:

    Vec r = a * b + c
You could either inline the functions on Mul and Add in the evaluation loop and rely on the compiler to deduce that an FMA instruction can be used. In the unlucky case, you at least avoid the intermediate a * b vector.

Another option, since the expression is represented at the type level is to write a compile-time evaluator that replaces patterns like Add, Mul> by FMA using templates.

This general idea is the foundation of libraries like Eigen.

Re: "14 Years of Go" by Rob Pike

#67

Earlier quoted context omitted.

My point was that operators don't exclude the possibility of fusion. C++ expression templates were just an example. Numba does fusion in Python.

They don't, but require significantly more machinery in the language than just operator overloading (especially if you want it to work at compile time).

Sure. But somebody writes it once and you can benefit from it. If you don't have operator overloading there isn't any chance of doing this.

At any rate, I feel like the goalposts have been moved a bit. You originally said:

But then you'll soon want to do A*B+C, and you'll find that fused multiply/add is a much faster operation than doing a multiplication and then addition, and soon you'll either be writing mul_add(A, B, C) anyway

Which I just wanted to point out that you can fuse these operations with operator overloading as well. I am pretty sure that

or you'll overengineer a complex solution to make A*B return some kind of object that can recognize the subsequent + operation etc.

was a later edit, I don't remember reading it when I first reacted to your comment. If so, doing that is not really nice, since it breaks the flow of the reactions.

At any rate, I think we agree on all the trade-offs.

And typing the multiplication operator in HN syntax sucks :).

Re: "14 Years of Go" by Rob Pike

#68

Earlier quoted context omitted.

They don't, but require significantly more machinery in the language than just operator overloading (especially if you want it to work at compile time).

Sure. But somebody writes it once and you can benefit from it. If you don't have operator overloading there isn't any chance of doing this. At any rate, I feel like the goalposts have been moved a bit. You originally said: But then you'll soon want to do A*B+C, and you'll find that fused multiply/add is a much faster operation than doing a multiplication and then addition, and soon you'll either be writing mul_add(A,…

> I am pretty sure that

> or you'll overengineer a complex solution to make AB return some kind of object that can recognize the subsequent + operation etc.

> was a later edit, I don't remember reading it when I first reacted to your comment. If so, doing that is not really nice, since it breaks the flow of the reactions.

I'm honestly not even sure. I had this in mind from the beginning, but I may have initially had a different vaguer comment about it and edited, I'm not sure. I sometimes edit comments right after posting them and then don't leave a note like I did for the later edit of the *s, since I assume no one read them. If this happened, I apologize.

Either way, yes, I think we are mostly in agreement. I'm not actually a big fan of Go's minimalism, so I actually see the value of such constructs.

Re: "14 Years of Go" by Rob Pike

#69

Earlier quoted context omitted.

How can you? Genuinely asking. You can overload operator + or operator *, but how could you make a dedicated ternary (three-way) operator that combines those two operations into something like std::fma? I guess you could overload the function call operator, but that doesn't offer much over just defining a function.

You define operators on your e.g. Vector types to construct a type that represents lazy evaluation of the expressions and reflect the operations at the type level. So for a * b + c you would get a type like Add , Mul> . The evaluation then happens as assignment or Vec construction when you have something like: Vec r = a * b + c You could either inline the functions on Mul and Add in the evaluation loop and rely on th…

Thanks for this response as well. I didn't see it earlier. It seems pretty interesting what you can do with C++ templates.

Re: "14 Years of Go" by Rob Pike

#70
post #14

Earlier quoted context omitted.

I was with you until you slagged on the other options. Rust and Scala are designed for other use cases than yours. That doesn’t trivialize their worth.

> Rust and Scala are designed for other use cases than yours This has become a sort-of gotcha for any discussions that involve comparing programming languages, but I think it has been over-extended beyond what is reasonable. It is true that some languages are much better at certain use cases than others, and especially if you consider their ecosystems when making this determination. For example, I don't feel Go makes…

[dead]
Post reply on HN