grabbing value of a variabe by its name?

Richard A. O'Keefe ok at cs.otago.ac.nz
Fri Jul 26 00:32:57 UTC 2002


Ragnar Hojland Espinosa <ragnar at linalco.com> wrote:
	foo _ 'hello'.
	bar _ 'world!'.
	baz _ #(foo bar).
	
	I can get the name of the var by a (baz at:  1), but how do i
	get its value?
	
We had a somewhat related thread about Smalltalk being insufficiently
"objectified" a week or two ago.  The answer is that a variable is not
an object so you can't do this.

You *can* do
	foo := 'hello'.
	bar := 'world!'.
	baz := {#foo -> foo. #bar -> bar}.
but that's didferent.

	The reason for this question is as follows.  I have:
	
	execute 'insert into table1 (var1,var2,var3) values (',
		var1 asQuotedPostgres,',',
		var2 asQuotedPostgres,',',
		var3 asQuotedPostgres,')'.
	
Um, there are two *different* things called 'var1' here.
There is a column of TABLE1 called VAR1
and there is a Smalltalk variable called var1

	and I'd like to do something like:
	
	fields _ SQLFields new: #(var1 var2 var3).
	execute 'insert into table1 (', fields asNames, ') values (', 
		fields asValues, ')'. 


Trust me.  You don't want to do this.  The names you want in table1(..)
are the names of the *columns*, while the names you want to get the values
are the names of the Smalltalk *variables*.  Tying the correctness of your
code to a somewhat unpleasant and not always feasible pun is a good way to
fail.

What you want is an automatically generated set of wrapper classes
so that you can do

    newRow := Table1 new.	"make new row with default values"
    newRow var1: "some value"; var2: "some value"; var3: "some value".
    newRow insert.		"insert new row into table"

In a data base designed using the Entity-Relationship approach,
a row in a table very nearly _is_ an object, so it might as well be
mirrored in your code _as_ an object.

A band-aid solution to your problem is to represent a row as a dictionary:

    newRow := Dictionary new.
    newRow at: #var1 put: "some value".
    newRow at: #var2 put: "some value".
    newRow at: #var3 put: "some value".
    Sql insert: newRow into: #table1

The quoted names here are *SQL* names only, not at all punning with
Smalltalk names.

Here Sql>>
    insert: aRow into: aTableName
        |ns vs sep|
        sep := ''.
        ns := ''.
        vs := ''.
        aRow keysAndValuesDo: [:key :value |
	    ns := ns, sep, key.
	    vs := vs, sep, value asQuotedPostgres.	    
	    sep := ', '].
	Sql execute: 'insert into ', aTableName, '(', ns,
	             ') values (', vs, ')'

Actually, I'd use Streams here, not string concatenation, but this
gets the idea across.

Let me stress one more time:
    DON'T rely on punning between Smalltalk names and SQL names.
    Smalltalk names are case sensitive but only allow letters and digits.
	(ANSI Smalltalk allows _ but Squeak doesn't support that yet.)
    SQL names are not case sensitive and all more than letters and digits.
    Above all, each of them might change separately.  If a column is
    renamed, you DON'T want to have to rename a lot of Smalltalk code
    immediately.




More information about the Squeak-dev mailing list