Anonymous types

Is it possible to define an instance of an interface?

e.g. something like:

abstract type Foo; end
instanceOfFoo = convert(Foo, (x=1, y=2))

You can not create an instance of an abstract type. A NamedTuple might be the closest you can come to an anonymous type in the sense that it has all the information associated with a concrete type, except for a name.

2 Likes

What would be the use of such `instance of an interface’? I am not aware of the existence of this concept in other languages.

2 Likes

It’s a obscure(?) java feature; were it is called an anonymous class.
Javascript also has them, but it is advised against using them.

I have only ever seen them used in Java to emulate having anonymous functions.
Back before Java got lambdas.

Totally distinct from what C# calls an anonymous type though, which is what we would call a NamedTuple
.

3 Likes

does C# consider two anonymous types with the same names and types of the fields the same? because we do:

julia> typeof((a=2, b=0.3)) === typeof((a=1, b=0.5))
true

edit, also yes for C#:

If two or more anonymous object initializers in an assembly specify a sequence of properties that are in the same order and that have the same names and types, the compiler treats the objects as instances of the same type.

Hi,

I thought it as a way to implement inheritance and extensibility.

For instance:

abstract type Interface; end
x(instance::Interface) = getproperty(instance, :x) 
y(instance::Interface) = getproperty(instance, :y) 

struct Impl1 <= Interface; x; y; end

struct Impl2 <= Interface; x; y; z; end

foo( arg :: Interface ) = ... 
bar( arg :: Impl2 ) = ...

But this approach of explicitly redefining a new type can become verbose once the number of fields grows. Since a type seems to be just a label and a set of fields, it seemed fine to create new types from named tuples.

Julia isn’t huge(*) on using super-types (or anything else) as interfaces to say what methods something has available, in contrast to static ahead of time compiled languages with static types, like Java or Haskell.
Because being a JITed language type-checking in advance isn’t possible, except as a optional “linting” step (JET.jl does do that); and being dynamic it isn’t certain to be covering all cases (so value decreased).

Mostly types are used for dispatch.
And everything else can be left to duck-typing.
So like unless you had a second Interface2 in your example, that defined x or y or foo differently, then those type constraints are not need.
and thus making Impl1 and Impl2 subtype Interface is not needed.
Similarly, having anon types implement the Interface is not needed.

(* It’s not a never, e.g. AbstractArray is a good example. which provided many methods. Particularly good as it has fast dispatches that would otherwise fallback to methods that would work on ducktyped generic iterators)

1 Like

Adding the formal type in the function signature helps documenting I think. Otherwise good luck to your colleague and IDE on finding what that parameter is or can do in a large codebase.

Doc Strings.


In my experience,
adding type constraints soley for purposes of documentation is an antipattern in julia.
It makes the code less flexible.
And gives nothing that is not better provided in a docstring.
Which can include the most commonly used type, and further commentry.

Sometimes MethodErrors earlier can be more helpful than later.
But I still don’t think it is worth it most of the time

3 Likes

I always find it annoying to read the lengthy python type annotation, also particularly because they do absolutely nothing in terms of dispatching and performance etc. And they cause very hard to debug CI failure because setting the whole thing up locally is a pain too.

So I would absolutely love Julia to NOT adopt “annotate just because I want” approach since it also limits composability when people overly specify types.

2 Likes

I am yet not sure why creating an instance of an interface would be useful.

You can have functions which restrict their parameters to any concrete types below some abstract type. Your code shows how to do it. These methods can even assume the argument object has a field with some name like x or y and operate over them. So I am not entirely sure what an instance of an interface accomplishes.

New types are also a constant global identifier, that never goes out from the memory, and is used by Julia to dispatch methods.