some more thoughts about the type system - Injections

176 views
Skip to first unread message

Simon Danisch

unread,
Mar 14, 2014, 2:00:52 PM3/14/14
to juli...@googlegroups.com

Hi,
I have some more thoughts about the type system, but didn't want to put it all in one mail.

The way you declare similarities in the type system, makes me a little bit nervous.
If a Type has fields or properties in common, you define an abstract type and make everything inherit from it.
This is nice, but the compiler/programmer can’t check without additional work, if the actual type really has the correct fields or properties.
If you do something like Type injection, things would be a lot more concise.
Example:

abstract WithShape

type Shape <: WithShape
  boundingBox
end

type Polygon <: WithShape
  @inject Shape
  points::Array{Vector, 1}
end
type Circle <: WithShape
  @inject Shape
  r::Int
  middle::Vector
end

function drawBackground(x::WithShape)
  ….
end

The macro inject easy to implement(if you want I can post the code), but the declaration of the abstract WithShape and the <: WithShape should be generated automatically.
Also, this is the point where multiple inheritance becomes very meaningful, as you might want to inject more than one type (I understood from the mailinglist, that this is in development, but hard to implement).

I’m not sure if I understand you right in the Docs for the Type system, but it seems that the functionality I describe is not wanted for a good reason.
Well, I think this could be some way of having an inheritance like functionality.
I think, that the function drawbackground becomes a lot more transparent to the programmer, as he can look up the type WithShape and find out the fields it has.
Without this, one would have to go through all subtypes of WithShape to see what they have in common.
Also someone who just inherits from WithShape, without paying attention, could break the function drawBackground.
All in all, the function drawBackground couldn’t guarantee, that it can work with all subtypes of WithShape, which makes it harder to see, what the function actually does.

This, plus injections at runtime would bring Julia closer to Scala in a (good?) way!

Is there any chance, that this will be implemented?
Or am I missing good reasons, why this is unwanted behavior?

Kind regards,
Simon

Ivar Nesje

unread,
Mar 14, 2014, 2:23:18 PM3/14/14
to juli...@googlegroups.com
There was some discussion about allowing abstract types to specify what fields all subtypes will have in #4935.

Simon Danisch

unread,
Mar 14, 2014, 2:27:31 PM3/14/14
to juli...@googlegroups.com
Awesome! This must have slipped my search ;)

Mauro

unread,
Mar 14, 2014, 4:01:02 PM3/14/14
to juli...@googlegroups.com
Interest in that issue has slowed down somewhat. I think Julia's
approach to "inheritance" is not through what fields types have but
trough what functionality methods defined for them have:

"If it looks like a duck, swims like a duck, and quacks like a duck,
then it probably is a duck."

In this thread (which I referenced in your other post as well), Jameson
posted a link to a good article about this:
https://groups.google.com/d/msg/julia-dev/v8B1tI_NB5E/XXp4uSlPadEJ


On Fri, 2014-03-14 at 18:27, sdan...@gmail.com wrote:
> Awesome! This must have slipped my search ;)
>
> Am Freitag, 14. März 2014 19:23:18 UTC+1 schrieb Ivar Nesje:
>>
>> There was some discussion about allowing abstract types to specify what
>> fields all subtypes will have in #4935<https://github.com/JuliaLang/julia/issues/4935>
>> .

Simon Danisch

unread,
Mar 18, 2014, 11:51:42 AM3/18/14
to juli...@googlegroups.com

Okay I guess this has been sufficiently discussed.

Just one last question:
What do you think about this “design pattern”:

function render(a::WithOpenGLBuffer)
   ...render buffer
end
function render(a::Shape)
   buffer = createOpenGLBufferFromShape(a)
   @inject a <-- Buffer
   render(a)
end

function modify(a::Shape)
   @remove a OpenGLBuffer
   ...do modifications
end

I’m very tempted to use this.
I think this a general pattern for the case, where you need to calculate some kind of representation, that gets invalidated if you do any modification.
With the representation it gets treated differently, as you can do something ( like displaying) directly without any precalculations.

Alternatively one would need to carry around an additional field, that doesn’t really has to do with the type itself, which then needs to be checked for initialization ( which doesn’t even work when you have immutable types)

I don’t really trust my judgement here, so what do you think?
Is this a good use case for injections?

Reply all
Reply to author
Forward
0 new messages