Dictionary Class

Post your FreeBASIC source, examples, tips and tricks here. Please don’t post code without including an explanation.
Post Reply
Roland Chastain
Posts: 992
Joined: Nov 24, 2011 19:49
Location: France
Contact:

Re: Dictionary Class

Post by Roland Chastain »

paul doe wrote:@Other people, reading the thread:

Is the thread title misleading? If it is, I can change it to 'Hash Table' or 'Associative Array', if it's more clear that way...
In my opinion, no, you don't have to change the title. The word dictionary is commonly used as you do (example).
srvaldez
Posts: 3373
Joined: Sep 25, 2005 21:54

Re: Dictionary Class

Post by srvaldez »

@Paul doe
your latest version works OK on macOS, however I had to comment-out all "export" statements otherwise ld would give this error

Code: Select all

ld: unknown option: --export-dynamic
linking failed: 'ld' terminated with exit code 1
Compilation failed.
paul doe
Moderator
Posts: 1730
Joined: Jul 25, 2017 17:22
Location: Argentina

Re: Dictionary Class

Post by paul doe »

Roland Chastain wrote:In my opinion, no, you don't have to change the title. The word dictionary is commonly used as you do (example).
Ok, then. Will leave it at that =D
srvaldez wrote:@Paul doe
your latest version works OK on macOS, however I had to comment-out all "export" statements otherwise ld would give this error
...
Really? That's odd, since the previous version also had them and you had no trouble compiling the lib version, no? Anyway, they're only needed if you're going to compile the code as a .dll, so no great loss. Thanks for testing, good to know it also works on a Mac =D
D.J.Peters
Posts: 8586
Joined: May 28, 2005 3:28
Contact:

Re: Dictionary Class

Post by D.J.Peters »

Paul you will run in to trouble if you declare stuff as public in a static build.
(trust me I was run in to same trouble)

Here are a simple solution for you, put it at first lines in file: fb-dictionary.bi

Joshy

Code: Select all

' is it a exe or dynamic build ?
#if __FB_OUT_EXE__ or __FB_OUT_DLL__
  ' use export no changes needed
#else
  ' must be a static lib build redefine "export" to nothing
  #undef export
  #define export
#endif
paul doe
Moderator
Posts: 1730
Joined: Jul 25, 2017 17:22
Location: Argentina

Re: Dictionary Class

Post by paul doe »

Hi, Joshy
D.J.Peters wrote:Here are a simple solution for you.
Nice tip, thanks. However, I do need to expose the objects that compose the class, if not, the class by itself is useless. The only classes that could be left opaque would be the DictionaryArray class and the DictionaryEntry class, but you need direct access to all the others to be able to implement something on top of them.

FreeBasic object model is pretty limited ATM, so you have to 'fudge' some features, such as inherit-only classes (like the ones declared as 'MustInherit' in VB.NET). In the case of the IDictionary interface, the needed methods are declared as 'protected:' so you actually need to derive a class from the interface to be able to access the instances' internal hash table, and thus implement the 'item()', 'remove()' and 'add()' methods normally expected in classes like this.

Thanks for the info. I'll probably change the code like you suggest, since it seems like other members (like srvaldez above) are experiencing troubles with the 'export' clause when compiling it as static lib.

On a side note, can you selectively expose objects in a static lib, or are all the symbols public?
MrSwiss
Posts: 3910
Joined: Jun 02, 2013 9:27
Location: Switzerland

Re: Dictionary Class

Post by MrSwiss »

paul doe wrote:On a side note, can you selectively expose objects in a static lib, or are all the symbols public?
Nope, it is exactly the other way around:
You can selectively declare them being 'private' = NOT exposed (only lib internal).
All else is by default 'public'.
jj2007
Posts: 2326
Joined: Oct 23, 2016 15:28
Location: Roma, Italia
Contact:

Re: Dictionary Class

Post by jj2007 »

paul doe wrote:
jj2007 wrote:There is a "real" dictionary, Webster's Unabridged Dictionary at Project Gutenberg, 27.6 MB of plain UTF-8 text for download, but it doesn't look like it's a candidate for a dictionary class.
Why not? It'll be very cool to be able to map it, if not because I found it very difficult to parse the text to separate the keys (in this case the words of the dictionary) from the values (the definitions of the words).
That is why wrote "not a candidate" - no clear delimitation, impossible to parse.
But I have found a test case: 556 ms for finding 2 entries in 3,806,636 lines - that is an Instr() search, and I have a feeling that it could be made a little bit faster. Guess which easily accessible important text source has around 4 Million lines and around 250 MB... an ideal test case!
paul doe
Moderator
Posts: 1730
Joined: Jul 25, 2017 17:22
Location: Argentina

Re: Dictionary Class

Post by paul doe »

MrSwiss wrote:Nope, it is exactly the other way around...
Yep, then it seems like I did it the other way around then =D
Thank you!
paul doe
Moderator
Posts: 1730
Joined: Jul 25, 2017 17:22
Location: Argentina

Re: Dictionary Class

Post by paul doe »

Ok, just finished revamping the repository. Only minor changes to the code, and some explanations added to the comments. I'll be adding a more meaningful example soon, but first I have to code it =D

If someone needs help on implementing some feature in their own code (as Makoto WATANABE), just ask and we can address it here.
Makoto WATANABE
Posts: 231
Joined: Apr 10, 2010 11:41
Location: Japan
Contact:

