בית פורומים למתכנתים שבינינו

שפת SCHEME

שלום אורח. באפשרותך להתחבר או להירשם
הצג 15 הודעות בעמוד הוסף לדף האישי  דווח למנהל שלח לחבר
נשלח ב-27/7/2011 17:33 לינק ישיר 
פרק 16 - Shell s

לעיתים נוח פשוט לכתוב מה אנו רוצים שייעשה לתוך קובץ או ולבצע אותו כאילו זו פקודת shell אחרת הקוראת למערכת ההפעלה. הממשק עבור תוכניות גדולות לעיתים מסופק במבנה של , ומשתמשים לעיתים בונים s משלהם או מתאימים s קיימים לצורכיהם המיוחדים. יש האומרים כי ing היא משימת התכנות השכיחה ביותר. עבור משתמשים רבים זה התכנות היחיד שיעשו אי פעם.

מערכות הפעלה כמו
Unix ו-Dos (ממשק ה-command-line מסופק ב-Windows) מספקות מנגנון כזה של s, אך שפת ה-ing בכל אחד מהם אינה מפותחת כ"כ. לעיתים הוא רק רצף או איחוד של כמה פקודות שהיינו יכולים להקיש בהינתן ה-prompt של ה-Shell. הדבר חוסך מהמשתמש להקיש כל אחת מפקודות ה-Shell בנפרד כל פעם שנזקקים לאותה סדרת פקודות. 
כמה משפות ה-
מוסיפות מעט אפשרויות תכנות נוספות בתבניות של התניות או לולאות, אך בכך מסתכם העניין. זה מספיק עבור משימות קטנות יחסית, אך כשה- גדל ונעשה תובעני יותר, כפי ש-s צריכים להיות, מורגש הצורך בשפת תכנות בשלה יותר. Scheme עם ממשקים הולמים למערכת ההפעלה מאפשרת יצירת s בקלות ובאופן שניתן יהיה לתחזק.

בפרק זה יתואר איך לכתוב
s ב-Scheme. מאחר ויש וריאציות רבות בגרסאות Scheme לגבי ביצוע העניין, אנו נתרכז בגרסת MzScheme, ונתעד בנספח A את השינויים שיידרשו כדי להתאים לגרסאות האחרות. כמו כן נתרכז כעת במערכת ההפעלה Unix, נספח B יעסוק במקבילה DOS.

16.1 חוזרים ל-!
Hello, World

 

כעת ניצור ב-Scheme האומר שלום לעולם. אמירת שלום, כמובן, אינה בעיית ing תובענית עבור שפות ה-ing המסורתיות. בכל אופן, ההבנה איך לתעתק זאת ל-Scheme תפתח עבורנו את המסלול ל-s דורשי מאמץ נוסף. ראשית, hello- שגרתי ב-Unix הוא קובץ בעל התוכן הבא:

 

echo Hello, World!

 

נעשה כאן שימוש בפקודת ה-Shell echo. ה- יכול להיקרא hello ותתכן בו פעולת ההרצה ע"י שנרשום:

 

chmod +x hello

 

ונמקם אותו באחת הספריות המוזכרות במשתנה הסביבתי PATH. לאחר מכן, כל פעם שנקיש: 
hello ב-prompt של ה-Shell, נקבל מיד את ברכת השלום.
ה-
hello- ייתן בדיוק את אותו הפלט כמו תכנית scheme רגילה (התכנית בפרק 1), אך אנו צריכים משהו בקובץ שיידע את מערכת ההפעלה שצריך להבין את הפקודות בקובץ כמו ב-Scheme, ולא כמו ה-default של שפת ה-. קובץ ה- ,שנקרא גם הוא hello ,נראה כך:

 

":"; exec mzscheme -r $0 "$@"

 

(display "Hello, World!")

(newline))

 

כל דבר שבא אחרי השורה הראשונה הינו scheme תקני. בכל אופן, השורה הראשונה היא "הקסם" שהופכת זאת ל-. כשהמשתמש מקיש hello ב-prompt של ה-Unix, Unix ייקרא את הקובץ כ- רגיל. הדבר הראשון שהוא רואה זה: ":", שזו no-op עבור ה-Shell. ה-; הוא המפריד בין פקודות ב-shell. פקודת ה-Shell הבאה היא exec .exec אומרת ל-Unix לנטוש את ה- הנוכחי ולהריץ במקומו את

 

mzscheme -r $0 "$@"

 

כאשר הפרמטר $0 יוחלף בשם ה-, והפרמטר "@$" יוחלף ברשימת הארגומנטים שתינתן ע"י המשתמש ל-. (במקרה שלנו, אין כאלו ארגומנטים).
למעשה, מה שעשינו עכשיו היה הפיכת פקודת ה-
shell hello לפקודת shell אחרת. כלומר,

 

mzscheme -r /whereveritis/hello

 

כאשר

 

/whereveritis/hello

 

