Mostrando postagens com marcador Caché Objects. Mostrar todas as postagens
Mostrando postagens com marcador Caché Objects. Mostrar todas as postagens

quarta-feira, 6 de agosto de 2008

Xecute Scoping

A nasty gotcha in scoping when you try to use Caché's "interpret a string containing code" command xecute inside an object.

You can execute (ie. eval) a string containing a piece of Caché ObjectScript with xecute like this :


set m = "write 2+2"
xecute m


xecute only works on statements, not expressions. But you can use the alternative @ for that. Eg.


set m = "2+2"
write @m



However, if you try to use this inside a class definition, something odd happens.

When a class is compiled, the string which contains code is obviously not affected by the pre-processor. But it seems that when the method is run and the string xecuted, the variable names in the string don't get bound to the scope within the method. Instead they get their values from the global frame or somewhere else entirely.

Look at the following example.

A class :


Class MY.ScopeGotcha Extends %Persistent [ ClassType = persistent, ProcedureBlock ]
{

Method f() {
set x = 6
set m = "write !,x"
xecute m
}

}


Now try running it from the terminal like this :


set x = 9
set y = ##class(MY.ScopeGotcha).%New()
do y.f()


Guess what it prints ... :-)

domingo, 27 de julho de 2008

Intersystems's documentation for Caché is notoriously bad.

Here's a classic example I found today for the "super" keyword.

Yes, I realize "super" has something to do with super-classes and inheritance and so the "extends" keyword is relevant ... but ... er ... wouldn't you expect the "super" example to actually *use* the "super" keyword? Somewhere?

Or if there is no "super" keyword, because "extends" is how you declare inheritance relationships, what on earth is this page doing here?

Update : after further consideration, the only way I can decode this is that "super" is the name of the list of super-classes. That's why the super "keyword" can "have a value".

This is typical of Intersystems' often garbled approach to documentation. Don't they know what the word "keyword" actually means???

quarta-feira, 16 de julho de 2008

The Quest for an ObjectScript Iterator (part 5)

In which we take the last post's iterator and simply wrap it inside a Caché Objects class.

Define a class User.MultiIterator



Class User.MultiIterator Extends %Persistent
{

Property i As %String;
Property j As %String;
Property k As %String;
Property val As %String;

Method startIterator()
{
set ..i=""
set ..j=""
set ..k=""
}

Method next()
{
if (..i="") {
set ..i=$order(^multi(..i))
quit ..next()
}
if (..j="") {
set ..j=$order(^multi(..i,..j))
quit ..next()
}
set ..k=$order(^multi(..i,..j,..k))
if ..k'="" {
set ..val = $get(^multi(..i,..j,..k))
quit 1
}
set ..j=$order(^multi(..i,..j))
if ..j'="" {
quit ..next()
}
set ..i=$order(^multi(..i))
if ..i'="" {
quit ..next()
}
quit 0
}

}



Using it (in another file) is now :



new it
set it= ##class(User.MultiIterator).%New()
do it.startIterator()
while it.next() {
write !,it.i_","_it.j_","_it.k_" : "_it.val
}



The logic is identical. The only difference, now I've made the i,j and k indices and the val properties of the iterator object rather than local variables passed by reference. It looks perhaps a little cleaner from the user's perspective. OTOH you have to create an extra class definition routine.

In the next post I think it's time to start thinking how we can add some filtering to the iterator.

Update : thanks to 80N for the correct. (Read comments)

segunda-feira, 14 de julho de 2008

Method Generators

Just noticed that you can do interesting compile-time code generation in Caché Objects using compile-time Method Generators.

Something I'll be investigating shortly.