Hacker News new | past | comments | ask | show | jobs | submit login

We’re switching into Powershell for operations. With azure automation.

We’re switching to Go for concurrency. C and C++ for computation (though to be fair, we were already doing this with C# and the integration between them has always been great).

Our generalist language has become TypeScript however. Not because it’s great technically, but because it lets us share resources better which in term has made us much more productive in meeting our business needs.

I don’t think C# is bad, I also think it’s much better today than it used to be. If your use of it remains within what works well I think it’ll be hard to find a language with better tooling, but if your needs go beyond that you’re going to have to fight it a lot.




What does Go offer that C# does not? Both have actors, channels, threads, etc.


> What does Go offer that C# does not?

Nothing. This often happens when people don’t know .net to begin with. Better they go to go than complain about non existent issues in. .net.


Do C# channels offer lightweight concurrency ? The defining feature of Go is only matched by Erlang/Elixir and now Java. AFAIK C# has nothing like it.


C# approach to concurrency has always been better since its introduction. It does have Channels which offer more focused pattern for SPSC, MPMC, etc. scenarios but neither Java nor Go offer a comparable level of ease of use as C#’s hot-started tasks:

    // The tasks will run in parallel
    var data = service.GetData(id);
    var user = service.GetUser(name);

    Handle(await data, await user);
Re: the above comment on switching to Go for concurrency - probably one of the most ill-informed things I have read in the last few days. Doing this borders on incompetence due to the lack of analysis of the utilized technology - Go's GC offers far worse throughput and its concurrency story at best is "on par" with C#.


There is no async coloring in Go. In the example you cited above, service.GetData can be a plain synchronous function in Go. You don't need to distinguish between sync/async as this is defined by the caller and not by the callee. Any function can be made asynchronous without changing its signature. That's one of the critical advantages of having first-class concurrency. There is no "function coloring".

The simplicity of this approach and the advantages this brings to code structuring and easy refactoring simply cannot be understated.


Deferring to function coloring terms usually indicates a skill issue of not understanding that types are meant to represent what the code actually does.

Task-returning method indicates an asynchronously produced (deferred/delayed) result, a promise. If a language hides this fact (that the returned value needs to be awaited), it is grossly misdesigned - at most it can offer not blocking a thread, completely missing the point and leaving 20 years of improvements other programming languages have on the table.

But it's not as bad, yet instead in many other languages you are forced to manually schedule and then block/join until all of your tasks/promises/goroutines finish. Not in C#, that makes it as easy as it gets, which you can see in my example.

On top of that, you always pay for concurrency in Go, even when you don't use it, it is by definition always "colored" which further contributes to the overhead.

Also, in my example, the tasks will run in parallel. They won't in Go.


> Task-returning method indicates an asynchronously produced (deferred/delayed) result, a promise. If a language hides this fact (that the returned value needs to be awaited), it is grossly misdesigned ..

Very hard disagree. This depends on your computing philosophy. Go was designed based on the principles of CSP in mind and that code is produced by humans for humans first. The CSP architecture has proven to work and fit well for high-concurrent middleware. Not just for Go either.

You are not forced to block until goroutines finish as you claim. You can do other work or yield to the go scheduler. All the necessary busy work is taken care of by the runtime - which is terrific for folks who don't want to fiddle with low level details.

> On top of that, you always pay for concurrency in Go, even when you don't use it, it is by definition always "colored" which further contributes to the overhead.

And that is a completely fair compromise. Supporting easy concurrency natively in the runtime was an excellent design tradeoff since the computing world is moving to more and more cores. There are fewer and fewer uses for non-concurrent software.

> Also, in my example, the tasks will run in parallel. They won't in Go.

You appear to be confusing Go with NodeJS. If you have more than one core and GOMAXPROCS > 1, the tasks can indeed run in parallel.


> You appear to be confusing Go with NodeJS. If you have more than one core and GOMAXPROCS > 1, the tasks can indeed run in parallel.

What would the Go code look like that achieves identical behavior to the example above (tasks are dispatched concurrently and executed in parallel)?


Async coloring is a good thing (imo)


Your example is not concurrency though, it’s parallelism. You’re consuming two different services at the same time and waiting for the result. What you would want to showcase is how you handle two different consumers calling a single service. The difference is rather important once you have many consumers calling a lot of services and your computation needs to be done on the right state.

As a side note I really don’t think C# does parallelism better than Java.


It is both, please do not misconstrue this.

If two callers call the same method concurrently, whether it requires any synchronization or a more advanced primitive like Channel (for which C# has well-written implementation) or nothing at all is a case-by-case choice.

Java's parallelism by definition cannot be better because they had to retrofit a green threads design onto existing ecosystem, only ever addressing the hardware thread blocking issue with all the ceremony and bloat to do the most basic actions concurrently and/or in parallel still remaining in place.

Java requires far more steps to achieve comparable behavior for what C# requires you doing nothing or a method call at most. Dispatching array elements to a consumer in parallel? call .AsParallel(), and no, Java's Stream API requires more work. Want to fire off two asynchronously completing methods? Just use the example above, neither Java nor Go can hold a candle to this. Methods are CPU-bound and blocking? Easy - just use Task.Run to achieve the same.


> It is both, please do not misconstrue this.

I’m sorry, but it’s really not the same thing. You appear very confident, and sort of rude, in your argumentation, but there is just such a huge difference between parallelism and concurrency I don’t even know where to begin. I mean, you’re talking about (a)synchronous calls, tasks, and, what not, but what you need to solve is when two thousand sensors want to update the same data through the same service all at once. And they want to do this fairly often.

In reality it’s even more complex than this because a lot of the sensors carry data on behalf of each other so often you’ll receive the same data multiple times and so on, but there isn’t much need to get into that.

But hey, you do you, if C# works for you, great.




Join us for AI Startup School this June 16-17 in San Francisco!

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: