Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-pascal / 2010-05

flexible record design

7 messages · 4 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

spir ☣

Hello,

I'm looking for a "convenient" way to implement a type for kinds of flexible records. "Best" means simple and efficient. A flexible record is a kind of set of name:value symbol, but completely necessary untyped aspect of the question is handled by values beeing pointers. Compared to a mapping *collection*, these objects have some specificity:
* conceptually, each one forms a single, whole, data unit -- as opposed to a set of data.
* Keys are all names (thus, a subset of string), and rather short.
* The number of symbols is typically small; these object are defined by hand! As opposed to extremely varying & possibly huge numbers of collection items.

The most important operation for such an object is value lookup. Some trials have shown me that data structures with sophisticated algorithms such as radix tries or hash table are counter productive (they are severely outperformed by simple sequences up to > 100 items). --> http://groups.google.com/group/pilud/browse_thread/thread/9d7992f97c976cef#

The simplest method may be to create a tool type for name:value symbols, and put this into a TFPList. Lookup is thus traversing the sequence, checking the name until found, returning the value.

Another way would be to hold // sequences for names and values. Lookup should be faster, since names are not hidden in symbol structure. Once a name's index is known, the matching value can be reached using this index. I guess the name sequence could be at best a linked list, since it's only traversed; while values, which are only indexed, should be held in a flexible array (TFPList) for direct indexing. Comments?

But I'm a bit troubled by the documentation about TStrings. TStrings declares interface methods to deal with "associated objects" (not implemented) and "value parts", eg:

   function AddObject(); virtual;   Add a string and associated object to the list.
   property ValueFromIndex: String; [rw]   Return the value part of a string based on it's index.

The description of the type reads:
"... It also allows an arbitrary object to be associated with each string. It also introduces methods to manage a series of name=value settings, as found in many configuration files..."

Side-question: What is the purpose of introducing unimplemented methods? Sub-classes can extend a super-class anyway, no? Is it just an incentive to implement those methods?

I would like to know the underlying structure of TString (linked list, "flexible-ised" dynamic array, what else?). What is actually a name:value association? How does it work and how is one supposed to use it? The _name_ of the feature perfectly fits my needs :-) but can I use it for my flexible record type? Associated objects are not implemented at all (all methods virtual). How is one supposed to design such a feature? Associate a // list of objects (maintaining matching indexes)? But if a TString is an array, lookup is probably slower than necessary (since it's a plain traversal), or am I wrong on this?

Thank you for your patience with a newcomer :-)

Denis
________________________________

vit esse estrany ☣

spir.wikidot.com

Reply by email

Felipe Monteiro de Carvalho
to spir ☣

Hello,

2010/5/28 spir ☣ :

Side-question: What is the purpose of introducing unimplemented methods? Sub-classes can extend a super-class anyway, no? Is it just an incentive to implement those methods?

TStrings is a an abstract class, which means that you shouldn't use it directly. It only provides guidelines for implementing a TStrings like class.

I would like to know the underlying structure of TString (linked list, "flexible-ised" dynamic array, what else?).

TStrings provides no storage.

I think that TStringList should be what you are looking for. See it's code instead.

Felipe Monteiro de Carvalho

Reply by email

spir ☣
to Felipe Monteiro de Carvalho
Show quoted text 6 lines
> I would like to know the underlying structure of TString (linked list, "flexible-ised" dynamic array, what else?). TStrings provides no storage. I think that TStringList should be what you are looking for. See it's code instead.

I know about TStringList. But it does not provide associated values & objects. The reason why I ask about what these things are (supposed to be) in the interface of TStrings. I have a better idea about values, now. Seem to be strings as well (the name "value" is a bit misleading imo), so not what I I'm still digging to try and find out what object association is *intended* to be, its purpose and possible implementation. In other word, what's the actual aim of this virtual interface?

The doc reads:
"Indexed access to the objects associated with the strings in the list. [...]
Objects provides indexed access to the objects associated to the strings in the list. Index is a zero-based index and must be in the range of 0 to Count-1. Setting the objects property will not free the previously associated object, if there was one. The caller is repsonsible for freeing the object that was previously associated to the string. TStrings does not implement any storage for objects. Reading the Objects property will always return Nil, Setting the property will have no effect. It is the responsability of the descendent classes to provide storage for the associated objects."

This is not stupid enough for me. I don't know what to do with this.

Denis
________________________________

vit esse estrany ☣

spir.wikidot.com

Reply by email

Michael Van Canneyt
to spir ☣
spir ☣ wrote 22 lines
On Fri, 28 May 2010 12:25:59 +0200 Felipe Monteiro de Carvalho wrote: >> I would like to know the underlying structure of TString (linked list, "flexible-ised" dynamic array, what else?). > > TStrings provides no storage. > > I think that TStringList should be what you are looking for. See it's > code instead. I know about TStringList. But it does not provide associated values & objects. The reason why I ask about what these things are (supposed to be) in the interface of TStrings. I have a better idea about values, now. Seem to be strings as well (the name "value" is a bit misleading imo), so not what I need at all. But I'm still digging to try and find out what object association is *intended* to be, its purpose and possible implementation. In other word, what's the actual aim of this virtual interface? The doc reads: "Indexed access to the objects associated with the strings in the list. [...] Objects provides indexed access to the objects associated to the strings in the list. Index is a zero-based index and must be in the range of 0 to Count-1. Setting the objects property will not free the previously associated object, if there was one. The caller is repsonsible for freeing the object that was previously associated to the string. TStrings does not implement any storage for objects. Reading the Objects property will always return Nil, Setting the property will have no effect. It is the responsability of the descendent classes to provide storage for the associated objects." This is not stupid enough for me. I don't know what to do with this.

