News for hackers. Stuff that matters.
Re:Go 1.18 Beta 1 is available, with generics by Cthulhu_ on Wednesday December 15, 2021 @08:43AM (#29565766)
Note that you still shouldn't use Go as a functional language (using map/reduce/filter); it's not optimized for functional programming, and the syntax would be pretty gnarly.

A for-loop has what's called "mechanical sympathy", and will go through things in the order that it is in memory. It'll allow the compiler and runtime to manage things quickly through memory, CPU registers, and CPU pipelines.

A great post on the subject is "Why Go Getting Generics Will Not Change Idiomatic Go": http://www.jerf.org/iri/post/2955

Re:Go 1.18 Beta 1 is available, with generics by lucian1900 on Wednesday December 15, 2021 @08:55AM (#29565935)
The bit about "mechanical sympathy" is wrong, though. Plenty of languages inline map/reduce or iterator type code down to very efficient cache-friendly traversal of memory, most notably Rust.

Go's compiler is just particularly naive.

Re:Go 1.18 Beta 1 is available, with generics by kortex on Wednesday December 15, 2021 @09:24AM (#29566325)
Actually I think while the compiler is a bit naive, the compiler writers are not. They are striving for simplicity, maintainability, speed, etc., vs trying to optimize high-level FP-esque idioms into fast machine code.

The compiler has definitely gotten more optimal over the years, but it's a different beastie than the rust one. Because go is not rust.

Re:Go 1.18 Beta 1 is available, with generics by Sharlin on Wednesday December 15, 2021 @11:50AM (#29568436)
It should be noted, though, that rustc does not really have any particular tricks up its sleeve to optimize functional patterns, or indeed much of anything. A lot of the LLVM IR that rustc generates is astonishingly naive and verbose – largely by design! rustc totally depends on LLVM's optimization passes to throw out all the boilerplate and output lean and mean optimized machine code.
Re:Go 1.18 Beta 1 is available, with generics by kortex on Wednesday December 15, 2021 @04:24PM (#29571819)
Right but that just means it's LLVM being clever, not rustc.

The main compiler is the self-hosting gc go compiler. Iirc ~~it's the reference implementation~~ erm I guess it's determined by spec, not reference implemenation. Gc is definitely "the default" though.

Then There's the gofrontend, which is a compiler frontend to other compilers, which can work with gcc and llvm. I am not aware of the state of the art for these, but I wonder if there are performance differences.

Re:Go 1.18 Beta 1 is available, with generics by lucian1900 on Wednesday December 15, 2021 @09:27AM (#29566355)
Go is not Rust, but there is a lot it could learn from Rust without sacrifice: sum types, Result for error handling, iterators with for loop support, [edit] non-nullable types etc.
Re:Go 1.18 Beta 1 is available, with generics by kortex on Wednesday December 15, 2021 @09:44AM (#29566567)
I've wanted a Result type I could map over in Go as soon as I saw the idea. But someone recently pointed out, without pattern matching and early return, it's kind of nerfed. Not sure I totally agree (I think it'd still be awesome to have Result, if only for .map()), but I see their point.

I disagree that it would be without sacrifice. That's kind of the whole point.

Unless I'm missing something, go has iterators with for loops.

Re:Go 1.18 Beta 1 is available, with generics by lucian1900 on Wednesday December 15, 2021 @09:48AM (#29566638)
Go switches with exhaustion checks like in [1] would go a long way. An early return construct would be important as well, though, you're right.

Go's for loops can only iterate over builtin types: slices, maps, channels, etc. You can't produce a custom type that is to be iterated over.

1. https://github.com/BurntSushi/go-sumtype

Re:Go 1.18 Beta 1 is available, with generics by sacado2 on Wednesday December 15, 2021 @09:34AM (#29566454)
Not as simple as it seems. For instance, what is the zero value of a sum type? Let's say, the zero value of a Result<int, error>?
Re:Go 1.18 Beta 1 is available, with generics by kortex on Wednesday December 15, 2021 @09:53AM (#29566711)
Perfect example of a caveat to "without sacrifice". For context, go really cares about having "zero values" - every initialized variable of some type must have a zero value.

The zero of Error is nil, so logically this would be Result(0, nil). But what do you set the internal state? It's not Ok, cause that int isn't used, and it's not Err either.

Option would work fine though and it would be amazing to map over options instead of nil checks.

I think you'd need to build Result on top of Option, it's naturally kind of ternary - "I have value" "I have error" "idk", either internally or externally.

What might be awesome would be if the Error were a slice type, nil would be "uninitialized" and empty slice means "initialized". still not...pleasant.

Re:Go 1.18 Beta 1 is available, with generics by DylanSp on Wednesday December 15, 2021 @11:00AM (#29567805)
Zero values are definitely an issue, and it'd be hard to get rid of them while sticking to Go's imperative/statement-based style. Still, it'd nice to use an Option type instead of pointers.
Re:Go 1.18 Beta 1 is available, with generics by Lev1a on Wednesday December 15, 2021 @10:01AM (#29566820)
IIRC in Rust it has to be either of the Ok or Err variants and the enclosed type can then provide its own "zero value" via the standard library "Default" [0] trait or your own implementation for the particular type. That trait is also implemented not for "Result" but for "Option" giving it a default value of "None".

[0]: https://doc.rust-lang.org/std/default/trait.Default.html

Re:Go 1.18 Beta 1 is available, with generics by sacado2 on Wednesday December 15, 2021 @10:30AM (#29567238)
Yes, for Option the default value is quite obvious. I'm talking about Result, because it's the second best-known sum type, and it doesn't have an obvious default value.
Re:Go 1.18 Beta 1 is available, with generics by Lev1a on Wednesday December 15, 2021 @05:58PM (#29572648)
Bindings in Rust have to initialized with an explicit value if the first use comes before the first modification/assignment otherwise [0] you get an error message with error E0381 [1]. Even if that explicit assignment is just through the use of the type's default method [2], if available.

Since it's implemented for Option<T> you can do it the same way [3] for that, but that's not available for Result<T,U> since the semantics are different from Option which is basically just Rust's alternative for 'null'/'nil' (but verifiable by the compiler).

Thus you'd have to choose what variant of the enum you want to have at initialization, after which you can use the Default implementation of the enclosed type, if available (and so on, if there are more nested types).

Though honestly I can't recall using the kind of pattern in Rust that would "need" something like that. Through the handling of code blocks as expressions, early returns etc. you for example don't need to initialize a variable before having an if-/match-/for-/while-/etc. block, you can simply use that block as an expression on the right side of the assignment [4].

[0]: https://play.rust-lang.org/?version=stable&mode=debug&editio...

[1]: https://doc.rust-lang.org/stable/error-index.html#E0381

[2]: https://play.rust-lang.org/?version=stable&mode=debug&editio...

[3]: https://play.rust-lang.org/?version=stable&mode=debug&editio...

[4]: https://play.rust-lang.org/?version=stable&mode=debug&editio...

Re:Go 1.18 Beta 1 is available, with generics by foldr on Friday December 17, 2021 @05:36AM (#29590391)
In Go, every type has a sensible built-in zero value. In Rust there is no need to worry about what the 'default' value of a Result type should be. So choosing a sensible default value for result would be a problem in Go (but not in Rust).
Re:Go 1.18 Beta 1 is available, with generics by lucian1900 on Wednesday December 15, 2021 @10:21AM (#29567107)
The zero value of a sum type can be the zero value of the first (or chosen) constituent. In this case, it could be Result<0>.
Re:Go 1.18 Beta 1 is available, with generics by sacado2 on Wednesday December 15, 2021 @10:29AM (#29567206)
I'm not sure that would be any better, in practice, than doing return 0, nil.
Re:Go 1.18 Beta 1 is available, with generics by lucian1900 on Wednesday December 15, 2021 @11:42AM (#29568317)
It would allow functions to be treated generically as returning error-able types. Since some functions even return 3 arguments where the third is the error, this isn't possible today.

It would also allow defer-like syntax to be used on the value a function returns, to return early from the calling function. Rust's ? is an excellent example of this, allowing explicit delegation of error handling that is still very lightweight syntactically.

Re:Go 1.18 Beta 1 is available, with generics by kortex on Wednesday December 15, 2021 @04:37PM (#29571936)
Function composition becomes a lot easier with Result/Option, because you can write functions in terms of assuming a "good" value (not nil/err or otherwise "bad") and then map over it. Or if we really wanna be fancy, flatmap/bind over it.

Foo, err requires either that all receiving functions accept (foo, err), or manually nil-checking at every stage.

Try/catch is the least composable, because deeper error types can "jump out" from any layer. Which means you have to keep wrapping catches, until you hit some base layer you can recover from. You get stack traces, but you lose type information along the way.

Sum (result) and product (foo, nil) types preserve type information. Meaning you can operate more generically over it. Meaning less code duplication.

Re:Go 1.18 Beta 1 is available, with generics by Zababa on Wednesday December 15, 2021 @03:28PM (#29571205)
Speed and maintainability vs trying to optimize high-level FP-esque idioms into fast machine code is a false dichotomy. OCaml has a really fast compiler, it has been maintained by a small team for 25 years, and it produces fast machine code. A big caveat in comparing OCaml and Go would be multicore support, but it's coming in OCaml, without breaking existing programs and with only a few percent of performance lost.
Re:Go 1.18 Beta 1 is available, with generics by fsdjkflsjfsoij on Wednesday December 15, 2021 @11:21AM (#29568025)
> Plenty of languages inline map/reduce or iterator type code down to very efficient cache-friendly traversal of memory

Very few languages outside of Rust and Haskell actually do this reliably and that's including languages like Ocaml and F#. Rust and Haskell are certainly the only even remotely popular languages that do it.

Re:Go 1.18 Beta 1 is available, with generics by spekcular on Wednesday December 15, 2021 @11:28AM (#29568123)
Does Haskell actually succeed here?

This is perhaps not the right way to measure, but: When I last checked the programming language benchmark game [0], the Haskell submissions were basically as fast as C/C++/Rust. But, this came at the cost of writing non-idiomatically/non-functionally – essentially abusing the language to write C in Haskell. I would be curious how well "idiomatic" Haskell compares to C++/Rust, in terms of the compiler optimizing away the functional abstractions.

[0] https://benchmarksgame-team.pages.debian.net/benchmarksgame/...

Re:Go 1.18 Beta 1 is available, with generics by igouy on Wednesday December 15, 2021 @11:49AM (#29568407)
Re:Go 1.18 Beta 1 is available, with generics by spekcular on Wednesday December 15, 2021 @12:14PM (#29568791)
Thanks, that's pretty convincing.
Re:Go 1.18 Beta 1 is available, with generics by Zababa on Wednesday December 15, 2021 @03:31PM (#29571243)
I think OCaml can do it with flamba, at least that's what this library readme says: https://github.com/c-cube/iter

> with flambda under sufficiently strong optimization flags, such compositions of operators should be compiled to an actual loop with no overhead!

Re:Go 1.18 Beta 1 is available, with generics by nine_k on Wednesday December 15, 2021 @12:46PM (#29569194)
Does the elephant-in-the-room of C++ do it? I thought it does.

I can't bet on what Java and JavaScript JITs make of map / forEach / filter / reduce, but I suspect that they can be pretty efficient, given the clear delineation and the repeated patterns.

Re:Go 1.18 Beta 1 is available, with generics by mananaysiempre on Wednesday December 15, 2021 @09:14AM (#29566176)
(The key phrase is “stream fusion”.)