Setting a Global Within a Proc

setting a global within a proc

It's rather simple, really: the reason why $SAFE doesn't behave like you would expect from a global variable is because it isn't a global variable. It's a magic unicorn thingamajiggy.

There are quite a few of those magic unicorn thingamajiggies in Ruby, and they are unfortunately not very well documented (not at all documented, in fact), as the developers of the alternative Ruby implementations found out the hard way. These thingamajiggies all behave differently and (seemingly) inconsistently, and pretty much the only two things they have in common is that they look like global variables but don't behave like them.

Some have local scope. Some have thread-local scope. Some magically change without anyone ever assigning to them. Some have magic meaning for the interpreter and change how the language behaves. Some have other weird semantics attached to them.

$SAFE has almost all of the above: it is thread-local, meaning that if you change it in one thread, it doesn't affect other threads. It is local, meaning if you change it in a local scope (like a class, module, method or block), it doesn't affect the outer scope (as you have discovered). It has magic meaning for the interpreter, since setting it to a value different than 0 makes certain things not work. And it has additional weird semantics in that you can only ever increase its value, never decrease it.

How to use global variable in oracle stored procedure for query

If you have value in the variables, take it as input parameter

CREATE OR REPLACE PROCEDURE TEST_CHK  
(IN_L_ID OUT NUMBER, S_NAME VARCHAR2(50),R_ID VARCHAR2(50) )
AS

CURSOR STA_CHECK IS
Select NAME, ID FROM KPI_LOG where NAME = S_NAME and ID =R_ID;

BEGIN

...

END TEST_CHK;

How come a proc local variable interferes with global variable

To accomplish what you seem to want, you can use the upvar command. Try this version of the unpack_list command:

proc unpack_list {list1 list2} {
foreach v $list1 e $list2 {
upvar #0 $e var
set var $v
}
}

This will never cause a clash between the global and local variable names.

how to declare a variable globally which is used only in proc

Tcl variables that are not local to a specific procedure run need to be bound to a namespace; the namespace can be the global namespace (there's a special command for that) but doesn't need to be. Thus, to have a variable that is shared between two procedures, you need to give it an exposed name:

proc testList {{setup_file ""}} {
# Use the 'eq' operator; more efficient for string equality
if {$setup_file eq ""} {
set setup_file location
}
global setupFile
set setupFile $setup_file
}
proc run {} {
global setupFile
puts "$setupFile"
}

Now, that's for sharing a full variable. There are some other alternatives provided you only want to share a value. For example, these two possibilities:

proc testList {{setup_file ""}} {
if {$setup_file eq ""} {
set setup_file location
}
# Create a procedure body at run-time
proc run {} [concat [list set setupFile $setup_file] \; {
puts "$setupFile"
}]
}
proc testList {{setup_file ""}} {
if {$setup_file eq ""} {
set setup_file location
}
# Set the value through combined use of aliases and a lambda term
interp alias {} run {} apply {setupFile {
puts "$setupFile"
}} $setup_file
}

There are more options with Tcl 8.6, but that's still in beta.

global variable not recognised when declared in procedure

The command "global y 2" declares 2 global variables, named y and 2 respectively (yes, in Tcl 2 is a perfectly valid variable name). Neither of the variables has a value yet. You may have intended:

global y
set y 2

But that would reset the variable to 2 every time. So you probably want something along the lines of:

set y 2
proc add_new_seq {} {
global y
rid .kl15_val -row $y -column 4
incr y
}
add_new_seq

How do I access a variable outside of a proc

You can use upvar:

set a apples
proc myList {b c} {
upvar a a
puts [concat $a $b $c]
}

Or, expanding the example a bit to show the "source" variable does not have to exist in the global scope:

proc p1 {} { set a 10; p2 }
proc p2 {} { upvar 1 a b; puts "in p2, value is $b" }
p1

outputs

in p2, value is 10

If a was defined in a namespace, you can use variable:

namespace eval foo {
set a apples
# OR
# variable a apples
}

proc foo::myList {b c} {
variable a
puts [concat $a $b $c]
}

Or if a was created in the global scope, you can still access it without the global function, using :: (I'll reference this SO question for this one):

proc myList {b c} {
puts [concat $::a $b $c]
}


Related Topics



Leave a reply



Submit