This blog entry is in english. Yet english is not my native language (italian is), so bear some indulgence with typos or grammatical mistakes. Also, I have been told that I write complex things - whether this is good or bad I don't know: but so, if you are unfamiliar with complex prose you may see grammatical errors not only where there could be some, but also where just a prose you're not acquainted with is. Native speakers with an A+ grade in english say my english, obviously not perfect, imports no major issues. Lend a deaf ear to the errors, vocally disagree with my thesis if you want, but enjoy the style all the while.
None of these texts should be considered as a lesson in the scientific topic it deals with. These texts represent only the personal effort of an individual with intellectual curiosity but no professional knowledge in the field and no degree in Physics or related subjects.
However, being so, these essays can still be of some interest for students: because they may occasionally reveal useful insights, sharing with students their very same naivety and the same necessity to cope with and solve the very same intellectual challenges they may meet.
Also, keep in mind that I like intellectual experiments. So, together with useful insights, you may find plain errors, and speculations that, arguably, you wouldn't find on any academic product.
«Don't you remember that love, like medicine, is only the art of encouraging nature? You see how I can fight you with your own weapons. (...)
Once one becomes interested in the game, there is no knowing where one will stop. (...)
But tolerance I see as no more than dangerous frailty when it brings us to look with equal favour upon virtue and vice. (...)
You were the topic of our conversation, to which I contributed not the good opinions I have of you, but the good opinions I don't have of you (...)
I have never believed in these sweeping and irresistible passions, which seem to have been agreed upon as a convenient general excuse for our misdemeanours (...) as if a thief could be justified by a passion for gold, or a murderer by a thirst for revenge. (...)
But this chimerical perfections exist only in their imaginations. Out of their heated fancies they produce charms and virtues, with which they adorn the man of their choice according to taste, decking out what is often a very inferior dummy in the vestments of a god. (...)
you might teach your pupils not to blush, not to be disconcerted at the slightest pleasantry; you might teach them not to deny so vehemently, on behalf of one woman, what they would so feebly disclaim on behalf on another; you might teach them, too, to hear a mistress complimented without feeling obliged to congratulate her upon it; and, if you allow them to look at you in your company, let them at least learn beforehand how to disguise that proprietary look which is so easily recognized, and which they so stupidly confuse with an expression of love.»
Choderlos De Laclos, Les Liaisons Dangereuses - sort of data structures of an everlasting human tragi-comedy: and who's the villain, those who pretend or those who exploit?HIC INCLVSVS VITAM PERDITWhat a
dream has to do with
digital data structures may rightfully appear less than obvious to you, yet you're to find many persons who believe that the other way round would be quite obvious.
You can then find startling statements as the following:
«Self-knowledge, including the ability of using a mirror, is no more mysterious than any other topic in perception and memory. If I have a mental database for people, what's to prevent it from containing an entry for (referencing) myself?»(Steven Pinker, How The Mind Works)So, it is just "no more mysterious than" that, and even no more than "perception and memory": my vivid congratulations, while we all feel very stupid.
Yet, using a mirror is not the same as implying the predicament I can also recognize myself as my-self just because I'm facing it: if you put a mirror in front of a computer, it doesn't develop vanity, as well as a dog who none the less has eyes as a perceiving apparatus is completely uninterested at his own image - and if your own dog is particularly smart and barks at a blinking image in a glass, this only proves the contrary, namely that the mere presence of a self reference triggers nothing if a mysterious dash of inner intelligence is not there to "
understand" the self reference as such.
And for how long you may be pleased to make a database self-referencing by including in it references to itself, it will just go on being as self unaware as it was from the beginning: it is still the barren database it can't but be forever.
Galilean experimental science was meant exactly to prevent science from getting deceived by this type of
self-persuasions, these arbitrary theorems: and whereas Galilean science cannot support us, like it was when for instance the Relativity Theory was developed while lacking even hopes of that experimental support which occurred only at a second time, we're doubly bound either to make a profound effort which abhors self evident mistakes (it is still Descartes who teaches us that when we're on the ground of pure theory because experiments are not possible, our golden rule must be: doubt
exactly of your-
self by default) or we must trust the primeval visions which twinkle within us, as dreams and archetypes are: because if they do, there is stored an immemorial wisdom stratified in them; as such, every true scientist (I'm confident no one would ever take me as one of them) should treasure visions rather than rebuff them: only a god (a myth carved by a demiurge, call it nature or Apollo, upon our blank slate) or the moon (a refined nocturnal thinking effort, as we'll see) may lead you out of the self-delusional, self-referencing maze you got trapped in and which deludes you exactly by virtue of auto references: a vision is subjective inasmuch as it is dreamt but it is universal inasmuch as it draws from an immemorial storehouse of ancient knowledge: and a knowledge that resides in eternity cannot be eternally wrong.
So what startles with these statements is not just the fact they propose the most unproved allegations seasoning them with ancillary observations meant to stress a spontaneity with them which has never been there since inception and which is so far from being undisputed that it should have suggested expressions of extreme
caution rather than expressions of extreme self-
confidence; what truly startles with them is that:
- Any writer in that line is apparently persuaded that the last steps mankind has undertaken in scientific or technical progress is also the definitive, the last and explain-it-all one: and as such suitable to be employed to ravel out all the other unresolved issues - it never comes to their mind we're just in a flux of time whereas what today may seem so obvious like the sun revolving around the earth could just be the most sensible of our self deceptions: and a mistake applied to ignorance only produces ideology, for by what other means could you uphold it? "A strong faith is only proof of its own strength" (Friedrich Nietzsche).
- These positions fail to perceive that what we have at hand is a representational metaphor whose purpose is not to describe a reality as it is, but to emulate it with a scheme that can have a meaning to our senses: the graphical representation of a mathematical formula describing the movements of a galaxy through analytical geometry is not what the trail of that galaxy is: it is just one convenient way we can represent it to ourselves in order to grab at least a few features of it.
- What we draw from reality in order to trace our own sensorial representations, is not what should then be ascribed back to reality, triggering a tautology: but it is the other way round, it is nature and reality who is going to teach us, not us who are teaching to nature what it still withholds from our inquiries.
Once you array yourself to neglect Copernicus and snub Galileo Galilei, to brush aside Descartes and to be by necessity below Einstein, and yet all the time you also claim you have nothing to do with magi (but wasn't Isaac Newton called "The Last Magician"? He wrote
more about
alchemy than about
mathematics, a thing this that many are arguably
unaware of) and you ignore nearly everything about arts symbols psychology and anthropology, what are you left with when none the less you still exact for yourself and appoint yourself with a role-name that can no longer suit you, namely that of scientific, objective thinker? The objectivity or the positivism that cannot work also
against itself, will never get out of the tangle, this is what the methodological doubting sponsored by Descartes meant.
Thus, talking of data structure, we'd learn lessons from nature and never attempt to allege that nature isn't but a replication of our own
current, maybe pitiable, representations.
So, what is there more powerful in order to represent a data structure, namely a set of cryptograms meant to hold meanings and information, than a
symbol? Yet, no digital structure thus far knows how to implement a symbolic container of data.
We should start considering the capability to symbolize as an
extremely dense and appropriate way to store and convey meaning/
information, and try to understand it in order to emulate it, rather than declaring that a conscience isn't but a database with one entry which points to itself - and then writing whole books entirely spinning around this regardless of the perfunctory complaints by which we vehemently try to claim we have been misunderstood and deny that we meant exactly what we kept meaning for hundreds of pages: «
Parturiunt Montes Sed Nascetur Ridiculus Mus» (Horatio), "The mountains begot but they brought forth a preposterous mouse".
As also Douglas Hofstadter suggests in Goedel Escher Bach
«There may be as many as 200,000 separate entry ports to a neuron (...) Before the ions reach the end, however, they may encounter a bifurcation or several (bifurcations). In such cases the single output pulse splits up as it moves down the bifurcating axon, and by the time it has reached the end, "it" has become "they" - and they may reach their destinations at separate times (...)
(...) entire successions of events recalled from some earlier time of life, such as a childhood birthday party. The set of locations which could trigger such specific (recollection) was extremely small - basically centered upon a single neuron. (...)
Now if it is granted that the notion of TAKING A TRIP is fair counterpart to the notion of having a THOUGHT, then the following difficult issue comes up: virtually any ROUTE leading from one city to a second, then to a third, and so on, can be imagined, as long as one remembers that some intervening cities are also passed through. This would correspond to the activation of an arbitrary sequence of symbols, one after another, making allowance for some extra symbols - which lie en route. (...)
However, the TRIP among these symbols need not be imminent: it may simply be one of billions of potential trips. (...) There are not only an infinite number of PATHWAYS in a brain, but also an infinite number of symbols. New concepts can always be formed from old ones, and one could argue that the symbols which represent such new concepts are merely dormant symbols in each individual, waiting to be awakened. They may never get awakened in the person's lifetime, but it could be claimed that these symbols are nonetheless always there, just waiting for the right circumstances to trigger their SYNTHESIS.»Thence my dream, which I dreamt a few weeks before starting this website. As most of the dreams which carry some importance, it is laconic:
"Sunny seaside. The waters before the shore suddenly start to swollen as if a vast leviathan was about to surface, and a trial of dented intumescent water riddles the sea, as a backbone displaying liquid vertebrae. The stream speeds headlong as the apparent bulk which must be underwater gets closer, and eventually an immense bull emerges from the parting waves; the size of this bull is beyond imagination, about as high as a three or four floors building and as wide as a five window building, huge, muscular and snorting though not posed to destroy.
Sort of a voice explains: 'This Is The Bull Of The Sun'." - Enditem.We'll come back to this dream, because this dream also reveals a lot about digital data structures. And I mean it: because of backbones and minotaurs in the labyrinths and water, which is a fixed volume without fixed shape. A wealth of Information about Data Structures all condensed in one symbol and connected by it to each other: can you guess a glimpse now?
Let me address first profanes, and then satisfy more experienced programmers: for thought is for everybody, not for elites.
The simplest type of data structures we deal with in scripting languages are called
arrays and
associative arrays: I even remember that in one occasion Danny Goodman wrote that he started a seminar on Javascript by dealing with arrays as first topic, and many thought it was a daring move for normally everyone starts with more basic things.
Being Mr. Goodman one of the very best, he was not wrong tackling arrays first: they are pivotal.
The most traditional digital way to gather as a family a set of items that share some common property or which must be meant as pertaining to one same set of currently inspected elements, is to arrange them in a so called
Array: an Array is a set of values indexed by a progressive numerical key handle (starting with zero, not with 1) which is put in between square brackets:
myFamily=new Array();
myFamily(0)="me"
myFamily(1)="Daddy"
myFamily(2)="Mommy"
myFamily(3)="Brother"
etc...
Alternatively, the keys (the numbers in between the square brackets) can be
other data type than
numbers: if even just one data type
different from a number is a key of the structure, the array is no longer called just an array but either
associative array or an
object (consider the terms practical synonymous): the only real difference between numerical and associative arrays, is that when you want to scan with a cycle an all numerically keyed array you use a type of loop different than the type of loops meant to scan associative arrays: in Javascript you scan arrays with a so called for loop and associative arrays with a so called for in loop (you can scan an array with a for-in too, but not vice-versa: you cannot scan an associative array with just a for loop). The same applies for instance to languages as PHP: you scan arrays with for loops and associative arrays with foreach loops.
Now, notice this (and we're getting to the creative part): each item arrayed into an array can be conceived like nothing else than an element which besides its value carries information about what the
previous element it is connected with is, and what its
next element it is connected with is, thus describing a fixed path in the way you can navigate the structure.
An array of one entry could be conceived like something implicitly stating the following:
self=self;
its previous=self;
its next=self;
Is that convincing? it should be, for the entry is
lonely, thus it can and must always refer only to the self (and of course, this doesn't make the item self conscious!).
When you add an element to an array, what you're doing is to change these indications about the proper way to travel this structure accordingly to some
specific constraint: in fact a new entry imposes to the previously lonely one to rearrange its previous/next fields as follows:
self=self;
previous=self;
next=self 1;
Whereas the subsequent new entry may be envisioned as implicitly declaring what follows:
self=self;
previous=self-1;
next=self;
Whether profane or experienced you may have now noticed something that arguably you
never focused your attention on before: there is a
constraint in action and this constraint is an algorithmic one which
prescribes to the data structure to be such inasmuch as it declares a way it can be travelled which gets entirely determined by the algorithm imposing the specificity of a constraint upon what is previous and what is next for each instance of the collection.
The family nature of the set is thus
entirely determined and specified by the nature of the type of
constraint they share regarding the way they can be
traversed: it is
not the properties of the nodes what makes of this simple grouping (an array) a family, but they way they can be
visited that makes an array recognizable as such.
Thus what is important for you to understand is this:
- You can gather data type by an algorithm, for instance if you want to colligate in a set all those items which are, say, string data type.
But this does not define the data structure nature in the least, it only defines what a previous algorithm in a previous task collected: and this task is not what defines the data structure type, but is only a proceeding that still imported nothing about the type of data structure these collected items were about to be arranged into: it merely reaped them, but defined nothing on their future definitive structure.
The fact an algorithm may first reap data types and then arrange them in a structure within the very same body of the very same algorithm digital definition (the codex, that is) should not induce you into error: the algorithm just conveniently subsumes two different conceptual processes in one set of digital codex: yet they are still conceptually differentiated in the highest degree: the one which discriminates the nodes (elements) to be arranged together, and the latter process which properly defines its data structure namely the shape of this arrangement by defining the constraint on their previous/next pairs. The latter is a different process, and is a shape entirely defined by the constrained way it declares it can be navigated.
- Once you have arranged your items in a data structure, this very same data structure can be travelled in many different ways: the fact the implicitly defined previous and next fields of one instance are, in a standard array, under the simplest constraint which predicates next= 1, previous=-1 should not conceal from your mental eyes the fact that this is only one among the many possible different traversing constraints that can be implemented, thus consolidating our persuasion: data structures are entirely defined by the way a subsequent algorithmic constraint dictates how they must be journeyed. That and that alone makes data structures defined.
We could even state that if the algorithm that defines the
navigational constraint is known, then by merely knowing either the next or the previous implicit field of an item we may foresee all the rest about
all the other items or about the next/previous fields collocation a new item to be inserted must respond to. This is a somewhat powerful consideration: conceiving a data structure as an algorithmic
constraint declaring the only way the structure can be
traversed, we imply that from the mere assignment of one field we can guess all the rest whenever it may be needed.
How are these constraints to be applied? Can they be assigned arbitrarily?
Theoretically yes: as a god in the Garden of Eden you can give names to things and define the nature of a constraint even arbitrarily. Yet, the nature of this constraints is obviously to be chosen in a way that is functional to what you want to get from the structure: it is in this fashion that the nature of the nodes (the items' data type, that is) can have a
feedback on the way the
constraint is chosen, and yet what still defines the data structure more significantly, are not the data type of its nodes, but the way they are constrained in their paths: it would be more
proper to deduce the nature of the nodes by the applied constraint than, by the nature of the nodes, trying to deduce the nature of the constraint: from the latter you can't deduce safely the type of constraint, but by the type of constraint you could even make sensible guesswork on the nature of the nodes data types.
A general set of nodes as, say,
ABC is always the same set, for however you look at it, it is always the same set of the very same items: it doesn't gather any
additional identity by merely knowing that ABC is made of A and B and C: but it
does gathers a lot of meaning if you apply a constraint x to it which says: A comes first then B then C; or a constraint y that says B comes first, then C then A: BCA, and you can't travel the structure otherways.
If no constraint is in place ABC is just as good as CBA or as DFZ. Its data
type nature provides it with an identity which is a miserable and a very poor one, you see.
Thus, an array is just a
conventional representation of a set whose
identity is characterized entirely by the default
constraint which imposes to it a
linear subsequent
path. An associative array is a set whose identity is under a constraint which says that from an anonymous stellar center (don't think anonymous is an immaterial word: you have in Javascript functions that are assigned to events by default defined as
anonymous by scripting catechism) you can instantaneously reach all the nodes on its branches: it is a radiant path.
You'd thus start considering data structures as pathways, as invisible connections describing paths.
Even if you consider algorithms that inspect data types and derive a path sifting among certain data types, what matters in the map which ensues as a result of the scanning and which is drawn to tell about the recurrences of certain data types against other data types, is the type of
path which is either revealed or imposed upon them, being thus the nodes nothing but pretexts to reveal the
rhythm of a
path which is the
true, authentic protagonist of the story.
What matters is the undulated nature of the regularity in the wavelength, not which nodes the backwash of the wave breaks against.
Data Structures are entirely defined by traversing constraints imposed by an
implicit algorithm: only algorithms make them.
As such, all data isn't but
raw data randomly heaped: data nodes are scattered in sort of an empty vacuum where they are of no real meaning unless an algorithm which connects them provides them with a meaning which is thoroughly and exclusively and truly given by the reciprocal
connections charged upon them.
Scattered nodes can be opportunistically confined within an object boundary whose unique purpose is to isolate them from an undifferentiated whole, but after this action has been performed nothing has been achieved but assembling a set of scattered data which is not less scattered just because now they are all of one data type.
In a labyrinth what matters are not the walls, but the paths.
Like a biological
RNA is
dispatched to determine the way a
DNA instruction has to be implemented in order to
array a protein (a protein is
indeed data structure, for a mere collection of atoms or molecules without a specified path has no remarkable property: it is the
stereometry of the shape what makes a molecular property active in one direction or in another), likewise a linked list is a map meant to store the paths an array has to be arranged after, without actually rearranging the
actual array.
Moving the
physical items of an array in order to signify that element A must now go after element, say, G, is more expensive than merely arranging a map of the array meant to collect the next/previous couples of each entry, thus achieving the following: instead than moving the actual A element after the G element, you flag in the map that now the
previous field of A must point to G. It is as if you have a car and instead of moving it to parking lot
A into parking lot
G you draw a map saying: this car must now be considered
as if it were in parking lot G. You then
consult the map to verify what connection constraint the array has.
Such a RNA like
map is called a
linked list, and as you may guess there can be even more maps applied on the
same item: whenever a node of an array can be connected to
more than just one item (in fact if you can envision a previous/next set of fields, nothing would prevent you from envisioning a node which has
multiple connections namely
multiple such previous/next
pairs:
nodes become then
crossroads, quadrivium, junctions, forks. The fact then a third decisional algorithm can be employed to
choose which path to undertake among the manifold available ones, doesn't mean the paths are no longer there: they are! and they still define the data structure) or whenever although each node has only one pair of previous/next fields but such fields are arranged under less strict constraints (or less apparent ones: A connected to G and Z, G connected to S and V) we say we are dealing with a
graph.
Now, without typing but pseudo-codes, let's imagine how we could craft a function (algorithm) meant to
insert an item inside a linked list, and we'll make of it our little case study, trying to provide it with as much flexibility as necessary to make us able to implement not just a linked list but also a graph depending on what instructions we provide this function with.
I won't discuss here what a class is, but you arguably need a class to implement an encompassing codex able to gather all the functions needed to manage our data structures. So say:
function map(){
this.linkedList=new Array(); /*the actual objects
with the actual previous/next fields
will go here, as new Object or as
another class instances*/
} It is extremely convenient to initialize within this function two general arrays meant to store all the positions of the previous and next fields in all the items that will be arrayed in the linked list: this will guarantee that if you want to find what nodes are, say, connected in their next field to say element X, you can instantaneously retrieve them without scanning the linked list and inspecting the next or previous field of each item until you've found the required one:
function map(){
this.linkedList=new Array();
this.items=new Array(); /*see further on what it is for*/
this.previouses=new Array();
this.nexts=new Array();
this.length=0;
} Every time you include or subtract an element, from the list of the mapped items you must be sure you update these this.previouses/this.nexts fields too and the this.length number too (which obviously keeps track of the length, amount, of the currently linked items) and you add an entry to the this.items field too. Each of the previouses/nexts fields is an associative array whose index will be an item that performs either as previous or as a next and whose values will be a numerically indexed array whose each entry points an item whose either previous or next field connects the item that works as the key: instance:
this.previouses(this.item18)=(this.item19, this.itemX ...);
That means that in this casual small example there are two items whose "previous" field points to item18 in
this map instance: the item19 and the itemX, and whatever subsequent list of items (optional). More correctly:
this.previouses( this.items(18) )=(this.items(19), this.items(X) ...);
The reason I use the new Array() constructor and not the new Object() one is that an array is more suitable to be subsequently stored in a database: it is in fact easily imagined that these maps won't reside
permanently on the memory of the computer (imagine a power failure: are all of your maps going to be lost forever?) and thus should be suitable to be retrieved any time by a database in case they need to be recomposed once again; in fact we have built in methods in server side languages, such as PHP, that can conveniently pack array data but not so conveniently data which has not been
initialized as an
array (instance, see the PHP method named serialize).
It is this very same reason that suggested to me to store also a
this.items array meant to collect the items currently stored in the linked list, for once you have stored in a database the items and the previouses and the nexts, you have
all the necessary data to unfurl and reproduce an instance of this map. True, this would require sort of an interface, namely a set of functions that on demand draw from the database,
unserialize, and then rearrange the map, but I won't discuss this interface here, it will be enough that I am highlighting what truly matters leaving the minor or sideways details of the implementation to the programmer.
Once defined the general outline of our map class, let's see how its insertion method could be implemented so that it will be as flexible as possible.
The insertion method has to assess the position of a new item by assigning its previous and next properties. If upon calling this method in order to insert, and no arguments concerning the assignment of previous and next for the about to be inserted new item are passed, there are at least three options we can think of:
previous=last in line
next=floor edge
This is the same as pushing an element to the stack of items: LIFO, last in first out.
It is then necessary that this operation, whose meaning is to add an element to the last one in the linked list, also updates the next field of the by now penultimate item so that it now points to the previous field of the newly added element and no longer to the floor edge.
previous=ceiling edge
next=first in line
This is the same as unshifting an element to the queue of items: FIFO, first in first out.
It is then necessary that this operation, whose meaning is to add an element to the first one in the linked list, also updates the previous field of the by now second item so that it now points to the next field of the newly added element and no longer to the ceiling edge.
previous=next of x
next= previous of y
This last operation truly inserts an element in a section which is not an edge.
It is than necessary that this operation also updates the next field of the antecedent item and the previous field of the subsequent item to fully reflect the new situation , namely the former must point to the previous field of the newly added item, and the latter must point to the next field of the newly added item.
Yet, this is nothing more but a default behaviour. The newly added item could actually either inherit its previous/next pair by one or both of the items that are abreast of it, or could just draw this values for the previous/next pair from other elements thus defining either an entirely different algorithmic constraint or a graph. You thus have the following options with the parameters you pass when invoking such an insertion method:
- First argument, the object that must be inserted (the new item itself, that is). This is necessary and obvious.
- An argument that flags whether it must be implemented a default, built-in behaviour, lacking other arguments.
This default behaviour can be the one of a mere array linear and sequential constraint as outlined above, or could even be another function tailored by yourself meant to call in a third external algorithm representing the pattern to apply.
If we want such default being represented by a function crafted by the scripter, we should then also grant the passage of arguments to this function too when invoking it; this tantamount to this, whether you fully appreciate it or not: you have to allow for an argument in your insertion method that is potentially meant to be argument itself meant for the third function that could be called in. I suggest it to be an array, because if this passed function would require more than one argument it would be unpractical to populate also your insertion method with a multiplicity of parameters meant for this passed function: so just pass an array and store in it all the possibly multiple arguments that the passed function might need - a trick familiar to those who work with a language called PERL where all functions accept only one and one argument alone, so that every necessity of more arguments is accomplished by passing as the only accepted argument an array and then decomposing such array within the function itself thus regaining a variety of arguments.
- Optional argument for possible function passed as second argument: see above.
- Management of field previous
- Inherit form the antecedent item's next field.
- Arbitrary assignment of it.
- Management of field next
- Inherit form the subsequent item's previous field.
- Arbitrary assignment of it.
- Thus out method "signature" might look like:
this.insert=function(
object,
defaultOrFunction,
OptionalFunctionArguments,
managePrevious,
manageNext
);
Our insertion function should be able to accept as object argument (its first argument, that is) both an object, or a pointer to it whereas the language explicitly allows for pointers, or even a mere
number in case for some reason what you want to pass to it is not an object but the index of an array which stores such object: remember, we're talking of drafting a method that implements path constraints as flexible as we can imagine it.
Thus you have to remember that if you want to bypass an argument (that is, you desire to skip some argument/s and yet you still mean to pass one of the arguments which are declared after the ones you want to bypass: since there is a
prescribed order in the way the arguments are defined in the function signature, you cannot skip a few to reach a further one without declaring also the skipped ones: you have to declare all the intermediate ones anyway) I don't suggest to you to declare the intermediate ones as zero (a typical way to mean: even if I passed this argument, it should be considered as nigh: I just meant to stretch and reach the next ones in the signature): in fact numbers in the inner working of a flexible function could even be numerical key indexes of an array, and zero as such is a legitimate potential numerical index. This could be the good occasion to use the keyword object named null when bypassing, thus verifying arguments by:
if(argumentName!=null)
. . .
Also, remember that in JavaScript index passed from an object may be numbers to human eyes and yet they could be internally represented as strings: this applies to JavaScript objects and not to arrays which are not associative - for more on this slight annoyance see the essay: Is it a number or a string?
It is also necessary to consider whether
multiple connections (graphs) to one same previous or next field of an item are allowed: if they are
not, remember to make sure that after you have made a new item point to either a previous or next field of another item, whatever other
concurrent item whose previous or next field was pointing to it must
cease pointing to it and should be updated to mirror the new situation;
these are cases where the class arrays storing the this.previouses and this.nexts fields prove themselves being quite useful features, which thus I didn't suggest to include just by chance.
Remember also that since nothing prevents you from imagining a data structure where each item is allowed to have
multiple pairs of the previous/next fields (that is, items stretching paths to more than just one previous and one next node), the best way to implement this characteristic wouldn't be to complexify your class by adding an indefinite amount of previous/next pairs for each item instance, but to
initialize more instances of class map for
how many maps you want to define upon the
same data structure: the collection of these maps, then, may be conveniently arrayed in a globally defined array, which so would provide the full set of maps defining the given data structure, as a file of maps you can unthread from its array hinge upon request.
Eventually, always make sure you updated within the map the other properties such as
this.length.
In order then to perform a deletion (insertion and deletion are the truly only necessary operations) you just have to reshape all the previous and next fields pointing to the item which is to be deleted.
These guidelines can be precious if you're to implement a method that arranges data structures as linked lists but as linked lists which actually aren't but potentially infinite sets of previous/next pairs not necessarily following the traditional linked list path constraint: we could call this idea a
multi
leveled
multi-
constrained linked list approach, a
mulmuc I'd dare say.
Why was the bull of my dream qualified as the bull of the sun? And if that was the bull of the sun, how comes that the bull is the symbol of the astrological sign of the Taurus and yet the Taurus is dominated by the moon? We can solve this riddle in an amazingly convincing way.
The sun runs in the skies like my words flow on the paper, it charges in the skies revolving like my words ramble, it fecundates by making plants thrive like my words may be stimulating for your thoughts.
The sun approaches sunset and seems as if it were going to be swallowed by the waters of the sea, and drown: yet the next day the sun re-emerges from it; is it the earth or the sea that is going to submerge the sun? Both symbols have been used (labyrinths are often underground, also because it is impossible to make one underwater, which certainly would have been more appropriate as a symbol) but the sea is going to be considered more suitable an element than the earth to impersonate the one that imprisons the sun when it vanishes from the skies, because everyone knows that water and fire are mortal enemies engaged in mortal combat.
Thus the sun dives into the waters, and the ocean simmers with crimson riddles before the ferment of the fire fighting with the waters settles down.
Then the moon appears. Now, aren't a bull's horns like the horns of the moon? This is precisely what the ancient thought agreed upon.
Thence the fantasy: the moon riding the bull has dominated it by riding on his head, and has submerged it into the waters: until the next day the sun will charge again resurfacing from the depths. The Taurus thus is
both lunar and solar, because the moon dwelling on the forehead of the sun can guide and lead it. Orphic myths ensue. The bull of the Sun is the bull on whose head the moon rides.
In Cnossus (Island of Crete), the ancient city where the labyrinth of the minotaur was and where Theseus entered led by Arianna's thread, labyrinths were strictly envisioned as connected to the bull. The Bull is linked to the Labyrinth, because who can tell the paths taken by the sun when it goes underground and fights or perhaps makes love with the moon in order to exit successfully and triumphantly regain his footage out of that fateful snarl?
If you draw a set of concentric closed circles (or whatever other consistent shapes), they can be conceived like defensive, impracticable, insurmountable sets of walls segregating circular tunnels.
If now you inflict random cuts on these walls, you have automatically arranged a set of different possible journeys within these tunnels, and by the agency of this very simple act of cutting through you have implemented an actual labyrinth. If the hand which delivered these cuts imparted them after a plan (an algorithm can be conceived as the rhythmical implementation of a plan), the labyrinth can be a cunning one. But a shrewd labyrinth can only be a labyrinth where you want to be sure there is at least one valid path - or none at all.
Within these circles, if no deception is in place (but maybe this applies even if deceptions exist, if we consider only the
valid paths and dismiss the others as "irrelevant") you can spot a
constant rhythm of turns either
leftward or rightward of yourself (unless the maze is tridimensional, which would add upward and downward) that gradually seem to shift the character lost in the maze
now from one outward circle to a more internal one and
then again from one internal one to one more external, rhythmically jumping inwardly/outwardly by some sort of a
proportion based on the ratio of how much it previously jumped outwardly/inwardly and of how many circles are included in the whole labyrinth (imagine to superimpose on it a grid to pinpoint all the coordinates of its turns).
These basic units can then collapse into themselves in order to produce replications of themselves within themselves and thus disseminate a plurality of patterns of a pattern nested within the pattern: indeed, like a Johann Sebastian Bach's Fugue or Canon.
It also appears as if quantum jumps of an electron on its possible orbits might be somewhat hinted, as if this idea was already dwelling within our immemorial souls well before scientists came to find it an appropriate representation of a quantistic reality. Never dismiss a dream, if you like truth.
It is important now that you do concur or that you understand that what an algo-rithm is isn't but a digital code meant to express exactly a
rhythm, and for how much a labyrinth is
cyclic so much an algorithm is rhythmic. Algorithms, like numbers,
are labyrinthic paths
not only for the sake of an occasional suggestion.
Moreover, it is reported that in Cnossus and also in several Homeric descriptions an intricate dance full of windings was staged to represent the paths of a Labyrinth in order to celebrate Theseus adventure. This reveals once more the rhythmical nature of the labyrinth and also alludes to the fact that, probably, the best way to solve the enigma of a maze is to let the rhythm conquer you and to abandon yourself to it, because a maze is all rhythms.
In fact, if you take care of drawing a line which connects all the visited nodes within a vast matrix, you most certainly draw a net made out of one thread which strongly resembles (or at least evokes) Arianna's thread, which isn't but the traditional and most indispensable complement of every idea of labyrinth - so that the presence of the one can suggest the compresence of the other: it thus hails the presence of a labyrinthic path, and thus downright of a labyrinth, whereas we suspected being none. «HIC INCLVSVS VITAM PERDIT»: as movies like "The Others" or "The Sixth Sense" we can rightly wonder, while walls we didn't understand were there slowly materialize around us as they fade
on from apparent emptiness, whether we are dead or alive. Ever got that strange sensation?
Every turn you take in a labyrinth is somewhat fatal: you can't turn otherwise, at most you can go backward: and when a labyrinth presents you with crossroads (you have seen above the image of a labyrinth that had no crossroads but one fixed path) each choice you make may be as fatal as well. Choices are irreversible, unless of course the labyrinth is alive and could adapt itself, or you can pierce holes in its walls, or as Daedalus you can fly over it (this is why many labyrinths are underground, to seal the ceiling and prevent the eagle vision of it: for if you find difficult following a maze with a pencil once you're faced with its whole plant, imagine being
physically within it with
no planimetry). Or a living being can suddenly deduce the rhythm which regulates the labyrinth by a strike of genius, and then by this knowledge even skip the possible deceptions whenever a turn doesn't fit the guessed rhythm.
For the difference between being alive and being inanimate relies much more on the capacity of
changing the self than on
referring to the self:
«Recursive enumeration is a process in which new things emerge from old things by fixed rules. (...)
This kind of thought carried a little further suggests that suitably complicated recursive systems might be strong enough to break out of any predetermined patterns. And isn't this one defining properties of intelligence? Instead of just considering programs composed of procedures which can recursively call themselves, why not get really sophisticated, and invent programs that can modify themselves? (...) (...) (...)
The Oxford philosopher J. R. Lucas wrote: (...) "a conscious being can deal with Godelian questions in a way which a machine cannot, because a conscious being can both consider itself and its performance".
(Douglas Hofstadter, Goedel Escher Bach)»A labyrinth can be conveniently described by the mere textual description of the leftward and rightward turns a traveller within it has to take in order to go to its center from one of its gates.
Of course, left and right are always conceived as left and right of the traveller/observer considered in regard of the direction he/she is facing.
Thus if the direction of the face is given by an O and the lines are the arms:
left_ _O_ _right
right_ _ _ _left
O
left
O
right
right
O
left
A casual labyrinth map might the just seem like, assuming L means Turn Left and R Turn Right and the numbers could represent any of the following:
- the positions counting the amount of side openings the traveller surpasses/sees on both sides while journeying
- the positions counting the amount of side openings the traveller surpasses/sees on the side of the lastly referenced (undertaken) turn side (right or left) while journeying
- the steps he/she took (length considerations, that is)
- the amount of inner or outward circles that could be orthogonally counted as enclosed while performing a turn
- The amount of times the right or left turn must be performed (example: 5R= go on turning right as soon as you see a turn for as many as 5 times): this last is the one I will mean in the following map:
1
L
4R
7
L
5R
4
L
8R
6
L
5R
Now, would you contend this is also the potential representation of a data structure, of a matrix, as it could be represented not as a whole but by merely the algorithmic path which currently inspects it?
Once again, I assume this is the valid path, yet you could build a whole collections of paths for one single labyrinth including also the possible deceitful ones: and isn't this strictly correlated to the idea I suggested to you in a chapter above speaking of a "multileveled multi-constrained linked list approach"?
An additional observation on possible deceitful paths may be of some interest. In a labyrinth we should not consider false paths as just a curse. We'd rather meditate in order to understand what is the meaning of the trick, why it cheats and how, and if in this process of cheating can be argued a meaning: reading a cheat just as such is being cheated twice. You can consider the following passage by Douglas Hofstadter:
«in normal chess play certain types of situation (are dealt by) the master on a different level from the novice: his set of concepts is different (...) he really
does not see bad moves when he looks at a chess situation.»
Now, this passage merely meant, in Hofstadter's intention, that the master disregards the bad moves if I have not misunderstood it. Yet, it magnificently lends itself to signify another thing, namely that if you want to master a situation you must never think of a situation as a bad situation or of its outcome or solution as a bad outcome or a bad solution: such things don't exist, only situations to understand and to exploit exist; I see the situation, but I cannot cast on it the predicament "bad" and confine it under the spell of this charm which is bound to paralyze me too, but I am to consider it just as a situation - there are truly no bad situations, only facts; and opportunities. A deceptive path must be understood in its meanings, what makes it deceptive is what makes it instructive, and what makes it instructive is what might be its reason to exist!
Given the labyrinthic map we wrote before, we can find a few graphical representations of it. For instance its first two instances, they declared:
1L4R
Let's consider these being just the times in the first steps the traveller must turn leftward and then rightward to his/her own face: this type of map is very
nuclear: it says
nothing about the
length of a corridor, it only says you must keep turning right for
as many as 4 times after you've turned left once for the first time; if then before your first rightward turn and your second one there
lapse 2 miles or 2 meters, this sort of
nuclear labyrinthic map is
not concerned in the least: I called it a
nuclear map, and this should now be its name.
Let's now trace a possible graph of this labyrinthic nuclear map: the letters within the shapes show how many round are made, from letter A onward: thus the highest letter flags the corner of the shape where at the end of the rounds the hypothetical traveller would find him/herself at, facing.
The ensuing shape is what we see (by the way looks like a gnomon, in this case).
This type of graphical representation of a nuclear map for a labyrinth
describes thus, potentially, a morphological growth.
I hope you have noticed that a few times the map traced again squares already drawn, yet at times a square already traced by a
leftward process is
re-traced by a
rightward process, or it is possible that the same square is traced twice (or more, for that matter) by still another
identical rightward or leftward process, over and over again; keep these things in mind.
About the growth of this shape we can make the following considerations:
- More identical shapes can be the result of, actually, different rightward or leftward processes: it is namely well possible that this very same graphical representation of our map could be the shape also for another map, at least as long as we don't introduce as we'll see further elements to be able to guess how many times a square has been traced and retraced by what type of processes (rightward and leftward journeys, that is).
Yet it is possible that identical shapes drawn by different processes may be intrinsically different though identical to the eye - and now don't tell me you can't remember one case where your senses induced you exactly into this type of error.
It also imports observations related to the Gestalt which is a theory that says that the whole is not equal to the sum of its parts; or, to say it with Douglas Hofstadter in the venerable dialogue form he uses (venerable inasmuch as it was already used by Galilei and then in the enlightenment age to present scientific treatises):«Crab: "HOLISM is the most natural thing in the world to grasp. It's simply the belief that the whole is greater than the sums of its parts. No one in his right mind could reject holism."
Anteater: "REDUCTIONISM is the most natural thing in the world to grasp. It's simply the belief that a whole can be understood completely if you understand its parts. No one in her left brain could reject reductionism."
»
- We could rather think that different processes dealing with a recursive traversal of the same square either raise towers on it if (by convention) they are say rightward or dig cavities in it if by convention they are leftward. If two processes which are opposite insist on the same shape, their algebraic sum is the net result that will say whether a tower or a cavity will prevail for that square visited by more processes.
Developing the latter representation, we can say that if the rightward processes add one level to the tower ( ) the leftward subtract one (-) and we thus have:
We could therefore view the orthogonal projections of this shape, let's say to simplify we'll see only the profile of this shape as it would appear cast from the rightmost side, ignoring the surfaces of the peaks and of the pits beyond the most immediate ones:
All these are, undoubtedly,
data structures. We are just drawing different ways to represent the same reality.
If then these representations would not be merely equivalent and conventional, but we would be to discover that one of these shapes is the one which truly gets developed (for instance: the growth of a tree or of a plant), we should explain why this representation gained preeminence above others that appeared equivalent.
The answer can be that we must consider the environment. Likewise a sound is not made by two clashing objects but by the medium (the atmosphere) which is knocked by the clash of the objects as well, in this same fashion we may say that it is the environment (a la Darwin) what selects and decides which among all the possible representation is the one that should also be
actually implemented.
We are thus treading in the ground of Einstein's Relativity: how time flows, how space gets dilated or shrunk, and also how a morphological representation is to be enacted as the apparently standard one, can depend on the relativistic and gravitational parameters and settings we're delved into, and it would be quite possible that among two different and yet equivalent graphical and morphological representations of an algorithm, a different environment would have proposed as the default one, the familiar one, an entirely different one.
Of course, as I said it is well possible that a labyrinth as the representation of an algo-rhythm could have more paths and therefore more maps within: you could have more trials to the center of the maze, and a few fake trials to toil onto.
If a labyrinth exhibits these multiple characteristics, it means it condenses multiple morphogenetic capabilities: and thus
a labyrinth can be the spatial way (or the nuclear way by a family of nuclear maps) to represent in a convenient way a plurality (of options, of patterns, of shapes, of whatever) that clearly have something in common, maybe as a potentiality that could be developed if circumstances allow or that could just rest dormant indefinitely as a promise never fulfilled or as a threat never befallen.
Likewise an algorithm is not defined by what it picks but by what it skips as already stated in Understanding Algorithms, so a data structure is not defined by the blocks that gather to build it, but by the excavated gates that bump it: data structures are not defined by what in them protrudes, but rather by what gives way and renounces to be obtrusive, namely by its paths. A taoist reality looms.
There is the shape and then there is its shadow; there is the body and then there is its print.
Bertrand Russell in his History of western Philosophy, dealing with Pythagoras appeared puzzled by a few Pythagorean moral precepts that Russell dismissed as "taboos". Particularly he quotes the precept that prescribes:
«When you rise from the bedclothes, roll them and smooth out the impress of the body»But this is no longer a surprise: as refined mathematicians that still to-day we study and we learn from and who were electively dedicated to mathematical analysis through
geometrical shapes and not through
computation, they had to know it is the print what truly matters, not the body: and that therefore you'd rather look after it than after the corpse.
The walls are the shape and the paths are both the print and the shadow; and the true hero of this story is the shadow, for the body seems just a pretext to imprint it.
As still Douglas Hofstadter writes:
«I remember quite vividly how puzzled and intrigued I was upon realizing the difference between a positive characterization and a negative characterization. I was quite convinced that not only the primes, but any set of numbers which could be represented negatively, could also be represented positively. The intuition underlying my belief is represented by the question: "How could a figure and its ground not carry exactly the same information?" They seemed to me to embody the same information, just coded in two complementary ways. What seems right to you?»(italics in the original)But here I've pushed a further step forward: it is not just that one information can be
coined in two different ways, it is that one is the press and the other is the true coin, and the truth is that it is the press that is for the imprinting and not the (finger)print an accident of the press. And aren't your fingerprints mazes of identity?
What matters is not having lived and having existed: what matters is having left a
legacy.
You exist for this: a ghost doesn't aspire to be a body, but it should be rather the body that should aspire to show its ghost and to reach the figure, the
silhouette.
The body that disdains the shadow doesn't know it should rather envy it, for when the body will vanish
only the shadow shall outlast it both in time and space, and it will cast itself to cover the centuries and the generations.
May your god grant you the grace of a shadow that men won't remember like the curse that just tainted theirs. Life, a deadly labyrinth where we carve new paths: I hope yours will be one of the many that can lead the travellers to the truth and not one of those fake, deceptive trials that lead the surfers to grope in even greater despair within the Cathedral of Our Maze of The Darkness.
This text is protected by Copyright and cannot be reproduced, either in totality or in part, without the consent of the author. Also derivative works cannot be produced without the consent of the author.
Minor excerpts may be quoted as long as a clearly readable link leading to this file is put in place soon after or soon before the quotation. Only the author has the right to reproduce in its totality this work on other servers.
To perform this operation it is necessary to be Full Poster members. If you are a member, insert your Identification Number and Password in the proper fields, and then proceed: