מבוא לפוגת אטלסיאן

1. הקדמה

פוגה היא ספריית ג'אווה מאת אטלסיאן; זה אוסף של כלי עזר התומכים תכנות פונקציונלי.

במחקר זה נתמקד ונחקור את ה- API החשובים ביותר של Fugue.

2. תחילת העבודה עם פוגה

כדי להתחיל להשתמש ב- Fugue בפרויקטים שלנו, עלינו להוסיף את התלות הבאה:

 io.atlassian.fugue fuga 4.5.1 

אנו יכולים למצוא את הגרסה האחרונה של Fugue ב- Maven Central.

3. אוֹפְּצִיָה

נתחיל את המסע שלנו בהסתכלות על אוֹפְּצִיָה כיתה שהיא התשובה של פוג java.util. אופציונלי.

כפי שאנו יכולים לנחש לפי השם, אוֹפְּצִיָה's מיכל המייצג ערך שעלול להיעדר.

במילים אחרות, an אוֹפְּצִיָה הוא או כמה ערך מסוג מסוים או אף אחד:

אפשרות ללא = Option.none (); assertFalse (none.isDefined ()); אפשרות מסוימת = Option.some ("ערך"); assertTrue (some.isDefined ()); assertEquals ("value", some.get ()); אפשרות אולי = Option.option (someInputValue);

3.1. ה מַפָּה מבצע

אחד ממשקי ה- API לתכנות פונקציונליים סטנדרטיים הוא ה- מַפָּה() שיטה המאפשרת החלת פונקציה מסופקת על יסודות בסיסיים.

השיטה מחילה את הפונקציה המסופקת על ה- אוֹפְּצִיָההערך אם הוא קיים:

אפשרות מסוימת = Option.some ("value") .map (String :: toUpperCase); assertEquals ("VALUE", some.get ());

3.2. אוֹפְּצִיָה ו ריק ערך

מלבד הבדלי שמות, אטלסיאן עשה כמה אפשרויות עיצוב עבור אוֹפְּצִיָה הנבדלים מ אופציונאלי; בואו נסתכל עליהם עכשיו.

אנחנו לא יכולים ליצור ישירות לא ריק אוֹפְּצִיָה מחזיק a ריק ערך:

Option.some (null);

האמור לעיל מביא יוצא מן הכלל.

עם זאת, אנו יכולים להשיג אחת כתוצאה משימוש ב- מַפָּה() מבצע:

אפשרות מסוימת = Option.some ("value") .map (x -> null); assertNull (some.get ());

זה לא אפשרי רק באמצעות שימוש java.util. אופציונלי.

3.3. אפשרות Iס ניתן לנידון

אוֹפְּצִיָה ניתן להתייחס לאוסף המכיל מקסימום אלמנט אחד, ולכן הגיוני שהוא מיישם את ניתן לנידון מִמְשָׁק.

זה מגביר מאוד את יכולת הפעולה ההדדית בעבודה עם אוספים / זרמים.

ועכשיו, למשל, ניתן לשרשר עם אוסף אחר:

אפשרות מסוימת = Option.some ("ערך"); מחרוזות ניתנות לנידוף = איטרבלים .concat (חלק, Arrays.asList ("a", "b", "c"));

3.4. ממיר אוֹפְּצִיָה ל זרם

מאז אוֹפְּצִיָה הוא ניתן לנידון, ניתן להמיר אותו ל- זרם גם בקלות.

לאחר המרה, ה זרם למשל יהיה אלמנט אחד בדיוק אם האפשרות קיימת, או אפס אחרת:

assertEquals (0, Option.none (). toStream (). count ()); assertEquals (1, Option.some ("value"). toStream (). count ());

3.5. java.util. אופציונלי יכולת פעולה הדדית

אם אנחנו צריכים תקן אופציונאלי אנו יכולים להשיג אותו בקלות באמצעות toOptional () שיטה:

