Ceylon (שפת תכנות)

Ceylon היא שפה מונחת עצמים, חזקה, עם טיפוסי נתונים סטאטיים עם דגש על קיבוע אובייקטים, אשר נוצרה על ידי Red Hat. תוכניות Ceylon רצות על המכונה הווירטואלית של Java (JVM) וניתן להדר אותן ל-JavaScript.

עיצוב השפה מתמקד בקריאות קוד המקור, יכולת חיזוי, מודולריות ומידת תכנות.

תכונות חשובות של Ceylon כוללות:
 מנגנון טיפוסים המחייב בטיחות null וקיום של מופעי list בזמן הקימפול (הידור).
 תחביר וסמנטיקה קבועים, הימנעות ממקרים מיוחדים ומבנים מוגדרים פרימיטיביים לטובת תחביר מסוכר.
 תמיכה בתכנות גנריות ובמטא-תכנות, עם גנריות מאומתות.
 מודולריות מובנית בשפה, מבוססת על מודולי JBoss, ניתנת פעולה הדדית עם OSGi ו-Maven.
 כלים רבי עוצמה, כולל IDE מבוסס Eclipse.

השם "ציילון" הוא התייחסות מרומזת לג'אווה, בכך שג'אווה וסרי לנקה, שנקראו בעבר ציילון, הם איים הידועים בגידול ויצוא של קפה ותה מדרום להודו.

באוגוסט 2017 נתרמה Ceylon לקרן Eclipse.

מאפייני שפה 
Ceylon מושפע מאוד מהתחביר של ג'אווה, אך מוסיף תכונות חדשות רבות.

טיפוסים (TYPE) בשפה 
אחד ההיבטים החדשניים ביותר של Ceylon בהשוואה לג'אווה הוא מערכת הטיפוסים שלה. Ceylon וויתרה על הטיפוסים הפרימיטיביים ו'עיטופם' (wrapping, boxing) כפי שנעשה בג'אווה', לטובת מערכת טיפוסים המורכבת כולה מאובייקטים. אמנם הדבר עלול לגרום למצב של תקורת יתר של המערכת במצבים מסוימים (טיפוס פרימיטבי זול מבחינת זיכרון יחסית לאובייקט), אך זה הופך את מערכת הטיפוסים לאחידה יותר.

טיפוסים מאוחדים

Ceylon מאפשרת איחוד טיפוסים, באופן דומה ל- TypeScript, Whiley ו- Flow.

יש שתי אפשרויות של איחוד; Union כלומר איחוד וכן Intersection כלומר חיתוך.

טיפוס איחוד Union

טיפוס המאוחד על ידי האופרטור | (או), כתוב A|B, מאפשר למשתנה להיות יותר מסוג אחד. הדוגמה הבאה מציגה פונקציה של Ceylon שעשויה לקבל מספר שלם או מחרוזת למשתנה המאוחד input: shared void integerOrString(Integer|String input) {
 if (is Integer input) {
 print("Got the integer ``input``");
 } else {
 print("Got the string '``input``'");
 }
}טיפוס חיתוך Intersection 

טיפוס המאוחד בחיתוך על ידי האופרטור & (וגם) ונכתב A&B, הוא הבסיס התאורטי המאפשר את flow-sensitive typing כלומר למעשה את ההקלדה הדינאמית, בה אין עוד חובה להגדיר במדויק את טיפוס הנתון אלא הוא יכול להיות מחושב על ידי הקומפיילר מהמשך התנהגותו (בכך למעשה השפה הסטטית מאפשרת התנהגות דינאמית) דוגמה יותר מפורטת לעיקרון הזה כאן shared void integerOrString(Integer|String input) {
 Integer added = input + 6; // illegal; the + operator is not defined on Integer|String

 if (is Integer input) {
 Integer added = input + 6; // legal; input is now known to be an Integer
 print("Got the integer ``input``");
 } else {
 print("Got the string '``input``'");
 }
} התנאי is Integer input מצמצם את סוג input להיות Integer|String > & Integer>, אשר מחושב על ידי חוק הפילוג כ Integer & Integer | String & Integer, אבל מכיוון ש String ו Integer טיפוסים שלא ניתן לחבר ביניהם, הפרוק שקול ל: Integer & Integer | Nothing

( Nothing הוא טיפוס ריק בסיסי), כל הנ"ל הופך בסופו של דבר ל Integer בלבד שכעת ניתן לבצע עליו את האופרטור + או כל אופרטור אחר המוגדר עבור Integer בלבד.

בטיחות עבור ערכי Null 
סוגי האיחוד והחיתוך משמשים למתן ביטחון לשימוש ב Null . הטיפוס העליון של היררכית הטיפוסים של Ceylon הוא הקלאסAnything, שיש לו שתי תת-קבוצות: Object, מחלקת העל של כל הקלאסים הרגילים וכל הממשקים, ו Null, עם המופע היחיד null.

מכיוון שObject ו- Null הם טיפוסים שלא ניתן לאחד אותם בצורה רגילה, טיפוסים רגילים כמו Integer או <List < String אינם מקבלים ערכי null;

אולם ניתן ליצור טיפוס אפיס שהוא האיחוד Integer|Null, או בכתיב מקוצר Integer? ובכך לפתור הבעיה.

ניתן גם להשתמש בטיפוסי חיתוך כדי ליצור טיפוס שאינו אופציונלי מטיפוס שמאפשר אופציונליות, כגון פרמטר לטיפוס. לדוגמה, החתימה של פונקציה שמסירה null אלמנטים מזרם ערכים יכולה להיות: Iterable<Element&Object> removeNulls<Element>(Iterable<Element> stream); כאשר נקרא removeNulls עם זרם של אלמנטים Integer|Null, התוצאה תהיה זרם של < Integer|Null > & Object>, המפושט ל- Integer .

