Live data from Hacker News

Go 2, here we come

blog.golang.org

401–410 of 534 posts

Re: Go 2, here we come

#401
post #389

Earlier quoted context omitted.

If you don't like the automatic cast, you can always manually cast inline by doing (3 :: Int). I've used this a number of times when doing numeric stuff in Haskell.

I do know how to manually cast, although in my case I'm usually casting to Integer. I was arguing that a cast from Num to Float, Double, Int etc is a lossy operation, and breaks the semantics of arithmetic, and so should not be done implicitly.

> but the lack of explicitness about casting exact types (Integer, Rational) to inexact types (Int, Float) has led to many bugs and confusions for me.

> I love all of the automatic casting between exact types, but happily implicitly casting to inexact types is (in my opinion) a big mistake.

> I was arguing that a cast from Num to Float, Double, Int etc is a lossy operation, and breaks the semantics of arithmetic, and so should not be done implicitly

It's not really casting; it's just type inference. You can't have a Num and use it as a Rational in one place and a Float in another (unless you lift the monomorphism restriction), and you can't add a Rational and a Float without explicitly casting one to the other by the use of a function like fromRational. Like so, real casting is very much explicit. I feel like you're technically arguing against representing Floats with decimal numbers in code, but I don't think you really mean that.

EDIT: At the risk of stating something that you might already know, (x :: Int) in Haskell is not a cast like (int)x in C. (x :: Int) simply further restricts the list of possible concrete types that x could be. If the code context implies that x is a Num a => a, that means it could one of an Int, a Float, etc. Doing (x :: Int) simply says to restrict those possibilities to only Int. If x were a Float, and you did x :: Int, that'd be a type error because it was never possible for it to be an Int, only a Float. You'd need to cast by using a function like floor, ceiling, or round.

EDIT 2: To further explain this, C's (int)x is a run-time operation that converts whatever x is to an int, while Haskell's x :: Int is a compile-time operation that states that x can only ever be an Int and never something else. At the end of compiling, Haskell needs everything to be concrete types. Num a => a is not concrete because it can be many types and if Haskell can't resolve it to a single concrete type implicitly by context or explicitly by signatures like x :: Int, then it has to resort to defaulting rules or raise a compile-time error informing the programmer of the type ambiguity.

EDIT 3: On:

> Coupled with the fact that so many standard functions (like length, for example) want to return an Int rather than an Integer, it just leads to me spewing ((fromIntegral ___)::Integer) all over my code.

I agree it would be nice for length to return a Num a => a instead of an Int, but it's nice that the reason is to maintain stability and limit code breakage from the times before Num existed. The Haskell community seems to really care about that. They did add genericLength which does return a Num a => a, though. There's other generic functions added to Data.List.

Re: Go 2, here we come

#402
post #347

Earlier quoted context omitted.

I really don't get the people opposed to generics. Is there actually a cross between experienced developers who have come from languages that have generics and understand them, yet don't want them in go? If so, why, and what do they use instead? Because go has no compromise-free answer for generics. You either lose type safety, maintainability, or performance. I suspect a lot of the generics hate is due to a large ch…

Increasing language surface area will generally increase the complexity of all api surfaces written in the language. This has obvious costs. It’s true genetics will shrink some specific APIs, where they are a good fit. But they will also be used opportunistically by developers excited to push their boundaries. Of course you can say “just don’t do that” which works if you have a tightly controlled codebase. But most c…

>I believe in the future all languages will fork into a simpler novice subset for general use and an expansive language for infrastructure. These will both be valid in the same parser, but the subset will be quarantined at the package management level.

I don't think we'll see this happen much for existing languages, but it could be a very interesting angle for a newly-designed language (or rather pair of languages).

Re: Go 2, here we come

#403
post #392

Earlier quoted context omitted.

Rather than writing multiple functions that take different types as args and return different types (say int8, int16, int32, etc.) but do the exact same thing, with generics, you can instead write one function that takes a number (which could be any int type) and return a number, and you only wrote one function. That is generics in a nutshell. The function is generic, not specific to one type. Generics allow for less…

Wouldn’t this make golang slow though? Isn’t that what people claim makes python slow?

In a ahead-of-time compiled language probably not. The generic function is just a code generator for several functions that will get called in the right places, generated and put in the right places by the compiler, and then get optimised as per normal.

And no, being a dynamic language is not what makes Python slow. Lua, Nim and Scheme are all examples of dynamic languages with fast implementations.

Re: Go 2, here we come

#404
post #203

Earlier quoted context omitted.

> Go doesn't actually have async support I usually phrase this part of Go as: no async/await, it only has threads. But no thread handles. Everything is potentially parallel under the hood and all coordination requires external constructs like WaitGroups / chans / etc. async/await has major complications like changing call syntax through the whole chain, so I actually prefer it this way. the lack of thread handle obje…

The main advantage of the async/await model is that it's just syntactic sugar on top of CPS, so you can bolt it onto any language that is capable of handling callbacks (even C!). For a good example of that, consider WinRT - you can write an async method there in C#, the task that it returns can pass through a bunch of C++ frames, and land up in JS code that can then await it - and all that is handled via a common ABI…

it's true that it's "just syntactic sugar", but in most languages it has call-site contracts that are either part of the signature (`await x()` to unpack the future/coroutine) or implicit (`x()` in an event loop host). and to change something deep in the stack means changing every call site everywhere.

that's a huge burden on a library (and thus the entire language ecosystem). it splits the world.

to avoid that, you basically need language-level support, so everything is awaitable... at which point you're at the same place as threads (but now they're green), where you cannot know if your callees change their behavior. which is both a blessing and a curse.