אופציונלי אופציונלי = Option.none () .toOptional (); assertTrue (Option.fromOptional (אופציונלי) .isEmpty ());

3.6. ה אפשרויות כיתת שירות

לבסוף, Fugue מספק כמה שיטות שימוש לעבודה אוֹפְּצִיָהבשמות המתאימים אפשרויות מעמד.

הוא כולל שיטות כגון filterNone להסרת ריק אפשרויות מתוך אוסף, ו לְשַׁטֵחַ לתורing אוסף של אפשרויות לאוסף של חפצים סגורים, מסננים ריקים אפשרויות.

בנוסף, הוא כולל מספר גרסאות של מעלית שיטה שמרימה א פוּנקצִיָה לתוך פוּנקצִיָה>:

פונקציה f = (מספר שלם x) -> x> 0? x + 1: null; פוּנקצִיָה הרים = Options.lift (f); assertEquals (2, (long) lifted.apply (Option.some (1)). get ()); assertTrue (lifted.apply (Option.none ()). isEmpty ());

זה שימושי כאשר אנו רוצים להעביר פונקציה שאינה מודעת לה אוֹפְּצִיָה לשיטה כלשהי שמשתמשת בה אוֹפְּצִיָה.

שים לב, בדיוק כמו ה- מַפָּה שיטה, מעלית לא ממפה אפס ל- אף אחד:

assertEquals (null, lifted.apply (Option.some (0)). get ());

4. אוֹ לחישובים עם שתי תוצאות אפשריות

כפי שראינו, אוֹפְּצִיָה הכיתה מאפשרת לנו להתמודד עם היעדר ערך באופן פונקציונלי.

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

ה אוֹ מחלקה מכסה את מקרה השימוש.

מופע של אוֹ יכול להיות א ימין או א עזב אך אף פעם לא שניהם בו זמנית.

לפי האמנה, הימין הוא תוצאה של חישוב מוצלח, ואילו השמאל הוא המקרה החריג.

4.1. בניית אוֹ

אנחנו יכולים להשיג אוֹ למשל על ידי קריאה לאחת משתי שיטות המפעל הסטטיות שלה.

אנו קוראים ימין אם אנחנו רוצים אוֹ המכיל את ימין ערך:

או ימין = או. Right ("ערך");

אחרת, אנו מתקשרים שמאלה:

או שמאלה = או שמאלה (-1);

כאן, החישוב שלנו יכול להחזיר a חוּט או מספר שלם.

4.2. שימוש ב- אוֹ

כשיש לנו אוֹ למשל, אנחנו יכולים לבדוק אם זה שמאל או ימין ולפעול בהתאם:

אם (either.isRight ()) {...}

באופן מעניין יותר, אנו יכולים לשרשר פעולות בסגנון פונקציונלי:

או .map (String :: toUpperCase) .getOrNull ();

4.3. הקרנות

הדבר העיקרי שמבדיל בין כלים מונאדיים אחרים כמו אפשרות, נסה, היא העובדה שלעתים קרובות זה לא משוחד. במילים פשוטות, אם אנו קוראים לשיטת map (), אוֹ לא יודע אם לעבוד איתו שמאלה אוֹ ימין צַד.

זה המקום שבו התחזיות שימושיות.

התחזיות שמאלה וימינה הן השקפות ספקולריות של אוֹ שמתמקדים בערך שמאל או ימין, בהתאמה:

either.left () .map (x -> decodeSQLErrorCode (x));

בקטע הקוד שלמעלה, אם אוֹ הוא שמאל, decodeSQLErrorCode () יוחל על האלמנט הבסיסי. אם אוֹ הוא ימין, זה לא. אותו דבר להפך בעת שימוש בהקרנה נכונה.

4.4. שיטות שירות

כמו עם אפשרויות, Fugue מספק כיתה מלאה בכלי עזר עבור אריתר, וגם, וזה נקרא בדיוק כך: אריתר.

הוא מכיל שיטות לסינון, ליהוק ואיטרציה על פני אוספי אוֹס.

