An excellent talk about the importance of simplicity in the language which is anything but:
Monthly Archives: September 2018
Internets of Interest #4: Niall Murphy’s Polemic Against On-Call
The interaction between career development and on-call is actually really, really, bad. Bluntly, the profession takes on-call seriously, tries to be good at it, yet it is very very rare for this to be rewarded in any meaningful way. In 11 years at my previous employer, I never saw anyone get promoted for on-call performance.
Not once.
Internets of interest #3: Adam Fletcher on Life of an Airline Flight
One of my favourite talks from the elusive Systems We Love conference series.
Videos: https://systemswe.love/videos
Internets of interest #2: John Ousterhout discusses a Philosophy of Software Design
Ousterhout’s opus is tearing up tech twitter at the moment. But for those outside the North American prime shipping service area, we’re shit out of luck until a digital version is available. Until then, here’s Ousterhout’s Google Tech talk:
Slides: https://platformlab.stanford.edu/Seminar%20Talks/retreat-2017/John%20Ousterhout.pdf
CS190: https://web.stanford.edu/~ouster/cgi-bin/cs190-winter18/index.php
Internets of interest #1: Brian Kernighan on the Elements of Programming Style
“It turns out that style matters in programming for the same reason that it matters in writing. It makes for better reading.”
Douglas Crockford
I stumbled across this old (in internet years) presentation a few weeks ago and it’s been on high rotation since. If you can look past the recording difficulties (and the evacuation siren) this presentation is chock full of sound advice applicable to all programmers.
Maybe adding generics to Go IS about syntax after all
This is a short response to the recently announced Go 2 generics draft proposals
Update: This proposal is incomplete. It cannot replace two common use cases. The first is ensuring that several formal parameters are of the same type:
contract comparable(t T) {
t > t
}
func max(type T comparable)(a, b T) T
Here a
, and b
must be the same parameterised type — my suggestion would only assert that they had at least the same contract.
Secondly the it would not be possible to parameterise the type of return values:
contract viaStrings(t To, f From) {
var x string = f.String()
t.Set(string(""))
}
func SetViaStrings(type To, From viaStrings)(s []From) []To
Thanks to Ian Dawes and Sam Whited for their insight.
Bummer.
My lasting reaction to the Generics proposal is the proliferation of parenthesis in function declarations.
Although several of the Go team suggested that generics would probably be used sparingly, and the additional syntax would only be burden for the writer of the generic code, not the reader, I am sceptical that this long requested feature will be sufficiently niche as to be unnoticed by most Go developers.
It is true that type parameters can be inferred from their arguments, the declaration of generic functions and methods require a clumsy (type
parameter declaration in place of the more common <T>
syntaxes found in C++ and Java.
The reason for (type
, it was explained to me, is Go is designed to be parsed without a symbol table. This rules out both <T>
and [T]
syntaxes as the parser needs ahead of time what kind of declaration a T
is to avoid interpreting the angle or square braces as comparison or indexing operators respectively.
Contract as a superset of interfaces
The astute Roger Peppe quickly identified that contracts represent a superset of interfaces
Any behaviour you can express with an interface, you can do so and more, with a contract.
The remainder of this post are my suggestions for an alternative generic function declaration syntax that avoids add additional parenthesis by leveraging Roger’s observation.
Contract as a kind of type
The earlier Type Functions proposal showed that a type
declaration can support a parameter. If this is correct, then the proposed contract
declaration could be rewritten from
contract stringer(x T) {
var s string = x.String()
}
to
type stringer(x T) contract {
var s string = x.String()
}
This supports Roger’s observation that a contract
is a superset of an interface
. type stringer(x T) contract { ... }
introduces a new contract
type in the same way type stringer interface { ... }
introduces a new interface
type.
If you buy my argument that a contract
is a kind of type
is debatable, but if you’re prepared to take it on faith then the remainder of the syntax introduced in the generics proposal could be further simplified.
If contracts are types, use them as types
If a contract
is an identifier then we can use a contract
anywhere that a built-in type or interface is used. For example
func Stringify(type T stringer)(s []T) (ret []string) {
for _, v := range s {
ret = append(ret, v.String())
} return ret
}
Could be expressed as
func Stringify(s []stringer) (ret []string) {
for _, v := range s {
ret = append(ret, v.String())
} return ret
}
That is, in place of explicitly binding T
to the contract stringer
only for T
to be referenced seven characters later, we bind the formal parameter s
to a slice of stringer
s directly. The similarity with the way this would previously be done with a stringer
interface emphasises Roger’s observation.
Unifying unknown type parameters
The first example in the design proposal introduces an unknown type parameter.
func Print(type T)(s []T) {
for _, v := range s {
fmt.Println(v)
}
}
The operations on unknown types are limited, they are in some senses values that can only be read. Again drawing on Roger’s observation above, the syntax could potentially be expressed as:
func Print(s []contract{}) {
for _, v := range s {
fmt.Println(v)
}
}
Or maybe even
type T contract {} func Print(s []T) {
for _, v := range s {
fmt.Println(v)
}
}
In essence the literal contract{}
syntax defines an anonymous unknown type analogous to interface{}
‘s anonymous interface type.
Conclusion
The great irony is, after years of my bloviation that “adding generics to Go has nothing to do with the syntax”
2, it turns out that, actually, yes, the syntax is crucial.