הוא ה-pathname של hello.
mzscheme קוראת ל-MzScheme להתבצע. האופציה -r אומרת לטעון את הארגומנט העוקב כקובץ Scheme אחרי ששאר הארגומטים נכנסו לוקטור הנקרא argv. (במקרה זה argv יהיה וקטור ריק).
כך, ה-
ירוץ כקובץ Scheme, ולתבניות Scheme בקובץ תהיה גישה לארגומנטים המקוריים של ה- דרך הוקטור argv.
כעת, על
Scheme לטפל בשורה הראשונה ב-, שכפי שכבר ראינו, אכן מסודרת היטב עבור ה-Shell המסורתי. 
ה-":" היא מחרוזת ההערכה העצמית ולכן אינה מזיקה.
ה-";" מסמן הערה ב-
Scheme וכמו כן מתעלמים מ-...exec
שאר הקובץ הוא
Scheme תקני, והביטויים בו מוערכים בצורה סדרתית. כאשר תסתיים ההערכה של כולם, Scheme תצא החוצה.
לסיכום, הקלדת
hello ב-shell prompt תפיק !Hello, World ותחזיר אותנו ל-Shell prompt.

16.2
עם ארגומנטים

 

ב-scheme משתמש במשתנה argv כדי לפנות לארגומנטים שלו. 
לדוגמא, ה-
הבא מציג את כל הארגומנטים שלו, כל אחד בשורה:

 

":"; exec mzscheme -r $0 "$@"

 

;Put in argv-count the number of arguments supplied

 

(define argv-count (vector-length argv))

 

    (let loop ((i 0))

         (unless (>= i argv-count)

         (display (vector-ref argv i))

         (newline)

         (loop (+ i 1))))

 

בואו ונקרא ל- echoall .קריאה ל-echoall 1 2 3 תציג:
1
2
3
שים לב כי שם ה-
("echoall") לא נכלל בוקטור הארגומנטים. 

16.3 דוגמא

בואו נטפל כעת בבעיה רצינית יותר. אנו צריכים להעביר קבצים ממחשב אחד לשני והשיטה היחידה בה אנו צריכים להשתמש היא שימוש בדיסקט 3.5" כאמצעי העברה. אנו צריכים split4floppy שיפצל קבצים גדולים מ-1.44 מליון בתים לנתחים שהם floppy-sized. ה-split4floppy הוא כדלקמן:

 

":";exec mzscheme -r $0 "$@"

 

;floppy-size = number of bytes that will comfortably fit on a

;              3.5" floppy

 

(define floppy-size 1440000)

 

;split splits the bigfile f into the smaller, floppy-sized

;subfiles, viz, subfile-prefix.1, subfile-prefix.2, etc.

 

(define split

 (lambda (f subfile-prefix)

    (call-with-input-file f

      (lambda (i)

        (let loop ((n 1))

          (if (copy-floppy-size-chunk i subfile-prefix n)

              (loop (+ n 1))))))))

 

;copy-to-floppy-sized-subfile copies the next 1.44 million

;bytes (if there are less than that many bytes left, it

;copies all of them) from the big file to the nth

;subfile. Returns true if there are bytes left over,

;otherwise returns false.

 

(define copy-to-floppy-sized-subfile

 (lambda (i subfile-prefix n)

    (let ((nth-subfile (string-append subfile-prefix "."

                                      (number->string n))))

      (if (file-exists? nth-subfile) (delete-file nth-subfile))

      (call-with-output-file nth-subfile

        (lambda (o)

          (let loop ((k 1))

            (let ((c (read-char i)))

              (cond ((eof-object? c) #f)

                    (else

                     (write-char c o)

                     (if (< k floppy-size)

                         (loop (+ k 1))

                         #t))))))))))

 

;bigfile = 's first arg

;        = the file that needs splitting

 

(define bigfile (vector-ref argv 0))

 

;subfile-prefix = 's second arg

;               = the basename of the subfiles

 

(define subfile-prefix (vector-ref argv 1))

 

;Call split, making subfile-prefix.{1,2,3,...} from

;bigfile

 

(split bigfile subfile-prefix)

 

הקריאה ל-split4floppy מתבצעת כך:

 

split4floppy largefile chuck

 

כך נפצל את largefile לתתי קבצים chunk.2 ,chunk.1 וכו' כך שכל subfile יהיה בגודל floppy.
אחרי העברת
chunk.i למחשב היעד, הקובץ largefile יכול לחזור לקדמותו ע"י קשירת ה-chunk.i ביחד. דבר זה יכול להיעשות ב-Unix ע"י :

 

cat chunk.1 chunk.2 ... > largefile

 

וב-DOS ע"י:

 

copy /b chunk.1+chunk.2+... largefile

 



תוקן על ידי אנוני_מוס ב- 28/07/2011 09:00:52




דדווח על תוכן פוגעני

סמל אישי
מנותק
נשלח ב-28/7/2011 09:02 לינק ישיר 

אני מבקשת לא להוסיף לאשכול זה תגובות נוספות. אם יש הצעות ייעול - אשמח לקבל בפרטי.



דדווח על תוכן פוגעני

סמל אישי
מנותק
   
בית > פורומים > אינטרנט ומחשבים > למתכנתים שבינינו > שפת SCHEME
מנהל לחץ כאן לנעילת האשכול
הוסף לעמוד האישי  דווח למנהל שלח לחבר
לדף הקודם 1 2 סך הכל 2 דפים.

bholext