---

tl;dr yes but no. do you want your callee's parallelism to be invisible? you can't have both. (afaik. I'd love to see a counter-example if you know of one. there was one very-special-case language that made parallelism a thing you did to code rather than the code doing, but I can't find it at the moment. it only worked on image convolutions at the time.)

Re: Go 2, here we come

#406

As a newcomer to Go, by an immensely wide margin, the hardest, most frustrating thing, which soured the language for me, is whatever the heck package management is in Go. There's like three or four different angles, all of which overlap. Some are official. Some aren't. The unofficial ones seem more popular. They're all kind of incomplete in different ways. And it was all such a frustrating migraine to try and figure…

Having used the new Go module system (introduced in Go 1.11 as an option, to be the default choice in 1.12) since August, it's my opinion that this is now a solved problem. The biggest source of pain moving forward is going to be the projects that haven't transitioned, including the various command-line tools that work on parsing, generating and manipulating Go code (e.g. linters, code generators). Most of the import…

> it's my opinion that this is now a solved problem.

It's starting to look like a viable solution, but it's not even close to actually solved yet. Why does `go mod why And as you mentioned, a lot of things have side effects now that didn't use to, which has catastrophically broken a lot of the tooling surrounding the language. Autocomplete using gocode used to be nearly instant. Now it sometimes triggers downloads and takes 30+ seconds.

I'm hopeful that go 1.12 will be the first release where this problem is really solved.

Re: Go 2, here we come

#407

Earlier quoted context omitted.

Having used the new Go module system (introduced in Go 1.11 as an option, to be the default choice in 1.12) since August, it's my opinion that this is now a solved problem. The biggest source of pain moving forward is going to be the projects that haven't transitioned, including the various command-line tools that work on parsing, generating and manipulating Go code (e.g. linters, code generators). Most of the import…

> it's my opinion that this is now a solved problem. It's starting to look like a viable solution, but it's not even close to actually solved yet. Why does `go mod why And as you mentioned, a lot of things have side effects now that didn't use to, which has catastrophically broken a lot of the tooling surrounding the language. Autocomplete using gocode used to be nearly instant. Now it sometimes triggers downloads an…

There are bugs, but I was referring to the design of the whole thing.

By the way, your "go get" bug was fixed today [1], if I understand your complaint correctly: With the new modules turned on, you could no longer do "go get" globally.

(I would agree that it's a little weird that "go get" outside a module installs it globally, while inside a module it installs it locally; that's going to trip up scripts and Dockerfiles, and it should really be two separate commands. "go mod add" to add a new dependency, for example.)

[1] https://github.com/golang/go/issues/24250#event-1996119923

Re: Go 2, here we come

#408
post #403

Earlier quoted context omitted.

Wouldn’t this make golang slow though? Isn’t that what people claim makes python slow?

In a ahead-of-time compiled language probably not. The generic function is just a code generator for several functions that will get called in the right places, generated and put in the right places by the compiler, and then get optimised as per normal. And no, being a dynamic language is not what makes Python slow. Lua, Nim and Scheme are all examples of dynamic languages with fast implementations.

Now I have to ask, what would you say does make python slow?

Re: Go 2, here we come

#409
post #86

Earlier quoted context omitted.

Makes no sense to me to redefine existing integer types. Why not introduce a primitive type "num" for arbitrary precision rational numbers instead? As a long-time Racket and Scheme user, I'd say that arbitrary precision numbers as default bring more disadvantages than advantages. As an option with syntax support Yes, but not as a default. it just makes it harder to port all kinds of code that relies on modulo arithme…

> Why not introduce a primitive type "num" for arbitrary precision rational numbers instead? Rationals aren't supported natively by processors, so there's no real need to handle this as a primitive instead of letting people to use a library for it. Adding them to the base language just because some people would find it convenient would clash with Go's explicit minimalist philosophy.

Scheme has an explicit minimalist philosophy, so much so that when R6RS was released with too many conveniences it fractured the language and community. Now there's two specs, R7RS-small and R7RS-big, and they're far less popular than R5RS.

Rationals are also the default number type.

Lists are the base type used throughout Scheme, and can be used to implement arrays and hashmaps and whatnot, so Scheme doesn't really need them, you can just use a library.

... That didn't stop the committee adding types to the spec. Like records, promises and other complex types.

What is useful and necessary to a language isn't defined by what the processor can natively do, or we'd only use registers, not arrays. And it isn't defined by a overbearing attitude towards one or more philosophies.

Re: Go 2, here we come

#410
post #47

Earlier quoted context omitted.

Isn't the premise of Go that a team sufficiently large enough will eventually act as a collective idiot in terms of code maintenance? I'm looking forward to some real research on the question of whether Go's design choices have had real world results in improving productivity with supersize code bases.

(Disclaimer: at Google) My team has ~200k lines of Go code and I'm exceedingly happy with the state of the codebase. Having previously maintained a C++ codebase of similar size, I can say that the pace of changes is higher, the effort necessary for large scale refactorings is lower, and our ability to reason about the system is similar. A few examples: - Refactorings are simpler due to the use of consumer-side interf…

> Simple scripts, bash until they need their first 'if' or flag or loop, then Go too.

If you don't mind, can you give a little insight on what this looks like in practice? I'm not sure how to use a compiled language as a script. I've played with executing go as a script using a shebang hack, but I somehow don't think this is how others are doing it.

For reference, the shebang hack I was using looked like this:

    //usr/bin/env go run $0 $@; exit $?
    package main

    import "fmt"

    func main() {
        fmt.Println("i am a script")
    }
Post reply on HN