Common Lisp – הבדלי גרסאות
תוכן שנמחק תוכן שנוסף
Matanyabot (שיחה | תרומות) מ בוט החלפות: מסוי\1, ,, לעיתים |
דויד פון תמר (שיחה | תרומות) הגהה, ניסוח, ויקיזציה, עיצוב, דקדוק עברית, תיקון פיסוק, הסרת שורות ריקות ורווחים מיותרים, שימוש במונחים בעברית ומונחים המקובלים במדעי המחשב. הסרת תוכן מבוא כללי ממדעי המחשב והוספת קישורים לערכים המורחבים באותם נושאים. סידור קטעי הקוד. |
||
שורה 13:
}}
== היסטוריה ==
Common Lisp פותחה להיות ניב [[תקן|מתוקנן]] וטוב יותר של [[Maclisp|MacLisp]]. בתחילת שנות ה־80 כבר היו מספר קבוצות שעבדו על יורשים מגוונים ל־MacLisp כגון [[Lisp Machine Lisp]], [[Spice Lisp]], [[NIL]] ו־[[S-1 Lisp]]. מטרתה המרכזית של Common Lisp הייתה לאחד, לתקנן ולהרחיב את התכונות של כל אחד מהניבים האלה בשפה אחת. Common Lisp כשלעצמה אינה [[מימוש|יישום]] של [[Lisp]] אלא אפיון בלבד. קיימים מגוון יישומים ל־Common Lisp, ביניהם יישומים קנייניים, חינמיים וב[[קוד פתוח]].
== מאפיינים ==
Common Lisp היא שפה [[שפת תכנות רב־תכליתית|רב־תכליתית]] שמשלבת מספר [[פרדיגמת תכנות|פרדיגמות]] כגון תכנות [[תכנות פרוצדורלי|פרוצדורלי]], [[תכנות פונקציונלי|פונקציונלי]], ו[[תכנות מונחה-עצמים|מונחה־עצמים]]. מהיותה שפה [[תכנון דינמי|דינמית]], היא מאפשרת [[פיתוח איטרטיבי והדרגתי]] נוח יותר שנעשה תוך כדי [[זמן ריצה (תוכנה)|זמן הריצה]] של ה[[תוכנה]] מבלי להפריע לה.
Common Lisp גם מאפשרת ביאור טיפוסים והמרתם עבור שלבי אופטימיזציה מתקדמים בזמן הפיתוח כדי לאפשר למהדר לחולל קוד יעיל יותר בביצועים. בנוסף ניתן להצהיר בעבור כל פונקציה או מרכיב בקוד בנפרד באיזה רמה של [[Type safety|תאימות טיפוסית]] רוצים להשתמש כדי למנוע אי־התאמה בין טיפוסים שונים.
שורה 23 ⟵ 27:
Common Lisp תומכת ב[[תאימות לאחור]] עד רמה מסוימת עבור [[Maclisp]] ו־[[Lisp]] המקורית של [[ג'ון מקארתי]], וזה מאפשר לשפה לתמוך בקוד מיושן מאמצע המאה ה־20.
== תחביר ==
=== ביטויים סימבולים (
'''ביטויים סימבולים'''
לדוגמה : <code>(3 2 5 +)</code> יחבר את 5, 3,
ביטויים סימבולים יכולים להופיע באופן מקונן, כלומר, בתוך ביטויים סימבולים אחרים. לדוגמה
(print (+ 5 2 3
</syntaxhighlight>קוד זה
=== פעולות חשבון ===
ארבע פעולות ה[[אריתמטיקה|חשבון]] המרכזיות ב־Common Lisp, ובניבי Lisp בכלל, הם חיבור <code>+</code> , חיסור <code>-</code>, כפל <code>*</code>, וחילוק <code>/</code>. אמנם פעולות חשבון בסיסיות אלה קיימות בכלל שפות התכנות, במשפחת Lisp צורת הכתיבה שלהם היא תחילית (דומה ל[[כתיב פולני]] במתמטיקה) עם מספר אופרנדים {{אנג|arity}} מרובה (מספר האיברים המשתתפים בפעולה) בניגוד לכתיב המסורתי במתמטיקה לפיו סימני פעולה מסומנים תמיד באופן בינארי בין שני אופרנדים בלבד המשתתפים בפעולה. הכתיב התחילי משותף גם לפונקציות כשהאיברים בביטוי הם הפרמטרים בהתאמה. בפעולות מובנות רבות אין מגבלה למספר האופרנדים. הפעולות חיבור, חיסור, כפל, וחילוק אינן פעולות בינאריות ב־Lisp. לדוגמה, החישוב <math>2 * 3 + 7 - 6</math> נכתב ב־Lisp כך,<syntaxhighlight lang="common-lisp">
( - (+ (* 2 3) 7) 6 )
</syntaxhighlight>
=== פעולות השוואה ===
פעולות השוואה ב־Lisp, כמו במתמטיקה בדידה, ובמדעי המחשב בכלל, משוות בין שני ביטויים או יותר ומחזירות ערך בוליאני (אמת או שקר). '''אמת''' אם הביטוי מתקיים, ו'''שקר''' אם הביטוי אינו מתקיים. באופן מקביל, בשפות תכנות רבות משתמשים בפעולת השוואה בינארית (בדרך כלל מסומנת כ־<code>==</code>) על מנת לבדוק האם שני ביטויים שווים זה לזה. מפני שהתחביר בניבי Lisp משתמש בכתיב תחילי, אז פעולת ההשוואה (כמו עם שאר הפעולות) ממוקמת תמיד בתחילת הביטוי ויודעת להתמודד מול מספר אופרנדים מרובה (האיברים המשתתפים בהשוואה יכולים גם הם להיות ביטויי השוואה מקוננים). על מנת לבצע השוואה ב־Common Lisp ניתן להשתמש (בין היתר) בפעולה <code>=</code> בעלת arity אינסופי, וכן בפעולה הבינארית <code>eq</code>. בין הפעולות הללו ישנם הבדלים אחרים, לדוגמה,<syntaxhighlight lang="common-lisp">
(= (+ 5 5) 10 (+ 2 8) (+ 3 7 ))
-> T
שורה 51:
</syntaxhighlight>
=== פעולות <code>min</code>
הפעולות <code>max</code>
=== התניה ===
[[בקרת זרימה]] לפי תנאי נכתבת ב־Common Lisp בעזרת ההוראה <code>if</code>.
ניבי Lisp אחרים לעתים תבוצע התניה באמצעות הוראת ה־<code>cond</code> (קיצור ל "condition").
מקומם של הפרמטרים בביטוי <code>if</code> מתארים את מבנה ההוראה,<syntaxhighlight lang="common-lisp">
(if (comparative-expression-either-true-or-false)
(expression-to-be-evaluated-when-true)
(expression-to-be-evaluated-when-false))
</syntaxhighlight>לדוגמה, קטע הקוד הבא ידפיס האם <math>6+4</math> שווה ל <math>3+7
</math>,<syntaxhighlight lang="common-lisp">
(if (eq (+ 3 7) (+ 6
(print "They are equal.")
(print "They are not equal."))
</syntaxhighlight>
=== רשימות ===
[[קובץ:Singly-linked-list.svg|ממוזער|304x304 פיקסלים|[[רשימה מקושרת]] (linked list) באופן חד־סטרי.]]
אחד ממבני הנתונים הנפוצים והשימושיים ביותר הוא [[רשימה מקושרת]] - אוסף של ערכים. ב־Common Lisp, ובניבי Lisp נוספים, ניתן ליצור רשימה מקושרת בשתי דרכים עיקריות, באמצעות <code>cons</code> ובאמצעות <code>list</code>.
==== '''שימוש ב[[מילה שמורה|מילה השמורה]]''' <code>cons</code> ====
בשיטה זו, מגדירים את הרשימה המקושרת באופן [[רקורסיה|רקורסיבי]]. <code>cons</code> קולט שני אופרנדים: הערך שבחוליה, והפניה לאיבר הבא. הרשימה נגמרת כאשר ההפניה לאיבר הבא היא <code>NIL</code> - כלום (השקול לערך הבוליאני <code>false</code> בשפות תכנות אחרות).
דוגמה להגדרה של רשימה מקושרת בעלת איבר אחד,<syntaxhighlight lang="common-lisp">
(cons 5 nil)
</syntaxhighlight>רשימה בעלת
(cons 1 2)
</syntaxhighlight>או,<syntaxhighlight lang="common-lisp">
(cons 1 (cons 2 nil))
</syntaxhighlight>שתי הרשימות יכילו <code>(2 1)</code> .
שורה 92 ⟵ 87:
דוגמה להגדרת רשימה בעלת 6 איברים:<syntaxhighlight lang="common-lisp">
(cons 16 (cons 22 (cons 43 (cons 82 (cons 41 (cons 93 nil))))))
</syntaxhighlight>הרשימה תכיל <code>(
הדרך הקלה יותר ליצור רשימות מקושרות לדוגמה (list 75 21 43 'hello 'world 98)
</syntaxhighlight>
=== יצירת משתנים ===
ניתן ליצור משתנים
* '''באמצעות המאקרו''' <code>'''setq'''</code> (קיצור ל־"set quote") לדוגמה: <code>(setq *foo* 42)</code>. גם בדוגמה זו, נוצר משתנה בשם <code>*foo*</code> שערכו <code>42</code>.
* '''באמצעות המאקרו <code>setf</code>''' שיטה זו נחשבת לחדשנית יותר, משום שבנוסף ליכולותיהן של השיטות הקודמות. באמצעות <code>setf</code> ניתן לגשת ולשנות איברים ברשימה, לעומת <code>set</code> ו <code>setq</code>.
להלן השוואה בין הקוד הנדרש ליצירת רשימה זהה בשיטות השונות,<syntaxhighlight lang="common-lisp">
(set (quote foo) (list 1 2 3)) ;foo => (1 2 3)
(1 2 3)
שורה 118 ⟵ 117:
(1 2 3)
</syntaxhighlight>
=== פונקציות ===
ב־Common Lisp הגדרת פונקציות נעשית באמצעות ה[[מילה שמורה|מילה השמורה]] <code>defun</code> (קיצור ל־"define function")
מבנה הגדרת פונקציה חדשה,<syntaxhighlight lang="common-lisp">
(defun name-of-function (parameters)
"Optional documentation string."
(body-expression))
</syntaxhighlight>דוגמה לפונקצית ריבוע ([[פרבולה]]) פשוטה. הפונקציה קולטת ערך ופולטת את הערך הריבועי שלו,<syntaxhighlight lang="common-lisp">
(defun f x
(* x x))
</syntaxhighlight>דוגמה לפונקציה [[רקורסיה|רקורסיבית]] אשר [[סכום|סוכמת]] את [[מספר טבעי|המספרים הטבעיים]] מ־0 עד למספר הטבעי הנתון.
(defun
(
0
(+ (
</syntaxhighlight>על אותו עיקרון, היישום הנאיבי (ללא הטמנה) לפעולת ה[[עצרת]] הקולטת מספרים טבעיים בלבד יכתב כך,<syntaxhighlight lang="common-lisp">
(defun recursive-factorial(n)
(if (eq n 0)
1
</syntaxhighlight>וכן פונקציה רקורסיבית אשר פולטת את המספר הגדול ביותר ב[[רשימה (מבנה נתונים)|רשימה]] הנקלטת אליה,<syntaxhighlight lang="common-lisp">
(defun recursive-maximum (item lst)
(if (eq lst
(recursive-maximum (max (car lst) item) (cdr lst))))
</syntaxhighlight>
|