Hacker Read top | best | new | newcomments | leaders | about | bookmarklet login

>It reads data from reader and writes to writer... simple. Now what makes this little function so darn useful is it takes anything fulfilling its interfaces (io.Writer and io.Reader). The first way you will probably use it will be to copy between some stream and a file without having to eat up all the memory to store the buffer (not using ioutil.ReadAll for example)... but then you realize you can use a gzip compressor on the writer side, or a network socket, or your own code... and io.Copy works with anything that fulfills its interface

And how is that any different than any language with interfaces? (Besides the implicit thing?).



view as:

Because of the implicit thing! The api designer doesn't have to write the interface, you can do it yourself. As long as naming conventions are kept to and the signature matches, you can apply this anywhere.

Imagine a close() interface in Java. There isn't one - but having a try {...} finally { x.close(); } can be very useful sometimes. But having interface graphs made of granular interfaces makes everything slow and causes a lot of complexity when you try to think about your type hierarchy. That's why interfaces always just grow and you can't use them any longer because other classes only implement part of the api. Something usable for all of awt, swing, file handling, random foreign libraries? Unthinkable. Also, adding something in a later release (like CharSequence in 1.4) can have a wide ranging impact and requires you to change a lot of code.

In Go, you just add an interface from the union set of multiple structs api - and you can use it. No matter who wrote those structs. The value is enormous. Think of it as something like dependency injection at compile time.


Like duck typing?

I suspect this is like duck typing with some verification before compilation : the compiler checks that the object sent as parameter implements the correct interface.

It's called structural typing.

So, compile-time duck typing.

In the same Formula 1 is performance go-karting.

No, structural typing. It has a name already.

So, wikipedia says (http://en.wikipedia.org/wiki/Duck_typing#Structural_type_sys...):

"Duck typing is similar to but distinct from structural typing. Structural typing is a static typing system that determines type compatibility and equivalence by a type's structure, whereas duck typing is dynamic and determines type compatibility by only that part of a type's structure that is accessed during run time."

So it sounds like "duck typing" is defined in terms of run-time semantics. I guess you might be able to have genuine "compile-time duck typing" in a dependently typed language, which could be a good reason to preserve the distinction.

Otherwise, yes, they are certainly similar.


> Because of the implicit thing!

Known as structural typing and available in most modern languages.


available in most modern languages

Well, "modern" is an ill-defined concept. As far as I'm aware, structural typing is not really that common, is it? Besides OCaml and Scala, is there any relevant (used outside of academia) language that supports it?


D and C++ templates for example.

F# also supports it, given its ML linage.

C# tricks with dynamic, although in this case it is dynamic typing, so not really the same thing.


The disadvantage of C++ templates is the structural type is implicit - you only know if the input object satisfies the type if you read the documentation, code, or can decipher the error message that occurs if it didn't.

Concepts would have fixed this, but we don't have concepts and maybe never will!


> Concepts would have fixed this, but we don't have concepts and maybe never will!

enable_if and type traits are a workaround for the time being.

Concepts lite will definitely be in the next revision.


Would rust's "traits" count as structural typing? (I know Rust may not count as "relevant (used outside of academia)" yet, but maybe in the future.)

Haskell's typeclass provide it.

Typeclasses aren't structural typing, they are nominative typing, as typing is controlled by explicit declaration of relations between types and typeclasses, not inferred from structural properties.

Sure they are: (forall a. X a => a) is a supertype of (forall a. (X a, Y a) => a).

I stand corrected.

>Imagine a close() interface in Java. There isn't one

https://docs.oracle.com/javase/7/docs/api/java/lang/AutoClos...

You can even leave out the finally when you use an autocloseable resource.

    //r will be closed no matter what
    try(Resource r = getResource()) {

    } catch(SomeException e) {

    }

My Java is getting rusty... I read about this sometime somewhere but forgot it, thanks! I should have picked something like "String getText()", then.

Legal | privacy