פונקציות 
בדומה לשפות מודרניות רבות, Ceylon תומך בפונקציות מהשורה הראשונה ופונקציות מסדר גבוה, כולל פונקציות כטיפוס ופונקציות אנונימיות. // A top-level higher-order function using block syntax (not associated with any user-created classes)
String process(String text, String transformString(String toChange)) {
 return transformString(text);
}

// A top-level function calling String.reverse in expression form.
String reverse(String text) => text.reversed;

// A function reference to String.reversed but mostly equivalent to the function above.
String(String) reverseFunctionReference = String.reversed;

// An example where the top-level function above is provided as an argument to the higher-order function above
String reversed1 = process("one", reverse);

// Any example where an anonymous function - (text) => text+text - is provided to the higher-order function above.
String reversed2 = process("one", (text) => text+text);

Enumerated types - טיפוסים ספירים- ברי מניה 
בדומה לג'אווה ולשפות רבות אחרות, ועם מנגנון דומה לטיפוסים אלגבריים, Ceylon תומך בטיפוסים ספירים, הידועים גם בשם enums. זה מיושם בCeylon על ידי דפוס של הגבלת המופעים של class מופשט (abstract ) בהצהרה המגבילה את האובייקטים הנוצרים של ה class (במקרה זה, מקרים של סינגלטון). דרך נוספת ליישום דפוס זה היא עם תכונת הבנאי החדשה בCeylon 1.2, שם מיישמים את האובייקטים כהצהרות בנאי שונות. // Traditional syntax for enumerated type, in this case, limiting the instances to three objects(for this purpose: Singletons)
abstract class Vehicle(shared String name) of plane | train | automobile {}

object plane extends Vehicle("plane") {}
object train extends Vehicle("train") {}
object automobile extends Vehicle("automobile") {}
// Compile error: type is not a subtype of any case of enumerated supertype: 'boat' inherits 'Vehicle'
//object boat extends Vehicle("boat") {}

// New (as of Ceylon 1.2.0) constructor-based syntax
class Vehicle of plane | train | automobile {
 String name;

 abstract new named(String pName) {
 name = pName;
 }

 shared new plane extends named("plane") {}
 shared new train extends named("train") {}
 shared new automobile extends named("automobile") {}
 // Compile error: value constructor does not occur in of clause of non-abstract enumerated class: 'boat' is not listed in the of clause of 'Vehicle'
 //shared new boat extends named("boat") {}
}

הסקה עצמית של הטיפוס 
כאמור Ceylon היא שפה 'חזקה' (במשמעות שלא עושה cast בעצמה ללא הוראה מפורשת) ו'סטטית' (כלומר לכל אובייקט צריך להיות מוצהר מה הטיפוס שלו), אך בכל זאת תומכת בהסקת הטיפוס (כלומר הצהרת הטיפוס יכולה להיות על ידי הקומפיילר ולא המתכנת). מילת המפתח value משמשת כדי להסיק את סוג המשתנה, ומילת המפתח function משמשת כדי להסיק את סוג הפונקציה. שתי ההגדרות הבאות שוות זו לזו: Integer i = 3;
value i = 3;

Integer add(Integer i1, Integer i2) {
 return i1 + i2;
}
function add(Integer i1, Integer i2) {
 return i1 + i2;
} עם זאת, ברור שהצהרה כזו תעבוד רק בפונקציה שמחשבת לבד את הערך המוחזר ללא קריאה לפונקציות אחרות.

נקודת כניסה עם שמות 
כברירת מחדל המתנע ( ceylon run ) מפעיל את פונקציית הריצה המשותפת של מודול- shared run(): /* The classic Hello World program */
shared void run() {
 print("Hello, World!");
} אבל כל פונקציה משותפת אחרת ללא פרמטרים יכולה לשמש כקריאה ראשית לתוכנית עם הפרמטר --run, כמו זה:

ceylon run --compile=force --run hello default

גרסאות 
גרסאות של Ceylon ששוחררו: 
 M1 0.1 "Newton" (Dec 20 2011)
 M2 0.2 "Minitel" (Mar 2 2012)
 M3 0.3 "V2000" (Jun 21 2012)
 M3.1 0.3.1 "V2000" (Jul 6 2012)
 M4 0.4 "Analytical Engine" (Oct 29 2012)
 M5 0.5 "Nesa Pong" (Mar 13 2013)
 M6 0.6 "Virtual Boy" (Sep 23 2013)
 1.0 beta "Virtual Boy" (Sep 24 2013)
 1.0.0 "No More Mr Nice Guy" (Nov 13 2013)
 1.1.0 "Ultimate Ship The Second" (Oct 09 2014)
 1.2.0 "A Series of Unlikely Explanations" (Oct 28 2015)
 1.2.1 "Irregular Apocalypse" (Feb 11 2016)
 1.2.2 "Charming But Irrational" (Mar 11 2016)
 1.3.0 "Total Internal Reflection" (Sep 19 2016)
 1.3.1 "Now We Try It My Way" (Nov 22 2016)
 1.3.2 "Smile Tolerantly" (Mar 02 2017)
 1.3.3 "Contents May Differ" (Aug 21 2017)

רישיון 
כל חלקי Ceylon זמינים כתוכנה חופשית, לרוב רישיון Apache. חלק מקוד המקור מורשה תחת LGPL.

קישורים חיצוניים

הערות שוליים 

תוכנות שהושקו ב-2011