1 / 22

recursie met de datastep

recursie met de datastep. jeroen j van beele 1(1) april 2005. kun je een programma schrijven dat zichzelf als output heeft? of: in welke taal kun je dat doen? of: waar moet een taal aan voldoen om zo'n programma in te kunnen schrijven?.

cindy
Download Presentation

recursie met de datastep

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. recursie met de datastep jeroen j van beele 1(1) april 2005

  2. kun je een programma schrijven dat zichzelf als output heeft? • of: in welke taal kun je dat doen? • of: waar moet een taal aan voldoen om zo'n programma in te kunnen schrijven?

  3. dat kun je leuk combineren met recursie: een programma dat zichzelf schrijft en vervolgens ook inleest en uitvoert • dan moeten we de omgeving van die programmeertaal een beetje schetsen: • denk aan de sas-program editor van waaruit je schrijft naar en leest van externe bestanden

  4. het kan bijvoorbeeld als de taal beschikt over de volgende twee opdrachten: • lees(<bestand>) • schrijf*(argument,<bestand>) waar schrijf* is: • herhaalt zichzelf • schrijft het argument naar <bestand> • het programma zou er dan alsvolgt uitzien: • schrijf*(lees(pgm),pgm)) • lees(pgm)

  5. kan dit in de datastep? • dus: kun je een datastep schrijven die zichzelf schrijft? en dan natuurlijk %includen

  6. filename rc000000 catalog "work.recurse.rc00000.source"; • data _null_; • file rc000000; • /* wat moet hier komen te staan? */ • run; • %include rc000000;

  7. weten jullie nog andere richtingen? • het is een beetje ook de keuze die ik maak in de vraagstelling: • programma schrijft zichzelf, helemaal in de datastep, dus geen scl of macro's

  8. filename rc000000 catalog "work.recurse.rc00000.source"; • data _null_; • file rc000000; • put "filename rc000000 catalog ""work.recurse.rc00000.source"";"; • put "data _null_;"; • put "file recurs;"; • put "run;"; • put "%include rc000000;"; • run; • %include rc000000;

  9. dit houdt op, 2 ideeen • put(quote) • do-loop • (3e toevalstreffer) schrijf in code eerst de stap die het einde wegschrijft en daarna het begin • ik vind het moeilijk om uit te leggen waarom dit werkt:

  10. het conceptuele schema is alsvolgt: • begincode; • put "begincode;"; • deze code heeft als resultaat: • begincode; • maar • put "begincode;"; • mist in de uitvoer • en put "begincode;"; kun je niet aan het argument begincode toevoegen want dan zit je conceptueel in een loop

  11. wat wel kan is put aan begincode toevoegen • begincode; • put "begincode; put"; • dan is het resultaat: • begincode; • put • merk op dat dit resultaat het argument is van de put

  12. als we nu alleen maar het argument herhalen hebben we de hele code gereproduceerd: • begincode; • regel="begincode; regel="; • put regel; • put quote(regel); • resultaat: • 1e put schrijft regel weg, resultaat: • begincode; • regel= • 2e put voert quote(regel) uit, resultaat: • "begincode; regel=" • samen is het resultaat • begincode; • regel="begincode; regel=" • merk op dat de ; aan het einde van regel 2 mist!

  13. dan hebben we die twee putstatements natuurlijk nog, maar die zijn aanzienlijk minder ingewikkeld dan die hele begincode • en toen kwam de grote truc (het omdraaien van de schrijfvolgorde in de code) die ik bij toeval ontdekte en niet kan uitleggen (een beetje kan ik hem wel uitleggen: de clou is dat je door het verwisselen niet in je eigen staart bijt):

  14. filename rc000000 catalog "work.recurse.rc00000.source"; • data _null_; • file rc000000; • do level=0 to 1; • if level then do; • regel="<eind>"; • put regel; • end; • else do; • regel="<begin>"; • put regel; • regel=quote(trim(regel)); • put regel; • end; • end; • run; • %include rc000000;

  15. begin loopt van het begin tot aan de beginquote van "<begin>" • eind loopt van na de eindquote van "<begin>" tot het eind • LET OP: EERST moet je <eind> substitueren en DAARNA <begin> • de truc zit hem in de laatste (geschreven) put (die als middelste uitgevoerd wordt): • als de datastep runt schrijft de middelste (geschreven) put eerst <begin> naar rc000000 • daarna schrijft de laatste put <begin> nog eens op maar dan als argument van de regel= zodat de code t/m • regel="<begin>"; • klaar is, op de ; na! • die ; stoppen we dan aan het begin van <eind> • en dan zie je ook waarom de omwisseltruc werkt, want met die truc kunnen we <eind> in zijn geheel in <begin> opnemen (als je EERST <eind> substitueert en DAARNA <begin>)

  16. dan kom je in een oneindige loop, • hoe kom je daar weer uit? • de antwoorden vind je hieronder:

  17. filename rc000000 catalog "work.recurse.rc00000.source" lrecl=1000; • data _null_; • length regel $1000; • include_level=1; • put include_level=; • if include_level=30 then put "stop"; • else do put_level=0 to 1; • if put_level then do; • regel="<eind>"; • put regel; • end; • else do; • file rc000000; • regel="<begin>"; • put regel; • regel="<midden>"; • put regel; • regel=quote(trim(regel)); • put regel; • end; • end; • run; • %include rc000000;

  18. hoe diep kan sas includes nesten? • om deze vraag te beantwoorden moet je de 30 aanpassen in de code (of documentatie raadplegen natuurlijk) • de eerste twee 30's doen niet terzake, die kun je weghalen (zie hieronder), de laatste is degene waar het om gaat • die heb ik vervangen door een macrovariabele, dus:

  19. options noquotelenmax nosource nosource2 nonotes; • %let diepte=30; • filename rc000000 catalog "work.recurse.rc00000.source" lrecl=1000; • data _null_; • length regel $1000; • include_level=1; • put include_level=; • do put_level=0 to 1; • if put_level then do; • regel="; • put regel; • regel=quote(trim(regel)); • put regel; • end; • end; • run; • %include rc"||put(include_level,z6.)||";"; • put regel; • end; • else do; • file rc000000; • regel=" • filename rc"||put(include_level,z6.)||" catalog ""work.recurse.rc"||put(include_level,z6.)||".source"" lrecl=1000;

  20. data _null_; • length regel $1000; • include_level="||put(include_level+1,6.)||"; • put include_level=; • do put_level=0 to 1; • if put_level then do; • regel=""; • put regel; • regel=quote(trim(regel)); • put regel; • end; • end; • run; • %include rc""||put(include_level,z6.)||"";""; • put regel; • end; • else do; • file rc"||put(include_level,z6.)||";"; • put regel; • regel=" • regel="" • filename rc""||put(include_level,z6.)||"" catalog """"work.recurse.rc""||put(include_level,z6.)||"".source"""" lrecl=1000;

  21. data _null_; • length regel $1000; • include_level=""||put(include_level+1,6.)||""; • put include_level=; • if include_level=&diepte then put """"stop""""; • else do put_level=0 to 1; • if put_level then do; • regel=""""; • put regel; • regel=quote(trim(regel)); • put regel; • end; • end; • run; • %include rc""""||put(include_level,z6.)||"""";""""; • put regel; • end; • else do; • file rc""||put(include_level,z6.)||"";""; • put regel; • regel="; • put regel; • regel=quote(trim(regel)); • put regel; • end; • end; • run; • %include rc000000;

  22. options noquotelenmax nosource nosource2 nonotes; • %let diepte=30; • filename rc000000 catalog "work.recurse.rc00000.source" lrecl=1000; • data _null_; • length regel $1000; • include_level=1; • put include_level=; • do put_level=0 to 1; • if put_level then do; • regel="; • put regel; • regel=quote(trim(regel)); • put regel; • end; • end; • run; • %include rc"||put(include_level,z6.)||";"; • put regel; • end; • else do; • file rc000000; • regel=" • filename rc"||put(include_level,z6.)||" catalog ""work.recurse.rc"||put(include_level,z6.)||".source"" lrecl=1000; • data _null_; • length regel $1000; • include_level="||put(include_level+1,6.)||"; • put include_level=; • do put_level=0 to 1; • if put_level then do; • regel=""; • put regel; • regel=quote(trim(regel)); • put regel; • end; • end; • run; • %include rc""||put(include_level,z6.)||"";""; • put regel; • end; • else do; • file rc"||put(include_level,z6.)||";"; • put regel; • regel=" • regel="" • filename rc""||put(include_level,z6.)||"" catalog """"work.recurse.rc""||put(include_level,z6.)||"".source"""" lrecl=1000; • data _null_; • length regel $1000; • include_level=""||put(include_level+1,6.)||""; • put include_level=; • if include_level=&diepte then put """"stop""""; • else do put_level=0 to 1; • if put_level then do; • regel=""""; • put regel; • regel=quote(trim(regel)); • put regel; • end; • end; • run; • %include rc""""||put(include_level,z6.)||"""";""""; • put regel; • end; • else do; • file rc""||put(include_level,z6.)||"";""; • put regel; • regel="; • put regel; • regel=quote(trim(regel)); • put regel; • end; • end; • run; • %include rc000000; • options noquotelenmax nosource nosource2 nonotes; • %let diepte=30; • filename rc000000 catalog "work.recurse.rc00000.source" lrecl=1000; • data _null_; • length regel $1000; • include_level=1; • put include_level=; • do put_level=0 to 1; • if put_level then do; • regel="; • put regel; • regel=quote(trim(regel)); • put regel; • end; • end; • run; • %include rc"||put(include_level,z6.)||";"; • put regel; • end; • else do; • file rc000000; • regel=" • filename rc"||put(include_level,z6.)||" catalog ""work.recurse.rc"||put(include_level,z6.)||".source"" lrecl=1000; • data _null_; • length regel $1000; • include_level="||put(include_level+1,6.)||"; • put include_level=; • do put_level=0 to 1; • if put_level then do; • regel=""; • put regel; • regel=quote(trim(regel)); • put regel; • end; • end; • run; • %include rc""||put(include_level,z6.)||"";""; • put regel; • end; • else do; • file rc"||put(include_level,z6.)||";"; • put regel; • regel=" • regel="" • filename rc""||put(include_level,z6.)||"" catalog """"work.recurse.rc""||put(include_level,z6.)||"".source"""" lrecl=1000; • data _null_; • length regel $1000; • include_level=""||put(include_level+1,6.)||""; • put include_level=; • if include_level=&diepte then put """"stop""""; • else do put_level=0 to 1; • if put_level then do; • regel=""""; • put regel; • regel=quote(trim(regel)); • put regel; • end; • end; • run; • %include rc""""||put(include_level,z6.)||"""";""""; • put regel; • end; • else do; • file rc""||put(include_level,z6.)||"";""; • put regel; • regel="; • put regel; • regel=quote(trim(regel)); • put regel; • end; • end; • run; • %include rc000000;

More Related