5. טיפול בחריגים עם לְנַסוֹת

אנו מסיימים את הסיור שלנו בסוגי נתונים זה או אחר ב- Fugue עם וריאציה אחרת הנקראת לְנַסוֹת.

לְנַסוֹת דומה ל אוֹאבל זה שונה בכך שהוא מוקדש לעבודה עם חריגים.

כמו אוֹפְּצִיָה ובניגוד אוֹ, לְנַסוֹת הוא פרמטריאלי על סוג אחד, מכיוון שהסוג "אחר" קבוע ל- יוצא מן הכלל (תוך כדי אוֹפְּצִיָה זה במשתמע בָּטֵל).

אז, א לְנַסוֹת יכול להיות או הַצלָחָה או א כישלון:

assertTrue (Try.failure (חריג חדש ("נכשל!")). isFailure ()); assertTrue (Try.successful ("OK"). isSuccess ());

5.1. מיידית א לְנַסוֹת

לעתים קרובות לא ניצור לְנַסוֹת במפורש כהצלחה או כישלון; אלא ניצור אחת משיחת שיטה.

נבדק קורא לפונקציה נתונה ומחזיר a לְנַסוֹת עוטף את ערך ההחזר שלו או כל חריג שנזרק:

assertTrue (Checked.of (() -> "בסדר"). isSuccess ()); assertTrue (Checked.of (() -> {throw new Exception ("ko");}). isFailure ());

שיטה אחרת, נבדק.הרמה, לוקח פונקציה פוטנציאלית לזרוק ו מעליות זה לפונקציה שמחזירה א לְנַסוֹת:

Checked.Function throwException = (String x) -> {throw new Exception (x); }; assertTrue (Checked.lift (throwException) .apply ("ko"). isFailure ());

5.2. עובד עם לְנַסוֹת

ברגע שיש לנו לְנַסוֹת, שלושת הדברים הנפוצים ביותר שאולי נרצה לעשות איתו בסופו של דבר הם:

  1. מחלץ את ערכו
  2. שרשור פעולה כלשהי לערך המוצלח
  3. טיפול בחריג עם פונקציה

חוץ מזה, מן הסתם, להשליך את לְנַסוֹת או להעביר אותו לשיטות אחרות, שלוש הנ"ל אינן האפשרויות היחידות שיש לנו, אך כל שיטות המובנות האחרות הן רק נוחות לעומת שלוש אלה.

5.3. מיצוי הערך המוצלח

כדי לחלץ את הערך, אנו משתמשים ב- getOrElse שיטה:

assertEquals (42, failedTry.getOrElse (() -> 42));

הוא מחזיר את הערך המוצלח אם קיים, או ערך מחושב כלשהו אחרת.

אין getOrTrow או דומה, אבל מאז getOrElse אינו תופס שום יוצא מן הכלל, אנו יכולים לכתוב זאת בקלות:

someTry.getOrElse (() -> {זרוק NoSuchElementException חדש ("אין מה להשיג");});

5.4. שרשרת שיחות לאחר הצלחה

בסגנון פונקציונלי נוכל להחיל פונקציה על ערך ההצלחה (אם קיים) מבלי לחלץ אותה במפורש תחילה.

זה האופייני מַפָּה שיטה שאנו מוצאים בה אוֹפְּצִיָה, אוֹ ורוב המכולות והאוספים האחרים:

נסה aTry = Try.successful (42) .map (x -> x + 1);

זה מחזיר א לְנַסוֹת כדי שנוכל לשרשר פעולות נוספות.

כמובן, יש לנו גם את flatMap מגוון:

נסה.מצליח (42) .flatMap (x -> נסה.מצליח (x + 1));

5.5. התאוששות מחריגים

יש לנו פעולות מיפוי אנלוגיות שעובדות למעט a לְנַסוֹת (אם קיים), ולא הערך המוצלח שלו.

