Swift vs. Go
sapan.svbtle.com
sapan.svbtle.com
(BTW, if you're interested in Swift, I send a weekly newsletter at http://swiftnews.co)
http://www.h4labs.com/dev/ios/swift.html?week=0
http://www.h4labs.com/dev/ios/swift.html?date=0
http://www.h4labs.com/dev/ios/swift.html
My server is written in Go and runs on AppEngine. I like both Swift and Go. It's more convenient to work with one language but Swift probably needs a couple more years to bake on Linux. Go is fast enough that my AppEngine server never has performance issues. I highly recommend it.
I don't think there's much cross-platform work being done in Swift yet. Give it a little time, though, it's only been open sourced for a few months.
One nice thing about it compared to many other languages is that it can use C APIs with almost no work. There's no need to screw around with annoying FFI systems, you just point the compiler at your C headers and the calls become available in Swift. They may not be very idiomatic Swift, but they're at least no more difficult to use in Swift than they are in C. That means that you don't necessarily need a bunch of Swift libraries to be built before you can start getting stuff done.
Support for other platforms is an area of active development right now, though. The language itself is pretty much already there (for Linux, at least), with an official release for Ubuntu (and it's buildable on other distros), but the supporting frameworks around it are still a work in progress.
“strong” compared to what? Go's duck-typing actually makes it weaker than a lot more type systems than you might expect, and compared to something like Haskell or Rust, both of these type systems are incredibly weak. If you're comparing to C, then sure, but “strong” and “weak” typing mean nothing without reference to another language.
For me, it's strong enough and very versatile. It's stronger than what you effectively get in, say, Smalltalk. (Which, technically is strongly typed, having only 1 type of Object.) Having Interfaces explicitly documented in 1 place, but usable through duck typing is genius language design, in my view.
“Strong” and “Weak” don't mean anything in discussions of typing without a reference-point.
(0) Statically typed [e.g., Java] vs. not statically typed [e.g., Python].
(1) Dynamically typed [e.g., Java] vs. not dynamically typed [e.g., Haskell]. Yes, Java is both statically and dynamically typed.
(2) Safe for arbitrary resources [e.g., Rust] vs. only memory-safe [e.g., Python] vs. totally unsafe [e.g., Objective-C].
(3) Typeful [e.g., Haskell] vs. not typeful [e.g., Objective-C].
(4) Global [e.g., Standard ML] vs. local [e.g., Scala] vs. no type inference at all [e.g., Java].
(5) Reflective [e.g., Common Lisp] vs. not reflective [e.g. Rust].
(6) Fixed [e.g., Standard ML] vs. extensible on top of a fixed core [e.g., C++] vs. extensible and modifiable [e.g., Common Lisp].
With respect to Haskell and dynamic typing, I am curious whether you had considered Typeable and Data.Dynamic in your analysis (and, in general, your thoughts on how they relate to the distinction being made).
GHC-specific implementation detail.
> the trust that bad instances are never created
The only way I can trust it is if the compiler enforces it, at which point it isn't “just a library feature”.
“Strong” and “Weak” are inherently relative terms; so, when used without a reference point, they will mean something different to different people. So, without a point of reference, the terms are not useful.
let x: Int = 3
let y: Int = x
and let x = 3
let y = x
are identical; in both cases, x and y are both strongly-typed as Int.I understand that both Go and Swift are statically typed. My comment is about saying that Go and Swift have type systems which are really strong, but such an assertion means nothing unless you give a point of reference (i.e., “strong compared to X”)
To clarify, type inference and strength (or strictness actually) of typing are completely unrelated. For example, Haskell, which is statically typed (and far stronger than most other languages out there—though certainly not the strongest) has incredibly good type-inference, so you rarely need to specify types.
Error codes are explicit and devoid of implicit automagic. You're not going to break a lot of contracts and alter semantics by adding a keyword. The error codes are explicitly part of your function signature, in the most stupidly straightforward way possible. If you're going to be a bad developer and ignore error codes, this is going to appear explicitly in your code. (As opposed to being rewarded with "cleaner" code when you sweep exceptions under the rug.)
Um, what problems do exceptions introduce that panics don't?
In any case, the argument in favor of using return values for handling error conditions would be stronger if Go had proper tagged unions. With tagged unions, you can guarantee that exactly one of an OK result of an error object will be returned. Right now, Go has the very confusing situation that a function might return two `nil`s (the operation neither succeeded nor failed) or two non-`nil`s (the operation both succeeded and failed), neither of which makes any sense.
I'm a fan of making errors explicit, but I continue to find the use of effectively a product type (value and error) to return what is actually a sum type (value or error) to be ugly and error prone. Ideally, invalid states should be unrepresentable. In this case, both "value and error" and "no value and no error" are not. This is not good design.
And clearly any language in which invalid states are representable is useless? Nice try, but nah. I like me some pure functions sometimes, but I'm not dogmatic about it.
"And clearly any language in which invalid states are representable is useless?"
I did not call anything useless, much less the entire language.
And I am the first to agree that trade-offs need to be made between a variety of considerations. But in this case, for the approach under discussion, I pointed out a design criteria that I find often important, that this approach is in flagrant violation of, while getting basically (perhaps literally) nothing in return toward any other design considerations.
Either I missed things or that's just a bad decision. If you think it's the former, please engage me more constructively so that at least one of us can learn something.
"Nice try, but nah."
This is needlessly rude.
"I like me some pure functions sometimes"
This issue has zero to do with pure functions.
"but I'm not dogmatic about it."
Right, pointing out bad design can only come from a place of dogma. Never experience, never consideration, and never anything that could permit substantive discussion.
I'm not sure about Swift, but in some languages you can statically check case statements to make sure that every enum has a case, which is not possible with Go.
Traditional enums aren't particularly interesting. What languages like Rust and Swift have are tagged unions. They let you associate data with each variant.
Moreover, pattern matching is needed to use tagged unions effectively.
Constants are not "basically" tagged unions or even enums. They are not grouped into a parent type. For example, if you have a `Foo` enum with `A` and `B` variants; while matching or accepting this, you can accept a `Foo` which is guaranteed to be either `A` or `B`.
How would Go typed constants achieve this?
Maybe when binary packages are available for non Ubuntu Linuxes?
Though as pointed out in SR-116 without ABI stability (which will not appear until Swift 3) packages do not necessarily provide a silver bullet of portability.
I for one have been maintaining a PKGBUILD script for Arch Linux that allows for a native package to be created. It's currently not working due to some issues with binutils [2].
[1] https://bugs.swift.org/browse/SR-116 [2] https://bugs.swift.org/browse/SR-1023
GCC has better micro-optimization in gccgo, but the compiler lacks important features like escape analysis and an up-to-date runtime so it's slower on real-world code.
I think the ideal for best performance of generated code is 3 IRs: a mid-level language-specific IR for high-level optimizations (especially around memory management and devirtualization), a low-level IR for lower-level optimizations (e.g. algebraic simplifications), and a codegen IR (for instruction selection and scheduling). This is what Swift is doing, as far as I can tell.
Seems clean.
Going to check it out more over time. Hope the Linux support improves.
Can we go back to Web 1.0 please? Everything was simple, everything worked, everything was fast. Or at least can we compromise and have a few reasonable design choices from Web 2.0 and Web 3.0 merged back in with Web 1.0, and just go with that? The current Web is just too broken, but there's nowhere to file a bug report.
I believe if you hover over it again it reverses the behavior, but I'm not certain. Regardless, it's not a good interaction paradigm.
Edit: It's not reversible. I thought I'd managed to undo one before, but I guess not.
No. Software is allowed to evolve, even if you don't like it.
>Or at least can we compromise and have a few reasonable design choices from Web 2.0 and Web 3.0 merged back in with Web 1.0, and just go with that?
No. People are allowed to make their own decisions about how to design and build their sites, and they have the freedom to make decisions you disagree with.
>The current Web is just too broken, but there's nowhere to file a bug report.
It's broken for you, but it's extremely entitled of you to declare it broken for everyone. Far, far more people would consider "revert to Web 1.0" to be a broken experience, and the web belongs as much to them as it does to you.
> No. Software is allowed to evolve, even if you don't like it.
Translation: Programmer Hubris is a constant.