Live data from Hacker News

Everyday hassles in Go

crufter.com

271–280 of 297 posts

Re: Everyday hassles in Go

#271
post #2

Although i'm still very unsure about rob pike's argument that go don't need generics since it has interface, a recent experience : After having implemented a mini web services in go and being fed up with its limited type system, i decided to stop coding in go and start recoding my project in java using what is often advertized here as the most minimal framework : dropwizard. Well, i downloaded the framework, configur…

There have been some fairly involved discussions about generics recently on the Golang mailing list[0][1]. I think at this point the Go team isn't really opposed to Generics, but high-level ideas about it have basically all been proposed at this point.

The only way a generics (however you choose to define it) will be added to Go is if someone puts together an in-depth proposal about how it works, beyond just syntax. This means how it will work with the compiler/linker. How it will work with the runtime and GC.

Due to the amount of time it will take to put together such a proposal without the guarantee that it would be added, no one has gone down that path yet. You also need a deep understanding of many parts of the language to be able to produce such a proposal, which is another barrier.

[0] https://groups.google.com/forum/#!topic/golang-nuts/L-2OTItS...

[1] https://groups.google.com/forum/#!topic/golang-nuts/smT_0BhH...

Re: Everyday hassles in Go

#272

Earlier quoted context omitted.

But that's not a net win for me, compared to just having the action in a function that is called from several places. Worse, composing the actions means I have to think through how the composing is going to affect the sequencing of events. Just having a function doesn't give me that problem - the sequencing is explicit, not hidden, and therefore is easier to reason about.

Can you give me some example code? I think our discussion would be a lot more productive and mutually beneficial with some code examples/output.

I can't give actual example code (proprietary, company confidential, blah blah blah). So I'm going to have to come up with some fake example.

[Thinking...]

How about a robotic hand that's supposed to pick up a ball. The (C/C++) code might look like :

  void pickUpBall()
  {
    openHand();
    moveHandToBall();
    closeHand();
  }
You have to have that sequence. If the hand isn't open, moving it to the ball just bumps the ball away. If you close the hand before you move to the ball, you don't pick up the ball, you just close on air.

So, in Haskell (if I had the hardware control libraries), I could put that in a monad to guarantee the sequence, and in an IO monad so that I could do things that had side effects like affecting the external world. But in fact I get both of those for free, just by not writing it in Haskell. (The pure functional nature of Haskell also doesn't do much for me in this situation. Yes, for the functions that can in fact be purely functional, it can make them easier to reason about and prove correct. But that isn't the difficult part of the code.)

Composability: It's unclear to me how you're going to compose something like this in any way that's a) useful in this environment and b) dramatically different from simply making a higher-level function that calls pickUpBall() and some other functions.

Re: Everyday hassles in Go

#273

Earlier quoted context omitted.

My comment was carefully worded in order to denote that it is not true in all cases. Your Big O analysis is correct. However, in a real-world case the list could be an iterator over a log file on disk. Then you really don't want to use chained combinators, repeatedly returning to the disk and iterating over gigabytes of data on a spinning plate. And yeah, you could benchmark to figure that out, or you could use the r…

Or you could use a library explicitly designed with these considerations in mind, that offers the same powerful, familiar combinators, with resource safety and speed. e.g., Machines in Haskell: https://hackage.haskell.org/package/machines Scalaz Stream in Scala: https://github.com/scalaz/scalaz-stream I've no doubt an equivalent exists for Clojure, too, although I'm not familiar enough with the language to point you…

In many cases, YAGNI.

This started as a conversation about for loops vs. chained combinators and wound up with specialized libraries for IO. You're not wrong, but that's a lot more work than a for loop to parse a log file efficiently.

Re: Everyday hassles in Go

#274

Earlier quoted context omitted.

Well, you don't need the JVM and any dependencies it pulls . That's also worth something in the era of "cloud" services. Less to install. Less to update. Ideally you only need to update the deployed application. Which in case of Go is that one binary. Another big thing is that same app written in Go just takes (significantly) less RAM than when written in Java. Go has arrays (and slices) of structs, not just struct p…

What does memory usage have to do with ease of deployment ? Congratulations Go uses less memory. Is that really a bottleneck these days ? And sure you only need to replace one binary. Java can do that too but also has the flexibility to hot deploy new code/libraries so no costly outage.

Yes, computing resources, including computing power, memory usage and storage are limiting factors and they do increase cost. One instance - who cares. 1000 instances and you might care. Something you ship for other people to run? End users might care.

Give me ssh, and I can deploy my app to default installation setup in a second, like CentOS 6. That includes binary transfer, installation and startup.

Hot deploy is nice. Sadly Golang is one of the only language environments where you just can't do it. Do watch out, the issues you'll encounter may be rather unique. Especially when applied in production...

Re: Everyday hassles in Go

#275

Earlier quoted context omitted.

Can you give me some example code? I think our discussion would be a lot more productive and mutually beneficial with some code examples/output.

I can't give actual example code (proprietary, company confidential, blah blah blah). So I'm going to have to come up with some fake example. [Thinking...] How about a robotic hand that's supposed to pick up a ball. The (C/C++) code might look like : void pickUpBall() { openHand(); moveHandToBall(); closeHand(); } You have to have that sequence. If the hand isn't open, moving it to the ball just bumps the ball away.…

Cool, now we have something to work with. However at such a high level no paradigm's differences (much less pros/cons) would be apparent. Would you mind implementing those individual functions?

Actually it might be easier to use some open source embedded code.

