VisualWorks Smalltalk Forums
September 05, 2010, 01:03:32 AM *
Welcome, Guest. Please login or register.

Login with username, password and session length
News: NYCST presents:  Introducing Web Velocity
 
   Home   Help Search Calendar Tags Login Register  
Pages: [1]
  Print  
Author Topic: Problems with #{obj} ifDefinedDo:  (Read 1460 times)
GaryD
Newbie
*
Posts: 41


Skype me: SageOfSmeg


View Profile
« on: November 09, 2009, 03:37:34 PM »

Need some help identifying a coding bug.

I have an initialization (.ini) file that looks like this:
   [OdbcPostgreSQL]
   hostsuffix=:
   portsuffix=_
   host1=127.0.0.1
   port1=5432
   host2=127.0.0.1
   port2=5432

I have developed a small utility class to read in values from the .ini file.

Smalltalk defineClass: #AppIni
   superclass: #{Core.Object}
   indexedType: #none
   private: false
   instanceVariableNames: 'sections '
   classInstanceVariableNames: ''
   imports: ''
   category: ''

Instance methods:-

AppIni>>initialize
   "Answer a newly created instance."
   sections := Dictionary new.
   ^self

AppIni>>loadSections
   "Loads the dictionary with sections and their message=value pairs from the .ini file."
   ...
and this populates the sections Dictionary thus:
Dictionary ('OdbcPostgreSQL'->Set ('hostsuffix=:' 'port2=5432' 'host1=127.0.0.1' 'portsuffix=_' 'host2=127.0.0.1' 'port1=5432') )
so in effect the Dictionary identifies the target class and selectors to be used with their arguments.

NB. OdbcPostgreSQL is a class I have developed to handle DB connections via PostgreSQLEXDIConnection and it has protocol including: hostsuffix, port2, host1, etc. in other words the messages in the above Set associated with the dictionary key.
See where I’m going?

However, I have another method with which I am having problems:
AppIni>>initializeObject: anObject
   "Processes the message=value pairs from the dictionary having key named after anObject
   and initializes the corresponding instance variables of the object."

   | pairs obj line msg arg sectionKey |
   sectionKey := (anObject class printString).
Transcript show: 'sectionKey = ' , sectionKey;cr.
   pairs := self sections at: sectionKey.
   obj := (anObject class name).   "the name of the class as a symbol"
Transcript show: 'anObject = ' , anObject printString;cr.
   #{obj} ifDefinedDo: [:className |       "<------ this is the bit causing problems"
Transcript show: obj printString , ' is defined!';cr.
         pairs do: [:element |
                  line := element tokensBasedOn: $=.   "Extract each message=value pair"
                  msg := (line first , ':') asSymbol.
                  arg := line last.
                  anObject perform: msg with: arg]
         ].
   ^anObject

This is then used thus:
ini := AppIni new loadSections.
anObject := OdbcPostgreSQL new.
result := ini initializeObject: anObject.
result host1

The problem is that the #{obj} is not recognized as defined when anObject is an instance of OdbcPostgreSQL. The value of ‘host1’ does no get set, although it does if I remove the #{obj} ifDefinedDo:
 
If I reproduce the above code in the workspace it works just fine, but not in the method itself and I cannot see why #{obj} ifDefinedDo: is failing.

I have inspected #{obj} in both versions and they both show the same value. I’m stumped!

Any ideas.
Logged
charles
Jr. Member
**
Posts: 84



View Profile
« Reply #1 on: November 09, 2009, 06:03:16 PM »

Gary:

First of all , pls note that there's a class Net.IniScanner  that provides you with ini file reading services. Should be part of the NetClients parcel if I recall.

Secondly , pls consider the following:

MyClass>>> (class side)
test2
   "self test2"
   | obj |

   obj :=  Object new class name.

   ^ #{car}

and for fun try this variation:

test2
   "self test2"
   | obj |
   obj :=  Object new class name.

   ^ #{yellow.submarine}

better if you do these in a browser.


"accept it" and the evaluate the comment: "self test2"

also consider/inspect this:

#( car elephant truck plane)

by now I bet you are getting my drift.


This:

 #{MyClassName} is a literal construct i.e. the entire thing starting with # and ending with }



This should work for you:

AppIni>>initializeObject: anObject
   "Processes the message=value pairs from the dictionary having key named after anObject
   and initializes the corresponding instance variables of the object."

   | pairs obj line msg arg sectionKey |
   sectionKey := (anObject class printString).
Transcript show: 'sectionKey = ' , sectionKey;cr.
   pairs := self sections at: sectionKey.
   obj := (anObject class name).   "the name of the class as a symbol"
Transcript show: 'anObject = ' , anObject printString;cr.

   (BindingReference simpleName: obj)
     ifDefinedDo: [:className |       "<------ this is the bit causing problems"

Transcript show: obj printString , ' is defined!';cr.
         pairs do: [:element |
                  line := element tokensBasedOn: $=.   "Extract each message=value pair"
                  msg := (line first , ':') asSymbol.
                  arg := line last.
                  anObject perform: msg with: arg]
         ].
   ^anObject




Let me know.


Logged
GaryD
Newbie
*
Posts: 41


Skype me: SageOfSmeg


View Profile
« Reply #2 on: November 10, 2009, 04:58:38 AM »

Hi Charles,

Thanks for the tip on Net.IniScanner. I wouldn't have thought of looking in that parcel for an ini file reader.
I often make reference to Cincom Resolutions (http://www.cincomsmalltalk.com/ResolutionsApplication/CincomResolutionsPortal) for useful code.

Yes, your suggestion worked as I intended. Now I see why the literal/symbol conversion didn't achieve what I expected, although I still don't understand how it worked in the workspace.

Thanks (yet again!)
Gary
Logged
charles
Jr. Member
**
Posts: 84



View Profile
« Reply #3 on: November 10, 2009, 09:55:46 AM »

Gary:

the short answer is that a Workspace is this special world Smiley Now, I didn't go as far into your code to pretend I know but if you walk yourself into ifDefinedDo: and I mean live in a debugger in your Workspace code (just highlight and do "debug it" ) I think you will find that <obj> has a binding and that binding is housed in the context of the Workspace i.e. if I recall the lookup tries to ascertain whether the  "named class" exists within a known context i.e. usually a Namespace but in the case of code evaluated in a Workspace the "Workspace" it self becomes a context and any var that has been assigned a value but not explicitly specified as a local var i.e. | myVar | type of thing will become forever bound in the context of that Workspace and of course within the lifespan of the image.

but have some fun and dive into the catacombs of ifDefinedDo: , btw, I highly suggest to go for walks with your debugger i.e. some deep walks, it is your best friend.

also let me know when you want to start talking about using the native Postgres driver functionality.
Logged
Tags: GeneralBindingReference  ifDefinedDo: 
Pages: [1]
  Print  
 
Jump to:  

Powered by MySQL Powered by PHP Powered by SMF 1.1.9 | SMF © 2006-2009, Simple Machines LLC
Twitter Mod 1.3 created by 2by2host.com - a web hosting company
Valid XHTML 1.0! Valid CSS!