הבלוג של ינון פרק

טיפים קצרים וחדשות למתכנתים

הטלגרם בוט הראשון שלי

04/10/2018

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

המשך קריאה

היפוך סדר המילים במשפט בגירסא פונקציונאלית

03/10/2018

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

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

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

sentence = process.argv[2];
result = [];

words = sentence.split(/\W+/);

for (let i=words.length - 1; i >= 0; i--) {
  result.push(words[i]);
}

console.log(result.join(" "));

אבל המעבר לתכנות פונקציונאלי משנה את התוכנית לחלוטין - ולא רק בגלל שפת התכנות. הנה אותו הקוד באליקסיר:

System.argv
|> List.first
|> String.split
|> Enum.reverse
|> Enum.join(" ")
|> IO.inspect

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

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

List.first(System.argv)

אפשר לכתוב את הדבר הזה שעושה בדיוק את אותו דבר:

System.argv |> List.first

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

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

  1. לוקחים את המשתנה הראשון שקיבלנו בשורת הפקודה.
  2. את התוצאה שוברים למילים.
  3. את התוצאה הופכים.
  4. את התוצאה מחברים חזרה.
  5. את התוצאה מדפיסים.

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

console.log(
  process.argv[2]
  .split(/\W+/)
  .reverse()
  .join(" ")
)

געגועים ל ++

02/10/2018

הקוד הבא ב perl מקבל רשימה של מספרים ובכל סיבוב מגדיל אחד מהם באקראי עד שכל המספרים גדולים מאלף (וכן אני יודע שיש לכם אלף רעיונות יותר יעילים לממש את זה. זאת לא הנקודה כאן):

use v5.18;
use List::Util qw/min max/;

my @numbers = <>;
my $rounds = 0;

while (min(@numbers) < 1000) {
  my $idx = int(rand(@numbers));
  $numbers[$idx]++;
  $rounds += 1;
}

say "@numbers";
say "took $rounds rounds";

מסתבר שיש בקוד קסם אחד שדי קשה לתרגם לשפות אחרות. הקוד הבא נראה כמו גירסת רובי של אותו המנגנון:

numbers = ARGF.readlines.map(&:to_i)
rounds = 0

while numbers.min < 1000
  idx = rand(numbers.size)
  numbers[idx]++
  rounds += 1
end

puts "#{numbers}"
puts "took #{rounds} rounds"

נסו להריץ ותגלו שהקוד ב Ruby אף פעם לא מסתיים. זה די ברור כשנזכרים שאין ++ בשפת רובי. אז מה כן קרה שם? הנה הגירסא שיותר קל לקרוא:

numbers = ARGF.readlines.map(&:to_i)
rounds = 0

while numbers.min < 1000
  idx = rand(numbers.size)
  numbers[idx] + (+rounds += 1)
end

puts "#{numbers}"
puts "took #{rounds} rounds"

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

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

היכרות עם הספריה Immer

01/10/2018

בתחילת השנה מייקל וסטרט התחיל לפרסם ספריית קוד פתוח חדשה לעבודה עם Immutable Data Structures. הספריה נקראת Immer ומאז הפכה לפיתרון יציב ואף זכתה לברכות מדן אברמוב. בואו ניקח כמה דוגמאות כדי להבין מהי ובמה היא טובה יותר מ Immutable.JS הוותיקה.

המשך קריאה

ריבייס מהיר יותר עם rerere

29/09/2018

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

המשך קריאה

לולאות בתכנות פונקציונאלי

28/09/2018

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

המשך קריאה

ללמד אנשים אחרים

27/09/2018

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

אחרי שלושה חודשים של וובינרים אני שמח לספר שהחודש את רוב הוובינרים תעבירו אתם. אנשים שמוכנים לקחת את הסיכון, לעמוד מול קהל (וירטואלי - אבל עדיין אנשים אמיתיים) ולשתף מהידע שלהם. אנשים שמוכנים להתאמץ כדי ללמוד ולהשתפר.

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

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

שתי גישות, אותם קשיים

25/09/2018

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

אנגולר או ריאקט? מיקרו סרביסס או מונולית? אפליקציה או אתר? שרת ייעודי או Serverless?

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

במקום לבזבז זמן על חיפושים קחו את זו שאתם יודעים איך להתקדם בה ותתחילו משם. אחרי שהקוד יעבוד יהיה לנו הרבה יותר קל לשכתב או לשפר אותו.

נ.ב. אני עדיין פותר עם חברים את Advent Of Code האחרון, בקבוצת לימוד באווירה טובה ובעברית. אם אתם רוצים דרך בטוחה לשפר את מיומנויות התכנות שלכם דרך פיתרון בעיות מדליקות ועזרה לחברים בבעיות אלה מוזמנים בחום להצטרף. החידה הנוכחית מחכה לכם כאן:

https://forum.tocode.co.il/t/advent-of-code/782