Re: Dictionary Class

Post by Makoto WATANABE »

Dear paul doe;

Thank you for adding a lot of sample programs.
In my environment, other programs moved but only "fb-dict-example-1.bas" got a following error:
Please tell me how to fix it.

C:\Tool\FreeBASIC\\fbc -s console -mt "fb-dict-example-1.bas"
fb-dict-example-1.o:fake:(.text+0xdb1): undefined reference to `DICTIONARY::operator=(DICTIONARY&)@8'
fxm
Moderator
Posts: 12081
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: Dictionary Class

Post by fxm »

It means that the Let operator of DICTIONARY is declared (and called), but that its definition is missing !
paul doe
Moderator
Posts: 1730
Joined: Jul 25, 2017 17:22
Location: Argentina

Re: Dictionary Class

Post by paul doe »

Makoto WATANABE wrote:Dear paul doe;

Thank you for adding a lot of sample programs.
In my environment, other programs moved but only "fb-dict-example-1.bas" got a following error:
Please tell me how to fix it.

C:\Tool\FreeBASIC\\fbc -s console -mt "fb-dict-example-1.bas"
fb-dict-example-1.o:fake:(.text+0xdb1): undefined reference to `DICTIONARY::operator=(DICTIONARY&)@8'
Hi Makoto,

I don't get any error here from the latest version downloaded directly from the repo. Can you post the offending code? Bear in mind that you can't do this:

Code: Select all

dim as Dictionary a = Dictionary()
dim as Dictionary b = Dictionary()

a = b
Shallow copies are disabled, because the class uses explicitly allocated memory internally, so you have to provide the appropriate code in derived classes. What are you trying to accomplish, concretely?
fxm
Moderator
Posts: 12081
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: Dictionary Class

Post by fxm »

paul doe wrote:Shallow copies are disabled, because the class uses explicitly allocated memory internally, so you have to provide the appropriate code in derived classes. What are you trying to accomplish, concretely?
But we cannot define a Let operators in the derived type because this operator would be mandatory chained with that of the base type which is forbidden !
(this would go against the principle of inheritance)
paul doe
Moderator
Posts: 1730
Joined: Jul 25, 2017 17:22
Location: Argentina

Re: Dictionary Class

Post by paul doe »

fxm wrote:But we cannot define a Let operators in the derived type because this operator would be mandatory chained with that of the base type which is forbidden !
(this would go against the principle of inheritance)
Not exactly. Look at how the IDictionary interface is defined:

Code: Select all

type IDictionary extends Object
	public:
		declare constructor()
		declare constructor( byval as uinteger )
		
		declare virtual destructor()
		
		declare property size() as uinteger
		declare property count() as uinteger
		declare property fixedSize() as boolean
		declare property fixedSize( byval as boolean )
		declare property allowDuplicates() as boolean
		declare property allowDuplicates( byval as boolean )
		
		declare sub clear()
		
	protected:
		declare constructor( byref as IDictionary )
		declare sub initializeComponent()
		
		declare property entries() as DictionaryArray ptr
		
		declare function keyExists( byval as IDictionaryKey ptr ) as boolean
		
		declare function addEntry( _
			byval as IDictionaryKey ptr, _
			byval as any ptr, _
			byval as sub( byval as any ptr ) = 0 ) as boolean
		
		declare function getEntry( _
			byval as IDictionaryKey ptr ) as DictionaryEntry ptr
		
		declare function removeEntry( _
			byval as IDictionaryKey ptr ) as DictionaryEntry ptr
		
		declare sub rehash( byval as uinteger )
		
		<snip>				
end type
The copy constructor is declared as protected. Now, look at the reference implementation of the Dictionary class:

Code: Select all

type Dictionary extends collections.IDictionary
	public:
		declare constructor()
		declare constructor( byval as uinteger )
		declare destructor() override
		
		declare function add( _
			byref as const string, _
			byval as any ptr, _
			byval as sub( byval as any ptr ) = 0 ) as boolean
		
		declare function item( byref as const string ) as any ptr
		declare sub remove( byref as const string )
		declare function keyExists( byref as const string ) as boolean
		
	protected:
		declare constructor( byref as Dictionary )
		declare operator let( byref as Dictionary )
end type
This means that you can, effectively, derive anything from Dictionary (I use it in 'fb-dict-example-1.bas' to derive a class called 'RegisterDictionary', and it's used in the code without problems.
In a sense, the IDictionary class works as an inheritable-only class, but since FreeBasic doesn't have such fine-grained control over the inheritance process, you have to somehow 'fake' it with hacks like this. The IDictionary class would be a 'MustInherit' class from VB.NET. So, if you want to do a deep copy of the object, you must provide a method (like Dictionary->copyTo() ) to do so.
The IDictionary class exposes the internal hash table via the 'entries()' property but only to derived classes, just for this purpose. This is for two reasons: I want to keep the inheritance hierarchy as flat as possible, and I don't want to expose the internal hash table to client code, only to the classes that are childs of IDictionary. Besides that, making a deep copy of the IDictionary class is a costly operation, and you don't normally want these kind of operations to be performed implicitly.

Perhaps I should explain a little how the code works, either here or on the repo, to avoid possible issues for the people that want to implement their own classes. I'll see to it.
fxm
Moderator
Posts: 12081
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: Dictionary Class

Post by fxm »

I get the same error as Makoto WATANABE.
(my previous remark is still valid in my opinion)
Post Reply