Also, the lack of robust battle-tested web-frameworks is right now a show stopper for me.
Also, the lack of robust battle-tested web-frameworks is right now a show stopper for me.
These are the kind of developers who have by now been burned by the inherent dangers and drawbacks of dynamic languages. They know enough to know that there must be a better way to develop safer, more reliable and better-performing software. They just aren't familiar enough with existing statically-typed compiled languages to know what's already possible.
Go may just be in the right place at the right time. It is simpler than languages like C, C++, Haskell, SML, and even Scala, for example. And it is getting a lot of hype just when these dynamic language refugees need something better, and are actively looking for it.
While it's good that Go offers a much better environment and infrastructure than many of these developers are accustomed to, this may also be harmful in some ways. It may be just "good enough", at least compared to the alternatives that they're familiar with, that they don't feel the need to explore more established languages which do offer much more.
Even if they don't move past Go any time soon, at least it's encouraging to see them using a more responsible language for larger-scale software projects.
I also remind fellow Rubyists who say "Go is boring, it's supposed to be that way!" that when they talk shit on Java, that was one of its rallying cries as well.
It's all just a bunch of cycles, what's trendy comes and goes, is boring and then interesting again...
The people who think Go is great are the same who lack substantial experience with any remotely modern programming language.
Scala has every feature and language construct under the sun and full access to the astounding landscape of Java -- as well as amazing tools like Akka. This is all wonderful, and I enjoy using Scala because it is rich and you can treat is very functionally.
That said, I now prefer Go to it after shipping two production products on it. A deploy that is second to none, amazingly fast development cycles, easy to build rich custom tools on top of it (for example go-diff, which ignores syntax differences and only shows functional differences), the easiest cross compilation I have ever used, and a focus on this exceptional clear and easy to read code (lack of implicitness / magic). It reminds me a lot of what I like about Erlang -- with some of the more annoying bits stripped away.
But, at the end of the day I am using Go for three reasons:
1) Lets me get work done quicker than other languages (and win contracts / beat competition)
2) I can keep the entire spec (50 pages) in my head, with very little time spent. I have used Scala far longer, but would never make such a claim about it.
3) The tool chain (build, cross-compile, test, format, doc) that comes with it is amazing, the least obnoxious I have ever used. It has warts (get), but all in all -- it makes using anything else exceptionally painful. Once you get used to "go test ./... && go install ./..." to build your app and put it in ./bin -- and you get used to doing deploys with "scp bin/foo server..." everything else starts to feel stupid.
Nope.
Yes, Scala has loop/react ... but they are really just a different way of writing callbacks, and don't allow you write truly synchronous-style code over an event based system.
Simply have each of those methods you wish to call return a future...
[1] https://github.com/scala/scala/blob/v2.10.2/src/library/scal...
The style one can program in and the style it is implemented isn't connected the way you think it is.
And no, Scala "doesn't have" loop/react. Unlike Go, where people seemingly put random stuff into the language, it's just a bog-standard library.
"The style one can program in and the style it is implemented isn't connected the way you think it is."
The above might be alluding to techniques for pretending to have these language features when one does not. You can write CPS manually, and you might even be able to make a machine apply the CPS transformation automatically to your procedural code. Neither of these things sound particularly fun, compared to the alternative of writing procedural code and then debugging the code that you've actually written. It's little help that you have to return every once in a while to avoid a StackOverflow due to the language's embarrassing lack of TCO.Edit: Apparently if you use Squawk you can have green threads. Can you have OS threads as well?
This whole sort of back and forth exchange of escalating condescension is not rare on the internet, but I was surprised that dino wouldn't actually tell anyone why we were wrong. Generally I've found this quote http://bash.org/?152037 to be more or less true; asserting that a system is incapable of things it is capable of is met with people pointing out how to make it do those things. In this particular instance the response from dino involved much more effort than a simple lmgtfy link while accomplishing dramatically less in the promotion of his faith, or even the promotion of any sort of knowledge at all.
This feature is a little obscure, and one could easily spend a great deal of time writing Scala professionally without ever passing "-P:continuations:enable" to anything. I believe that one would be missing out.
TCO is a runtime property, not a language property.
Anyway, you have clearly not been doing your research and its not my job to do it for you.
Bye.
Edit: I am still seeking the legendary JVM implementation with TCO. I guess the argument is something like, oh well at some point in the future some JVM could conceivably have that feature, therefor it is wrong to say that Scala does not have it! Rather than writing code that assumes Scala is a complete joke of a functional language, one could simply write the code the natural way, verify that it compiles, and then wait until a JVM with TCO exists, so that it will stop crashing! In the mean time, one can enjoy the entertainment provided by Scala's inability to compile shift in an if statement without an else clause. Truly I am writing code exactly as I would if(it_was_synchronous) else { cpsunit }.
I feel as though you told me reset and shift, although you did not. So thanks for that!
scala> :paste
// Entering paste mode (ctrl-D to finish)
object TCO extends App {
def stackSize = Thread.currentThread.getStackTrace.length
def printStackSizeMessageOutside() =
println(s"$stackSize stackframes outside of the mutually recursive calls")
def printStackSizeMessageInside() =
println(s"$stackSize stackframes inside the mutually recursive calls")
def mutuallyRecursiveAdd1(a: Long, b: Long): Long =
if (b == 0) {
printStackSizeMessageInside()
a
} else
mutuallyRecursiveAdd2(a+1, b-1)
def mutuallyRecursiveAdd2(a: Long, b: Long): Long =
if (b == 0) {
printStackSizeMessageInside()
a
} else
mutuallyRecursiveAdd1(a+1, b-1)
printStackSizeMessageOutside()
mutuallyRecursiveAdd1(23, 10000000)
}
// Exiting paste mode, now interpreting.
defined object TCO
scala> TCO main null
We have 29 stackframes outside of the mutually recursive calls
We have 30 stackframes inside the mutually recursive calls 27 stackframes outside of the mutually recursive calls
java.lang.StackOverflowError
at TCO$.mutuallyRecursiveAdd2(<console>:22)
Oddly, your Thread.currentThread.getStackTrace.length seems to return strings like "We have 30". Mine is returning an Int over here.After a significant amount of effort (googling for stuff about scala, JVMs, and TCO mostly gets hits with people complaining about their code not working) I discovered something called Avian, which I can try out soon. I still think it is a bit weird to spend time engaging with a stranger who wants to know something very simple, but to expect the stranger to dig around for it for a few hours instead of telling him.
This way people who are lazy, whose interest is just strong enough to make ridiculous claims and complaints but don't actually care about the topic at hand, don't get things for free.
I protect my investment and everyone wins.
The implementation determines what happens when synchronous, blocking code, well blocks.
In Go it yields to another green thread (Goroutine).
In any language implemented on the JVM (including Scala) you block an OS level thread.
The way languages without green thread support allow non-blocking, event based code is through callbacks, which can get pretty horrendous in large, complex programs.
> Unlike Go, where people seemingly put random stuff into the language, it's just a bog-standard library.
I'm not sure why that is relevant (Actors seem a pretty core part of Scala), but I guess it is unsurprising that a mere library on top of the JVM is still constrained by the kind of concurrency supported by that platform, i.e. the lack of green threads.
Wrong. Whether JVM implementations use green threads or system threads is an implementation detail. There are implementations for both cases.
You realize that many JVM implementations started with green threads in the early days and abandoned them not much later? There is a reason for that.
> The way languages without green thread support allow non-blocking, event based code is through callbacks, which can get pretty horrendous in large, complex programs.
Wrong. I repeat, the underlying threading model does not necessarily enforce some style of API.
> I'm not sure why that is relevant (Actors seem a pretty core part of Scala)
Actors are a library, just like Scala's async/await, the Future/Promises library, the continuation library, Java's Fork/Join library.
Actually, Scala just replaced its “official” Actor library in the last release. Go will be stuck forever with its ad-hoc stuff which has been hard-coded into the language.
> it is unsurprising that a mere library on top of the JVM is still constrained by the kind of concurrency supported by that platform, i.e. the lack of green threads
LOOOOOOOOOOOL. Since when are green threads the “new best thing ever!!!11!!”? Did I miss a memo here?
You know what? Wake me up when Go has fixed their broken scheduler. Until then, I just keep watching how the JVM embarrasses Go on pretty much every concurrency and scalability workload.
Obviously it is an implementation detail, and for any JVMs that support green threads (none of the major ones do), then it would be a different matter entirely.
> You realize that many JVM implementations started with green threads in the early days and abandoned them not much later? There is a reason for that.
Java was created in the mid-90s before every man and his dog was trying to solve the c10k problem on a $5/month VPS. Hardly surprising.
> Wrong. I repeat, the underlying threading model does not necessarily enforce some style of API.
But it does allow for it, or make it easy. Why do you think Scala has both blocking, and "event based" (loop/react) API's?
> Since when are green threads the “new best thing ever!!!11!!”? Did I miss a memo here?
Quite possibly, you must have been living under a rock if you haven't heard of callback hell in Node.js. Funny because Node was the coolest thing ever a couple of years back, how times change.
> You know what? Wake me up when Go has fixed their broken scheduler. Until then, I just keep watching how the JVM embarrasses Go on pretty much every concurrency and scalability workload.
Java has great MT concurrency. It's light-weight concurrency (NIO) is about as good or bad as any other event-based systems out there. What is lacks (my original comment) is the ability to write event-based code using a synchronous, blocking style (without callbacks).
The only contenders there are Go, Haskell, and possibly some of the scripting language extensions (Python/Gevent, Perl/Coro).
And if by "broken scheduler" you mean it's lack of preemption...then I would say rethink your design, you should be handing long-running jobs to a work queue anyhow.
Have fun moving the goal posts around.
> Java was created in the mid-90s before every man and his dog was trying to solve the c10k problem on a $5/month VPS. Hardly surprising.
So what? C10k isn't a hard thing to do on the JVM and it probably beats Go by a large margin in terms of latency and performance.
> Why do you think Scala has both blocking, and "event based" (loop/react) API's?
Your point is ...? There are plenty of different libraries, because concurrency can be tackled in different ways. Use the right tool for the job. Unlike in Go, where you pretty much have to shoe-horn everything into “goroutines” or channels.
The lack of developers which run around and try to tell everyone that they found the silver bullet for solving concurrency in Scala is a sign of a mature community which has experience and expertise and doesn't just repeat whatever Rob Pike says like Go users seem to do all day long.
> Quite possibly, you must have been living under a rock if you haven't heard of callback hell in Node.js.
Eh ... so what? It's not like Node's terrible approach is the only alternative to Go's approach. Claiming “A is the best, because B is even worse” just shows a complete lack of knowledge of existing solutions.
> What is lacks (my original comment) is the ability to write event-based code using a synchronous, blocking style (without callbacks).
Again: No it doesn't. Do your research instead of claiming blatantly false things.
It is using the traditional threading model, which is all it had before NIO came along.
> Your point is ...?
My point is if Scala's synchronous API was compatible/built on an event based system or green threads, then the far less attractive callback based API would not exist. Just like Go doesn't have callbacks...what would be the point?
> Use the right tool for the job.
Go doesn't claim to be good at everything. If you want great traditional multi-threading then by all means use Java. If you want a highly-scalable network engine with code that doesn't look like spaghetti, use Go.
> The lack of developers which run around and try to tell everyone that they found the silver bullet for solving concurrency in Scala is a sign of a mature community
I don't don't hear many Java programmers running around complaining about hand-editing reams of XML either...I still don't envy them.
> Claiming “A is the best, because B is even worse” just shows a complete lack of knowledge of existing solutions.
I don't think Go is "best", and I already gave you examples of other synchronous, event-based languages (you still haven't shown me an example in Java/Scala). I actually prefer Python/Gevent for most things.
> Do your research instead of claiming blatantly false things.
Well I think the onus is on you to provide some evidence to back up your claims.
https://news.ycombinator.com/item?id=6125567
http://jim-mcbeath.blogspot.com/2010/08/delimited-continuati...
https://github.com/jimmc/scoroutine - some of the examples in this are godawful, but you'll find that they still work if you rewrite them to be legible.
// Some example methods which might spend waiting for other
// services (calling the database, sending emails).
def getEMailForUsername(username: String) =
future { DB.Users.find(_.name == username).get.email }
def sendPassordRecoveryMail(email: EMail, message: String) =
future { SMTPService.send(email, message) }
// Future/Promises API:
def resetPassword(username: String) =
for {
email <- getEMailForUsername(username)
result <- sendPassordRecoveryMail(email, "some message")
} yield result
// Async API:
def resetPassword(username: String) =
async {
val email = getEMailForUsername(username)
val result = sendPassordRecoveryMail(email, "some message")
await(result)
}
@smegel:
I don't see any “callback hell” or “code that does look like spaghetti” here.
By the way, I'd love to see a link to “Scala's synchronous API” and that mystical “far less attractive callback based API”. Or are you making things up again?