
It is ridiculously easy to refactor Go - bslatkin
http://www.onebigfluke.com/2013/01/it-is-ridiculously-easy-to-refactor-go.html
======
dons
Welcome to bounded polymorphism, circa 1989. A young Wadler would be pleased.

An aside, it is not "duck typing" if it involves a static type system.

~~~
voidlogic
Thanks right, technically Go supports a structural type system* which is a
similar to, but different than duck typing. But the Go community often refers
to Go as being duck-typed due as that term is more familiar to people coming
from languages like Python.

* <http://en.wikipedia.org/wiki/Structural_type_system>

~~~
zemo
"often" is stretching things a bit. The reason this terminology popped up is
that it was in the official documentation, but it was (or is scheduled to be)
taken out.

anyway, you're right, it's not duck typing. Duck typing happens at runtime.
With Go, every variable has exactly one type at compile time. Sometimes that
type is an interface type. With duck typing, the checking happens at runtime.
There's no runtime type checking with Go's interface system.

~~~
NateDad
Nothing says duck typing has to be at runtime.

The only requirement to duck typing is "an object's methods and properties
determine the valid semantics, rather than its inheritance from a particular
class or implementation of a specific interface".

This is exactly how Go's interfaces work. You define the methods you require
an argument to have, and then anything that has those methods can be used as
that argument, without the original type having any knowledge of the interface
that was designed. The only difference between Go and Python in this regard is
that Python doesn't actually define what a duck is for a specific method, it
is implicitly defined by the methods that are called on it. Go explicitly
defines what a duck is, which makes it a hell of a lot easier to know if the
object you're passing in qualifies as a duck without reading every line in the
damn function.

Yes, go checks that an object is a duck at compile time, that doesn't have
anything to do with duck typing.

~~~
Dn_Ab
It is true that duck and structural typing have only a subtle difference. But
it is also true that duck typing has to be at run time essentially by
definition.

Structural typing looks for structural isomorphsims - it is total. Duck typing
looks at run time compatibility, so long as the runtime accessed portion is
the correct signature it passes.

So structural typing is about isomorphisms and duck typing is about checking
the correct boxes before entry. Both have the attribute of looking at
structure but you cannot expect them to cluster types in the same manner.

In ML* terms I like to think of structural typing making hard clusters and
Duck typing allowing for soft clusters.

* No, not that ML.

~~~
NateDad
Structural typing is duck typing at compile time. I'm fine with that
definition.

~~~
Dn_Ab
Sure if you define the difference away anything can be the same.

But you cannot expect them to always behave the same way. That is, { f_d(t) |
t ∈ T} <> {f_s(t) : t ∈ T} where f : T -> T set takes a type and returns the
set of types in T equal to it and f_s , f_d check for equivalence via
structural and ducks respectively. You can expect f_s to also define a
partition over T but not necessarily the same for f_d. f_d is vaguely defined
there but if you pretend it acts like it simulates how a runtime check would
occur, |f_d| will tend to be >= than |f_s|