עם זאת, שיטות אלה נבדלות בכך שמשמעותן היא להתאושש מהחריג, כלומר לייצר מצליח לְנַסוֹת במקרה של ברירת המחדל.

לפיכך, אנו יכולים לייצר ערך חדש עם לְהַחלִים:

נסה להתאושש = נסה .failure (חריג חדש ("boo!")) .Recover ((חריג e) -> e.getMessage () + "התאושש."); assertTrue (recover.isSuccess ()); assertEquals ("בו! התאושש.", recover.getOrElse (() -> null));

כפי שאנו רואים, פונקציית ההתאוששות לוקחת את החריג כטיעון היחיד שלה.

אם פונקציית ההתאוששות עצמה זורקת, התוצאה היא אחרת שנכשלה לְנַסוֹת:

נסה כישלון = Try.failure (חריג חדש ("בו!")). התאושש (x -> {זרוק RuntimeException (x);}); assertTrue (failure.isFailure ());

המקביל ל flatMap נקרא להתאושש עם:

נסה להתאושש = נסה .failure (חריג חדש ("בו!")) .RecoverWith ((חריג ה) -> נסה.מצליח ("התאושש שוב!")); assertTrue (recover.isSuccess ()); assertEquals ("התאושש שוב!", recover.getOrElse (() -> null));

6. כלי עזר אחרים

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

6.1. זוגות

א זוג הוא מבנה נתונים פשוט ורב-תכליתי, העשוי משני רכיבים חשובים לא פחות, שפיוג מכנה שמאלה ו ימין:

זוג זוג = Pair.pair (1, "a"); assertEquals (1, (int) pair.left ()); assertEquals ("a", pair.right ());

Fugue אינו מספק שיטות מובנות רבות ב- זוגs, מלבד מיפוי ותבנית הפונקציה היישומית.

למרות זאת, זוגs משמשים ברחבי הספרייה והם זמינים לתוכניות משתמשים.

היישום של המסכן הבא של ליספ נמצא במרחק כמה הקשות!

6.2. יחידה

יחידה הוא אנום בעל ערך יחיד שנועד לייצג "אין ערך".

זה תחליף לסוג ההחזרה הריק בָּטֵל בכיתה, זה מחסל ריק:

יחידה doSomething () {System.out.println ("שלום! תופעת לוואי"); יחידת החזרה (); }

באופן מפתיע למדי, עם זאת, אוֹפְּצִיָה לא מבין יחידה, מתייחסים אליו כאל ערך כלשהו במקום לאף אחד.

6.3. כלי עזר סטטיים

יש לנו כמה שיעורים עמוסים בשיטות שימוש סטטיות שלא נצטרך לכתוב ולבדוק.

ה פונקציות מחלקה מציעה שיטות המשתמשות בשינוי פונקציות בדרכים שונות: קומפוזיציה, יישום, קארי, פונקציות חלקיות באמצעות אוֹפְּצִיָה, תזכורת חלשה וכדומה.

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

שרטוטים ו מחטביםלבסוף, מכילים שורה של שיטות סטטיות למניפולציה של שני ממשקי Java הסטנדרטיים הנפוצים ביותר.

7. מסקנה

במאמר זה נתנו סקירה כללית על ספריית Fugue מאת אטלסיאן.

לא נגענו בשיעורים כבדי האלגברה כמו מונואיד ו קבוצות חצי כי הם לא נכנסים למאמר כללי.

עם זאת, תוכלו לקרוא עליהם ועוד ב- javadocs של Fugue ובקוד המקור.

כמו כן, לא נגענו באף אחד מהמודולים האופציונליים, המציעים למשל שילובים עם גויאבה וסקאלה.

ניתן למצוא את היישום של כל הדוגמאות וקטעי הקוד בפרויקט GitHub - זהו פרויקט של Maven, כך שיהיה קל לייבא ולהפעיל אותו כמות שהוא.


$config[zx-auto] not found$config[zx-overlay] not found