JuliaLang/julia — pull request #7695 by abe-egnor (2014-07-22 20:34:51+00:00)
Title: Interface definition and implementation macros

Example:
```julia
@interface stack(Container, Data) begin
push!(Container, Data)
pop!(Container)
end

@implement stack{T}(Vector{T}, T) begin
push!(vec, t) = Base.push!(vec, t)
pop!(vec) = Base.pop!(vec)
end
```

This expands to:
```julia
stack(Container, Data) = [
:push! => (Container, Data),
:pop! => (Container,)
]

push!{T}(vec::Vector{T}, t::T) = Base.push!(vec, t)
pop!{T}(vec::Vector{T}) = Base.pop!(vec)
```

Notable features:
* Interfaces and interface methods are normal functions, and can be exported, imported, passed around, inspected, etc.
* This does not introduce any new form of method overloading/resolution, it compiles down to normal Julian multiple dispatch.
* The methods are not owned by the interface, nor is the interface owned by any abstract type; it is a declaration that for any *list* of types, they conform to the interface if a particular list of methods is defined on those types.
* Interface implementations can be type-parameterized, creating a family of interface implementations in the same way that a type-parameterized method definition creates a family of methods. If a type parameter is unused by a particular method's type bindings, it will be stripped.

Notable warts:
* This inherits the same problems with scope that normal function overloading has; if the intended functions aren't imported, new ones will be silently created.
* Party A can declare an interface, and party B can be certain they've implemented it, but party A cannot define methods that require (in an enforced manner) parameter types to have an implementation defined for them. This may be considered a wart or a feature depending on one's language philosophy; it prevents some potential bugs from being caught pseudo-statically, but allows methods to work on a wider variety of types (i.e. if they happen to have the methods defined outside of the interface mechanism).