TStrings provides an abstract interface. It allows you to associate an object with each string in the list.

This means you can do a

   L.Strings[i]:=Key;
   L.Objects[i]:=MyObject;

Or, in 1 statement:

   L.AddObject(Key,MyObject);
And you can retrieve it with
   I:=L.IndexOf(MyKey);
   If (I=-1) then
    // no mykey in list
   else
    MyObject:=L.Objects[i];

However, it does not actually implement this; it just provides a common API for a string list with associated objects.

TStringList actually implements - in a simplistic way - the functionality to store the strings, and the associated objects.

The 'Values' property is for Name=Value pairs, where both are strings. (used commonly in .ini files)

That means that if you do

L.Add(mykey+'='+myvalue);

or, alternatively

L.Values[mykey]=myvalue;

you can retrieve myvalue with

MyValue:=L.Values[mykey];

The objects are not used in this case, the list contains items of the form Name=Value.
This is not very performant, but works easily for small amounts of values.

For large amounts of data, you should use hash lists, as implemented in the contnrs unit.

Michael.

Reply by email

spir ☣
to Michael Van Canneyt
Show quoted text 18 lines
TStrings provides an abstract interface. It allows you to associate an object with each string in the list. This means you can do a L.Strings[i]:=Key; L.Objects[i]:=MyObject; Or, in 1 statement: L.AddObject(Key,MyObject); And you can retrieve it with I:=L.IndexOf(MyKey); If (I=-1) then // no mykey in list else MyObject:=L.Objects[i];

Thank you very much, that's what I needed to understand. If I get it right, using the Objects property is analog to what I intended to do with a TStringList for names // to a TFPList for values.

Show quoted text 5 lines
However, it does not actually implement this; it just provides a common API for a string list with associated objects. TStringList actually implements - in a simplistic way - the functionality to store the strings, and the associated objects.

All right, now I get it. Just a point about doc: Some methods implemented in TStringList, but virtual in TString, are listed in the interface of TStringList at http://www.freepascal.org/docs-html/rtl/classes/tstringlist.html. But the ones dealings with associated objects aren't listed there (including the Objects property). This feature is also not mentionned in the description. So, I thought TStringList simply does not implement this functionality. Another point: in the description of TList and TFPList is written that the notification system (not implemented on TFPList) is slows down some mechanisms. Is there a version of TStringList without this feature. I need the simplest and most efficient version, because the type I'm now designing will be the elementary building block of a rather big system.

Denis
________________________________

vit esse estrany ☣

spir.wikidot.com

Reply by email

Michael Van Canneyt
to spir ☣
spir ☣ wrote 35 lines
On Fri, 28 May 2010 16:03:28 +0200 (CEST) Michael Van Canneyt wrote: > TStrings provides an abstract interface. It allows you to associate an > object with each string in the list. > > This means you can do a > > L.Strings[i]:=Key; > L.Objects[i]:=MyObject; > > Or, in 1 statement: > > L.AddObject(Key,MyObject); > > And you can retrieve it with > I:=L.IndexOf(MyKey); > If (I=-1) then > // no mykey in list > else > MyObject:=L.Objects[i]; Thank you very much, that's what I needed to understand. If I get it right, using the Objects property is analog to what I intended to do with a TStringList for names // to a TFPList for values. > However, it does not actually implement this; it just provides a common > API for a string list with associated objects. > > TStringList actually implements - in a simplistic way - the functionality > to store the strings, and the associated objects. All right, now I get it. Just a point about doc: Some methods implemented in TStringList, but virtual in TString, are listed in the interface of TStringList at http://www.freepascal.org/docs-html/rtl/classes/tstringlist.html. But the ones dealings with associated objects aren't listed there (including the Objects property). This feature is also not mentionned in the description. So, I thought TStringList simply does not implement this functionality. Another point: in the description of TList and TFPList is written that the notification system (not implemented on TFPList) is slows down some mechanisms. Is there a version of TStringList without this feature. I need the simplest and most efficient version, because the type I'm now designing will be the elementary building block of a rather big system.

TStringList doesn't have the notification mechanism.

Michael.

Reply by email

David Emerson
to spir ☣: On Fri, 28 May 2010 16:03:28 +0200 (CEST) Thank you very much, that's what I needed to…
Spir wrote
I need the simplest and most efficient version, because the type I'm now designing will be the elementary building block of a rather big system.

If you design your class hierarchy well, it ought to be possible to switch the base later on.

Personally, I reinvented the wheel by creating my own list framework that suits my needs. If you're interested I'd be happy to share it, although really my first comment ought to trump much interest therein.

Cheers,
David

Reply by email