An example of how structural typing is not just compile time duck typing is
because such a thing exists (in F#) and is not the same as structural typing.

~~~
sirclueless
I'm beating a dead horse here, but is there a difference between "compile-time
duck-typing" and "structural typing" besides just type inference? It seems to
me that so long as the duck-typing language really does unify types, they are
the same thing, except that with structural typing you have to write down the
type somewhere and it can be a more restrictive type than the actual runtime
calls necessitate.

~~~
zemo
yes, with structural typing, you have to be able to do everything a duck can
do, not just the duckish things you're interested in locally. In duck typing,
if all you're interested in is walk_like_a_duck, anything with
walk_like_a_duck is acceptable, even something that doesn't talk_like_a_duck,
because in reality, you never defined the "duck" type to begin with; the
actual "duck" type doesn't even exist. In structural typing, "duck" would be a
concrete type. "duck typing" is a pretty shitty name for it, to be honest,
because of that saying "if it walks like a duck and talks like a duck, it's a
duck", but the reality is it's more like "if I need something that
walks_like_a_duck and this walks_like_a_duck then it's good enough for me".

let's put it in another perspective: if you have a function that takes
disparate types, then the thing that's passed in that function may be of
arbitrary type. It's unknown at compile time how much memory will be allocated
for the instantiation of that function in order to accept the parameter,
because the type that's being passed it is unknown. In structural typing, like
in Go, you know at compile time the type of the thing being passed in, and
therefore, the amount of resources that will be required upon calling.

Or in another sense, an array of an interface value in Go has a well-defined
memory layout, whereas an array of disparate types in a dynamic language does
not have a well-defined memory layout at compile time.

internally, an interface value in Go is a two-tuple; it's an actual
_additional_ structure; it _boxes_ the structure we're interested in. With
duck typing, there is no box.

so yes, it's actually very different. The difference is more meaningful than
people generally let on.

------
scott_s
I think you could actually do this in C++, but not with runtime polymorphism.
I think you should be able to define extractBody and extractTextBody as
template functions. If the signatures (return type, name and parameters) of
the functions of the interface are identical - and it looks like they are -
then this would work as a C++ template function. Behind the scenes, the
compiler would generate two different kinds of functions for you, one for each
of the types you called it with.

(Please note I'm not saying this would be _better_ , just pointing out that
it's possible.)

~~~
pdhborges
And he doesn't even have to define an interface.

~~~
scott_s
Concepts were an attempt to allow people to explicitly state what that
interface is: <http://en.wikipedia.org/wiki/Concepts_(C%2B%2B)>

------
VeejayRampay
Great article. As a side note, you might want to consider reformatting the
blog post using syntax highlighting to make the code more readable and
obvious. Thanks for posting though.

~~~
mseepgood
<http://kyleisom.net/blog/2012/10/17/syntax-off/>

Syntax highlighting is less common in the Go community since Rob Pike called
syntax highlighting juvenile :D [https://groups.google.com/d/msg/golang-
nuts/hJHCAaiL0so/kG3B...](https://groups.google.com/d/msg/golang-
nuts/hJHCAaiL0so/kG3BHV6QFfIJ)

He also argued against keyword emphasizing:
<http://www.lysator.liu.se/c/pikestyle.html>

~~~
shadowmint
...

This is surely a minority view.

Everyone uses syntax highlighting, for everything. _for everything_

I can't honestly believe the whole go community just decided to by like, oh
gee, well Rob doesn't like it, I gues _we'll just ignore what everyone else is
doing and do our own thing_.

For what it's worth, _I_ use syntax highlighting in my go code, and so does
<http://tour.golang.org/>

~~~
VeejayRampay
And everyone uses it for a reason: color is one of the primary discriminators
of human vision, it carries information efficiently and does it instantly, as
clearly laid out in the Wikipedia article about visual search (pop-out effect)
: <http://en.wikipedia.org/wiki/Visual_search>

It seems strange that Rob Pike would call it "infantile". I don't think it's
very modern (nor mature) to say that either, since it completely ignores years
of research done on the subject by scientists. But then again, to each his/her
own.

~~~
dchest
He isn't arguing that highlighting doesn't carry more information. I think
he's saying that it carries useless or wrong information.

------
shurcooL
Go has really grown on me in the last few months, it's becoming my favourite
language, coming from C++.

~~~
Tekker
I've been working in C/C++ for over 20 years now. I started playing with Go
about two months ago, burnt through the tutorial in 2 afternoons, and was
hooked. It's very easy coming from a C background, it has constructs I'm
familiar with, but also picks out the best parts of Python-ish SmallTalk-ish
languages, while still being compiled.

I'm looking forward to when I can write Android apps in it, instead of mucking
around with Java.

~~~
dualogy
Exactly... the day Go compiles for mobile devices is the day I'll dig into
mobile development.

But the thing with mobile OSes is, you need a sane binding to the native GUI
lib.

However, it would be awesome to circumvent this and just be able to do what I
can already do with GLFW and OpenGL across 3 different desktop OSes: open a
blank window that's just a canvas for GPU (GL) commands. Seeing how OpenGL ES
is on all smart phones, having an equivalent "mobile GLFW" library and GLES
binding would be awesome and good enough to roll one's own snappy GUIs.

Oh, all that only once Go compiles for said mobile OS / HW in the first place,
which is probably still a few years off...

------
jbrackett
I went into the article thinking it was going to be about some way of renaming
functions or something. Probably just my limited internal definition of the
word refactor. After reading I would say Go has a cool built in way of using
the adapter pattern. More interesting than renaming functions.

~~~
eknkc
Actually, Go makes this somewhat easy too. Check this:
<http://blog.golang.org/2013/01/go-fmt-your-code.html> It's possible to do
context aware source code substitutions. Works great. (Not that it's something
new or groundbreaking though, just relevant to your expectation)

~~~
pjmlp
Comparing gofmt with what refactoring tools allow is too far fetched.

~~~
redbad
Are you aware of gofmt's rewrite rules?

<http://golang.org/cmd/gofmt/#hdr-Examples>

Pretty powerful stuff.

~~~
pjmlp
I am. Refactoring is much more than that:

\- create functions and methods from code snippets

\- merge duplicate code

\- Semantic renaming of method names/variables/functions without affecting the
same name being used in a different context

\- convert field direct access to wrapper functions/methods

\- remove dead code

\- add missing code to interface/module/class where it is being applied

\- validation of code references in comments

\- ...

------
mahmud
Folks, recursive data-strcutures are CS101. Processing them is also a trivial,
template-filling exercise. First you specify the (recursive) datatype,
consisting of the simple "leaf" elements, along with the complex forms. Then
you write your program consisting of a series of mutually recursive functions.

What matters is that once you specify the data type, the code that processes
it follows immediately from the grammar.

~~~
adam-a
I think you're slightly missing the point. It's not the use of recursive
functions or data structures that is interesting. It's that, in Go, you can
add a new type which covers externally defined types, and those types are now
instances of the new type automatically. In other languages, to unify two
types like this with a common interface, you would probably have to define a
wrapper class which proxies the calls to the real objects. Even though the
methods for the two classes have matching type signatures and do the same
thing already.

------
chipsy
Haxe has a similar (but not quite identical) bag of tricks which act as a
"gradient" of stronger/weaker couplings.

You have to specify that an implementation can use a specific interface, but
you may overload an implementation with multiple interfaces.
<http://haxe.org/manual/2_types#interfaces>

You can use structure types instead of classes and rely on structural
subtyping to match them. <http://haxe.org/manual/2_types#structural-subtyping>

And you can ask for dynamic type behavior wherever the code needs it.
<http://haxe.org/ref/dynamic>

------
zcrar70
Typescript allows you to do this also. It's extremely convenient.

------
skrebbel
I don't completely seee the point - in more established OO languages you'd
make two one-line wrapper classes that both implement Get() and be done with
it. Not stuck at all.. Extra indirection, yes, but is your performance going
to block on parsing mime mails?

~~~
Djehngo
I assumed you would do the same thing as was done in the article.

Create an interface and have a function that takes implementations of that
interface as a parameter. The difference would be that in Java or C# you would
need to explicitly mark Header and MIMEHeader as implementing emailHeader

I don't think much will come of discussing what is/isn't possible in a
language given that they are all Turing complete. Usually posts like this are
used for discussing what's easier or cleaner in a language.

For what it's worth I think having dynamic interfaces is cool, but I can only
really think of one place I have actually relied on that capability.

Mostly the "dynamic"ness is nice for decoupling code. You can have a
package(A) containing a function that takes an interface a parameter, a
package(B) containing an implementation of the interface in A and a package
(C) which passes the implementation in B to the function in A.

Given this situation C needs to import A and B but neither A nor B need to
know about each-other.

------
6ren
To be fair, you can do this in java by adding to _Header_ and _MIMEHeader_ "
_implements emailHeader_ ".

Structuring typing seems simpler. Are there any downsides? (apart from two
types having an identical method signature by coincidence)

~~~
LeafStorm
> To be fair, you can do this in java by adding to Header and MIMEHeader
> "implements emailHeader".

Not if you aren't the author of the package. (You could modify your local
copy, but requiring a fork is always a pain.) Without the ability to modify
the sources, you would have to create custom subclasses of Header and
MimeHeader which implement that interface, and find some way to make the
library generate your custom subclasses instead of the defaults.

~~~
bslatkin
Exactly

------
Benferhat
Off-topic: I had to use Readability[0] to make your blog readable.

[0] <http://www.readability.com/shorten>

------
Uchikoma
I wished for years for Java to determine "implements interface" by method
checking not the way it does it currently.

And while Scala has "structural typing" I'd also wish it would implement it
the way Go does not with explicit methods.

------
knodi
I hope go 1.1 will be ready soon. A lot of goog stuff in it.

~~~
signa11
care to elaborate ?

~~~
Mr_T_
He/she probably wanted to say "good": [https://groups.google.com/d/msg/golang-
nuts/FxELIOik2f4/X5x7...](https://groups.google.com/d/msg/golang-
nuts/FxELIOik2f4/X5x7rDsh8moJ)

------
Ramonaxvh
Go has been out for a while, it's really cool to see it finally starting to
gain traction.

------
martinced
Refactoring is probably the one area where good IDEs shine the most.

I was expecting to see some advanced Emacs / vim or whatever texteditors _or_
IDE support for refactoring Go code.

Not just manual extraction of common behavior into a tinier interface.

But I'm more and more impressed by Go and may give it a try one of these days.

~~~
est
I doubt it.

How could anyone refactor something like this in Python

getattr(myobj, 'myprop', None)

Where mypropis dynamically generated?

~~~
eru
What do you mean by refactoring a single line?

