2016-09-21 24 views
3

我正在使用SAS'PROC FCMP來編寫一些函數進行重新編碼。這些將被保存在共享目錄中的數據集中,所以我的同事可以使用它們。大多數情況下,函數只是將查找表散列在相同目錄中的包裝器。在PROC中散列數據時無法保證libname

簡單的例子:

Libname OurStuff "path/to/shared/data"; 

DATA OurStuff.foobar; 
    foo = 1; 
    bar = 2; 
Run; 

PROC FCMP outlib = OurStuff.functions.lookup; 
    Function recode_foo(foo); 
     Length bar 8; 
     Declare hash foobar(dataset: "OurStuff.foobar"); 
     rc = foobar.defineKey("foo"); 
     rc = foobar.defineData("bar"); 
     rc = foobar.defineDone(); 
     rc = foobar.find(); 
     Return(bar); 
    Endsub; 
Run; 

的功能與原來的LIBNAME工作:

Options cmplib = OurStuff.functions; 
DATA _NULL_; 
    result = recode_foo(1); 
    Put result =; 
Run; 

但是,如果有人使用了不同的LIBNAME,也不會:

Libname OurStuff clear; 
Libname WildName "path/to/shared/data"; 
Options cmplib = WildName.functions; 

/* Results in "ERROR: Libref OURSTUFF is not assigned" */ 
DATA _NULL_; 
    result = recode_foo(1); 
Run; 

是除了堅持每個人都使用相同的libnames外,還有一種方法可以確保這些函數始終有效嗎?

回答

3

由於dataset是一個字符串,它可以在運行時確定。因此,可以將它作爲參數傳遞給函數 - libname或(更好)整個數據集字符串。

PROC FCMP outlib = OurStuff.functions.lookup; 
    Function recode_foo(foo,dset $); 
     Length bar 8; 
     Declare hash foobar(dataset: dset); 
     rc = foobar.defineKey("foo"); 
     rc = foobar.defineData("bar"); 
     rc = foobar.defineDone(); 
     rc = foobar.find(); 
     Return(bar); 
    Endsub; 
Run; 
+1

在FUNCTION語句中需要DSET之後的DSET。 – Tom

+0

@Tom良好的捕獲 - 我喜歡可運行示例的一個原因(當我有秒時,我會創建一個) – Joe

+0

@Joe這個答案可以工作,但我希望爲每個查找函數添加一個額外的參數更優雅。由於數據集名稱是可靠的,我認爲提供容納數據的庫就足夠了:函數recode_foo(foo,lib $)'。這樣,我也可以將庫傳遞給也需要知道在哪裏尋找的嵌套函數。 –