Join Now

Juletip #13 - proc lua, din nye bedste ven når du skal programmere

by SAS Employee AllanLassen ‎12-17-2015 04:02 AM - edited ‎12-17-2015 04:05 AM (595 Views)

 

Og det skete i de dage at Jim Goodnight skabte SAS Institute og programmeringssproget SAS. Goodnight så, at det var godt. Og med en skæv blanding af en statistisk entrepenør, juleevangeliet og skabelsesberetningen er julestemningen forhåbentlig på plads, og vi er hermed igang med det 13. juletip!

Dengang i SAS-tidernes morgen, anno 1973, så programmerne ganske anderledes ud, end de gør den dag i dag. Det gætter jeg i hvert fald på, jeg var endnu ikke født på dette tidspunkt. Min hurtige research fortæller mig i hvert fald at macro-sproget først så sin spæde begyndelse med SAS 82, og nej, der manglede ikke et punktum i versionsnummeret! Vi skal dermed omtrent 33 år tilbage i tiden, før "vi" fik mulighed for at påvirke flowet af et SAS program, så det ikke blot blev læst fra top til bund, men også kunne påvirkes af logik og gentagelser af kode. Citationstegnene omkring "vi", skyldes at jeg stadig ikke var født på dette tidspunkt.

Macro-sproget er blevet udviklet en del igennem årene, og får da til stadighed en ny feature eller to med hver større frigivelse af SAS. Med den allerseneste version af SAS (9.4M3) kommer der dog den ny procedure proc lua som, blandt mange andre ting, kan give et alternativ til at påvirke SAS-programmers afvikling på.

lua er et relativt ungt programmeringssprog, som oprinder fra et universitet i Brasillien og dermed intet direkte har med SAS at gøre, udover at det altså nu er tilgængeligt som endnu et værktøj, på linje med eksempelvis proc sql. Sproget lua rummer mange nyttige features og elegante måder at løse gængse programmeringsproblemer på, som ikke direkte er kan overføres til SAS sproget.
Jeg skal her forsøge at komme med tre eksempler, som viser lidt om syntaksen, elegancen og fordelene ved dette sprog. Måske endda grunde til at lua måske kunne være interessant at kigge på, for jer SAS brugere derude.

 

  1. Første ting er næppe noget der i sig selv vil være grund i sig selv til at begynde at anvende lua, men dog et eksempel på en genial feature i sproget. Nemlig muligheden for at give flere output tilbage i samme funktion:

    proc lua;
    submit;
    	function split_today()
    		-- get current date
    		local date = sas.today()
    		-- return day, month, year
    		return sas.day(date), sas.month(date), sas.year(date)
    	end
    	
    	local day, month, year = split_today()
    	print("d=", day, "m=", month, "y=",year)
    endsubmit;
    run;
    
    NOTE: Lua initialized.
    d=    15    m=    12    y=    2015
    

    På en enkelt linje kan man altså få eksempelvis både dag, måned og år ud af en dato. Smart!

  2. De fleste kan nok nikke genkendende til at &- og %-tegn af og til kan blive lidt vanskelige at finde hoved og hale i. Se fx her, hvor alle værdier bliver udskrivet fra alle fem kolonner fra den velkendte sashelp.class tabel - både på macro måden, og på lua-måden. (http://www.lexjansen.com/nesug/nesug09/bb/BB08.pdf)

    %macro print_vals;
        %local dsid rc now total cols;
        %let dsid = %sysfunc(open(sashelp.class));
        %let cols = %sysfunc(attrn(&dsid, nvars));
        %let now  = 0;
    
        %do %while (%sysfunc(fetch(&dsid)) = 0);   %* outer loop across rows;
            %let now=%eval(&now + 1);
    
            %do i=1 %to &cols;   %* inner nested loop;
                %local v t;
                %let v=%sysfunc(varname(&dsid,&i));
                %local &v;
    
                %let t = %sysfunc(vartype(&dsid, &i)); %* N or C;
                %let &v = %sysfunc(getvar&t(&dsid, &i));
    
                %put &&&v.;%* put value;
            %end;
        %end;  %* while fetch loop;
        %let rc = %sysfunc(close(&dsid));
    %mend print_vals;
    %print_vals
    Alfred
    M
    14
    69
    112.5
    Alice
    F
    ...
    

     

    Dette står selvfølgelig i skærende kontrast til den noget simplere lua-kode, som blandt andet er mulig takket være den generiske for-løkke som både kan give information om værdi og inkrementværdi, også beskrevet i punkt 1.
    proc lua;
    submit;
        local dsid = sas.open("sashelp.class")
        for row in sas.rows(dsid) do
            for i, value in ipairs(row) do
                print(value)
            end
        end
        sas.close(dsid)
    endsubmit;
    run;

     

  3. Det er naturligvis også muligt at køre ganske almindelig SAS-kode i lua, ved hjælp af den såkaldte submit-funktion, som er stillet til rådighed i SAS' bibliotek af lua-funktioner. Dette bibliotek rummer i øvrigt også alle de kendte SAS-funktioner. Således kører nedenstående kode fint i SAS, og udfører de kendte SAS kommandoer.

    proc lua;
    submit;
        sas.submit[[
            proc sort data=sashelp.class(keep=sex age) out=class_sort;
                by sex;
            run;
    
            data class_calc(keep=sex avg_age);
                set class_sort;
                by sex;
                if first.sex then do;
                    age_sum     = 0;
                    num_pers = 0;
                end;
                age_sum + age;
                num_pers + 1;
                if last.sex then do;
                    avg_age = age_sum/num_pers;
                    output;
                end;
            run;
        ]]
    endsubmit;
    run;

Udover alt det ovenstående er der endnu mere guf tilegnet de avancerede programmører eller de ivrige nysgerrige. Udover at være kompakt, letlæseligt og open-source rummer sproget nemlig også alle fordelene fra et "avanceret" programmeringssprog. Herunder muligheden for at bruge mere avancerede koncepter såsom komplekse datastrukturer, klasser og objekter. Dette står i kontrast til macro-sproget, der som bekendt primært er en intelligent tekst-motor til at drive SAS-programmer. Fx vil hash-tabeller, træer, stakke og køer vil alle være tilgængelige datastrukturer i lua, som vil være svære at programmere i SAS macro sproget.

lua vil helt sikkert ikke erstatte macro-sproget, og der er ikke nogen åbenlys grund til at omskrive alle ens gamle macroer blot for at føre det over i lua. Ikke desto mindre er dette ekstra værktøj i værktøjskassen, som helt sikkert kan blive nyttigt i mange situationer! Særligt i forbindelse med meget store programmeringsprojekter, eller der hvor mere avancerede sprog-features er nødvendige.

Hvis du læser med endnu er du nok interesseret i at vide endnu mere, og til det formål findes der selvfølgelig et paper, og en masse dokumentation, samt selvfølgelig mere info om lua selv på luas eget community. Følg eksempelvis disse links, og opdag selv mere omkring lua og SAS i samspil. God jul og godt nytår til jer alle!

http://www.lua.org/ (lua's egen hjemmeside med yderligere links til info og community)
http://support.sas.com/resources/papers/proceedings15/SAS1561-2015.pdf (Paper omkring lua i SAS)
https://www.youtube.com/watch?v=7G5Mb--iTc8 (Youtube video med SAS' egen Chris Hemedinger, der interviewer en af SAS' egne udviklere om lua)
https://support.sas.com/documentation/cdl/en/proc/68954/HTML/default/viewer.htm#n1w8nl91tml15dn1mw9p... (SAS dokumentation om proc lua)