"concepts" as Array abstractions for multiple simultaneous conceptual paradigms?

question
proposal

#1

There’s a language feature that I have always wanted and am wondering if julia has anything close. Just wanted to check before attempting to implement anything…

My idea is based on the fact that one way of accessing and viewing data is often times not enough. It would be great to be able to have multiple conceptual schematics of the same data and be able to access that data in the most convenient way. As an example, I found this code in the wild:

type Vector
	x::Real
	y::Real
	z::Real
end

Vector() = Vector(0, 0, 0)

function toList(a::Vector)
	return [a.x, a.y, a.z]
end

function toVec(a::Array)
	return Vector(a[1], a[2], a[3])
end

...

As you can see the author of this code really wants to be able to simultaneously treat this data as both an array and a structure (type). I’ve been there myself! I would guess that the best form for the computer is an array whereas the best conceptual representation for a human is a named data structure. I’m assuming that the rest of the program --which appears to use these functions regularly-- would likely incur execution speed penalties by constantly restructuring the data. Would that be correct? …if so, then this is not only a style issue …but one of efficiency as well.

There’s no end to the posible applications for the ability to easily and cleanly designate abstractions of subsets of data. For example, in working with images one often has to work with subsets of data such as row, col, pixel, red, green, blue… even a sliding Window (to which a kernel is applied for convolution, etc). Some of these abstractions are very different from others.

  • In the case of color channels, they’re similar to the case above where the elements of an array dimension are named.
  • With a “row” of pixels, the situation is slightly different. You would be naming sets/offsets of elements.
  • A sliding Window is still more complex…

I know that a lot of great work has been done in julia to simplify and make things easier but is there anything like what I’m looking for? Let’s say something like this:

julia> concept V 
           [ a  b  c ]::Int64
       end

julia> typeof(V)
  Concept: V::Array{Int64,3};
  a, b, c = V[1], V[2], V[3]          # or something better ;)

julia> v = V(1,2,3) 
  1×3 ConceptualArray{Int64,3}:
  1  2  3

julia> v.b
  2

julia> v[2]
  2

julia> v .^ 2
  1×3 ConceptualArray{Int64,3}:
  1  4  9

The word abstract is already being used so I’ll use “concept”.

The objective here is to have a very clean and simple way of accessing data from within different conceptual frameworks depending on needs and thereby simplify otherwise complex code. I will give/invent a more complex example:

julia> concept  Pixel, Color         # pixel same as color when ignoring image's context
          [ red  green  blue  alpha ]::UInt8
          RGB, RGBA, HSV  # Associated "concepts" help define the way data is accessed 
       end

julia> concept  Row # row must access the width variable from it's parent 
            [ Offset() : Next() ]::Pixel   # Asume internally defined: "Offset() = index*width,  Next() = Offset()+width"
            Pixel, Color
        end

julia> concept  Col;     ... ;     end
julia> concept  Layer;     ... ;     end
julia> concept  Window;     ... ;     end
julia> concept  Kernel;     ... ;     end

julia> concept  Image
                 [ width, height ]::Pixel          # let's say pixel is the base unit
                Pixel, Color, Row, Col, Layer, Window 
           image() = new(width, height)  # hmm... probably not right!
        end

julia> pic = Image( 150, 150 )   # Let's create an image!
150×150 ConceptualArray{Pixel,2}:  # something similar to this...

julia> pic[10,10].Pixel
1x4 ConceptualArray{Int8,1}:
 ...   # probably = "[0 0 0 0]" since we didn't set color data; let's set them...

julia> pic[10,10].Pixel = RGB[220 20 60]  # let's say this sets it to crimson

julia> pic[10,10].Pixel
1x4 ConceptualArray{Int8,1}:
220  20  60

I hope the idea is clear enough. I haven’t really put enough thought into implementation yet but I am looking forward to getting some feedback on this.

How much does this idea overlap with the NamedArrays package? …I think it’s different. Is this realistic? Would anyone else like something like this? …or am I missing something and it already exists? Would this be compatible with the julian way of thinking? How would you further simplify and polish this -thrown together- set of examples??? Could this be extended beyond arrays?


#2

Further thoughts…

You may be able to classify this as Destructuring …but in a more julian way!

How is this different from unions? For one thing, the data never changes type.
An Image or pixel or whatever, continues to be just that. This is an approach to
establishing multiple ways to access the data based on the different perspectives
that arise from processing data under differing circumstances.

Also, this is very different from struct and type for several reasons.

A related set of concepts describe the relationship between abstractions of
the data. This would make it possible to have built in functionality that would
otherwise have to be specified by the developer. As an example, if a “Row” is
defined in an image as a representation of the x-axis, and Row is part of the
concept “Image”, Row can use Image’s width to automatically define an increment
and alignment scheme.

If we take that one step further, Row and Col really should be predefined concepts
because they’re obvious and would be used often in many different contexts. For example,
besides being a part of Image they could also be concepts of Table and Kernel…

Another way that this is different from struct ad type, is that, whereas struct
and type describe how to build an object as a collection of parts, concept, in effect,
describes how the data may be sliced, so to speak.


#3

For your first example, you might want to look at FieldVector in StaticArrays.

More generally, your idea sounds somewhat like “Traits.” Traits have been discussed quite a bit here in Discourse and in Julia issues.


#4

Thank you @tshort! First, I have to warn of my lack of knowledge of traits. I do not use any language that uses traits.

After reading your suggestion (that “concepts” might be something akin to traits) I had to take some time to look into “traits” further and try to look at the similarities and differences. Actually, in my mind they were totally different but I do see some similarities. However, as I looked at examples of trait usage in different languages I saw that most of the examples show a usage somewhat similar to how we might use the type system in julia. Specifically, strings are used to classify (or generalize the properties of things) and therefore help to determine how information is processed. In other words the principal function of traits seems to be for marking/identifying aspects that objects have in common. Is my understanding correct?

Here is a random example: https://rustbyexample.com/trait.html

If my understanding is correct… and that is a big IF, then the purpose of my code examples above would be different in that it is principally meant to describe metrics of the abstract or conceptual components of data along with associated names and other things to facilitate access to that data. In other words my idea is more like a map than a flag.

Are the differences I am describing real or do I still need to greatly refine my understanding of traits? Thanks for your thoughts!