For completeness sake, I'd write the snippet above almost identically:

    pickUpBall = do
        openHand
        moveHandToBall
        closeHand

Re: Everyday hassles in Go

#276

Statically typed languages impose unnatural hardware-oriented constraints on your business logic - It forces you to spend extra time and effort to make sure that your logic is in a format which the compiler can understand. Yes, this can sometimes help you to find silly errors in your code at compile time (and thus occasionally save you a bit of time) but, unfortunately, that occasional benefit doesn't make up for the…

Have you never used a statically-typed language? Most statically typed languages can handle adding an integer and a float together. The only one I can think of that isn't capable of that is OCaml, though this is probably a strength of OCaml rather than a weakness (int-to-float casting can be a common source of bugs if it happens unexpectedly).

Try to add an int and a float32 using 'Try go' on http://glolang.org - I get this error:

prog.go:13: invalid operation: x + y (mismatched types int and float32) [process exited with non-zero status]

I'd have to cast one of the variables to get it to work. Casting is unnatural - Maybe it's not so bad in this case, but in many cases it isn't desirable.

Re: Everyday hassles in Go

#277

Earlier quoted context omitted.

If you give some examples of the work that you do perhaps we can make some of the abstractions concrete.

Perhaps you could. That's not the same as making them useful for me, though. I work primarily in embedded systems, where sequence is critical, many things are stateful, and there are multiple threads of control. So, for example, I could take the sequential aspects and re-write them as a monad. Or I could just do nothing, and let them be sequential imperative code. I know that in a pure functional world, sequence can…

One neat thing you can do with monads thats useful in your setting is coroutines/generators as a library. You get to write code that looks like its regular sequential code and behind the scenes it gets expanded into the "callback hell" you would have had to write if you decided to code the things in event driven style by hand.

Anyway, I do have to say that the Monad abstraction is not that useful outside of Haskell because you kinda really need Type Classes to get monads "right" and most languages don't have that. What you might end up is with specific monads like promises in JS but then the monads are just a design pattern instead of being a concrete abstraction like they are in Haskell.

In addition to that, in Haskell monads are the only way to do sequential computations with side effects because by default the language is Lazy. This means that Haskell programmers have to learn this abstraction whether they like it or not while in other languages you can avoid it better :)

Re: Everyday hassles in Go

#278

Earlier quoted context omitted.

I can't give actual example code (proprietary, company confidential, blah blah blah). So I'm going to have to come up with some fake example. [Thinking...] How about a robotic hand that's supposed to pick up a ball. The (C/C++) code might look like : void pickUpBall() { openHand(); moveHandToBall(); closeHand(); } You have to have that sequence. If the hand isn't open, moving it to the ball just bumps the ball away.…

Cool, now we have something to work with. However at such a high level no paradigm's differences (much less pros/cons) would be apparent. Would you mind implementing those individual functions? Actually it might be easier to use some open source embedded code. For completeness sake, I'd write the snippet above almost identically: pickUpBall = do openHand moveHandToBall closeHand

OK, now you've got me really confused. Is that Haskell code? I thought that Haskell couldn't do sequence except inside a monad. (Or is "do" a monad?)

But if that isn't a monad, then why did you write it that way? My original claim was that a monad wouldn't do much for me in my world, and if you wrote this without a monad, that kind of seems like you're agreeing with me.

You said that you'd gain composability from writing this as a monad. In this example, how would that work? What would it buy me that I couldn't write (as easily) using what to me is the normal way?

Re: Everyday hassles in Go

#279

The article author points out, correctly, that Go code has far too much "interface{}" in it. That's an indication of real need for more power in the type system. Generics may be overkill. Parameterized types may be enough. The difference is that you have to explicitly instantiate a parameterized type. Generic functions and classes get instantiated implicitly when used, which gets complicated. (See C++'s Boost.) Go al…

That's not really the full story though. The parameterized type isn't just `map[K]V`, it's more than that. The type `K` needs to be hashable, and not all types support that. e.g., slices do not: http://play.golang.org/p/IKp_I25NW2 It gets more complicated then that too, because composite types can be used for keys, but only if the type does not contain any non-hashable type. Similarly, if you're going to build a bina…

True. A useful question to ask is this: what's the minimal parametric type design that would allow writing "map" and "chan" within Go? (Ignoring, of course, that "map" and "chan" both have special syntax; map has a "[]" operator, and "chan" has "select')

If we needed to write, say, "thread-safe map", or "network chan", with type parameterization, that should be possible.

Re: Everyday hassles in Go

#280

Earlier quoted context omitted.

Cool, now we have something to work with. However at such a high level no paradigm's differences (much less pros/cons) would be apparent. Would you mind implementing those individual functions? Actually it might be easier to use some open source embedded code. For completeness sake, I'd write the snippet above almost identically: pickUpBall = do openHand moveHandToBall closeHand

OK, now you've got me really confused. Is that Haskell code? I thought that Haskell couldn't do sequence except inside a monad. (Or is "do" a monad?) But if that isn't a monad, then why did you write it that way? My original claim was that a monad wouldn't do much for me in my world, and if you wrote this without a monad, that kind of seems like you're agreeing with me. You said that you'd gain composability from wri…

It would most likely be in the IO monad since IO would be happening.

As for whether monads would help your code (and I still think they would) I'll need a larger example. In a small example abstraction and reuse aren't really apparent.

If you can provide a larger example, we can find out who's right ;)

Alternatively I'll try to find a larger example if you can't or don't want to.

Post reply on HN