יימח שמו של הבינה המלאכותית
ולו רק מפני שהוא מעורר בי נטיות אלימות כלפיו...
במחשבה שנייה, זו לא בעיה שלו, הוא כלי, הבעיה במשתמשים בו...
יימח שמו של הבינה המלאכותית
ולו רק מפני שהוא מעורר בי נטיות אלימות כלפיו...
במחשבה שנייה, זו לא בעיה שלו, הוא כלי, הבעיה במשתמשים בו...
בפוסט זה אני הולך לשתף דבר שלמדתי לאחרונה ב-TS שהיה חידוש עבורי
אני משתמש בנושא זה כקרש קפיצה לכתוב מבוא כללי ל-TS. כדי להסביר את החידוש שגיליתי, אסביר בצורה מתומצתת את המושגים שצריכים להכיר כדי להבין את החידוש
(אם מישהו יתחיל להשתמש בשפה בזכותי והיה זה שכרי. פשוט חבל שיש כל כך הרבה מתכנתים מוכשרים בקהילה שלנו שלא משתמשים ב-TS מחוסר היכרות...)
מכיון שאני כותב את הפוסט בהמשכים אשמח אם התגובות יהיו בנושא נפרד
התוכנית:
מקווה שיהיה קל לקריאה ולתועלת
ובכן, אעביר אותך קורס מזורז מאוד ב-TS:
דרך אחת להסתכל על טייפ הוא ככה:
טייפ הוא סט (set - כן, ההוא מתורת הקבוצות...) של ערכים.
לדוגמה:
number
מייצג את הסט שכולל בתוכו את כל המספרים1
מייצג סט שכולל בתוכו ערך אחד: המספר 1, כמו"כ כל ערך ב-JS הוא גם שם של טייפ שכולל חבר אחד - הערך הזה בעצמו{ foo: string; bar: number }
מייצג את הסט שמכיל כל האובייקטים האפשריים שמכילים שדה foo
מסוג string
ושדה bar
מסוג number
never
מייצג סט ריק. סט בלי חברים.unknown
מייצג את הסט של כל הערכים האפשריים. "סט סטי הסטים". הסט הכי גדול ביקום הטייפים. לכן אין הרבה מה לעשות עם ערך מסוג unknown כי אתה לא יודע איזה פעולות מותרים לעשות איתו.דרך נוספת לחשוב על טייפים:
הטייפ של הערך אומר לנו איזה פעולות מותרות על הערך
למשל:
number
אומר לנו שמותר לעשות פעולת חיבור וחיסור על ערך זה עם מספרים אחריםstring
אומר לנו שמותר לנו לקרוא לפונקציה בשם startsWith
על הערך שלנוזו גם דרך נכונה לחשוב על טייפים.
בהמשך המאמר נתמקד יותר בפן הראשון: טייפ של ערך מייצג חברות בסט של ערכים.
TS נותן שני כלים אריתמטיים לבניית טייפים מורכבים מטייפים אחרים:
האופרטור |
ב-TS עושה את פעולת החיבור באריתמטיקה של טייפים
למשל:
1 | 2
מייצג חיבור של שני הסטים 1
ו-2
. התוצאה היא סט (טייפ) שכולל שני חברים, 1 ו-2string | number
מחבר את שני הסטים והתוצאה היא סט גדול שכולל בתוכו כל המחרוזות האפשריים וכל המספרים האפשרייםnever
(להזכירכם: זהו הסט עם 0 חברים) הוא כמו פעולת חיבור מספרי של מספר כלשהו עם 0. הפעולה לא משנה את הערך המקורי.למדנו איך להרחיב סט עם אופרטור |
עכשיו נלמוד איך להצר סט עם אופרטור &
.
האופרטור &
מקבל שני סטים משני צידי האופרטור ומחזיר את הסט שכולל רק את החברים בשני הסטים גם יחד
למשל:
{ foo: string } & { bar:number }
לוקח את הסט שכולל כל האובייקטים האפשריים שיש להם שדה foo
מסוג string, וכן את הסט שכולל כל האובייקטים האפשריים שיש להם שדה bar
מסוג number, והוא מחזיר סט של כל האובייקטים האפשריים שחברים בשתי הקבוצות: דהיינו אובייקטים שיש להם גם שדה foo וגם שדה bar& unknown
לא עושה כלום כי כל ערך אפשרי נמצא בתוך סט ה-unknownTS נותן כלים יותר משוכללים לבניית טייפים על ידי "תכנות"
תחביר ה-generics מקביל לפונקציה המוכרת מתכנות רגיל.
אבל בעוד שפונציקה רגילה פועלת על ערכים, ה-generic פועל על טייפים.
זה פונקציה שמקבל כארגומנט טייפ, ופולט את הטייפ הסופי לפי הלוגיקה של ה-body של הפונקציה.
לדוגמה:
// הצהרת טייפ שכולל כל נוסחאות התפילה האפשריים
type Nusach = 'Ashkenaz' | 'Sefarad' | 'Edot Hamizrach'
// הצהרת טייפ גנרי שמקבל נוסח תפילה ומחזיר טייפ של יהודי שמתפלל בנוסח הנ"ל
type Jew<T extends Nusach> = {
name: string
nusach: T
}
// ערך עם שדה שם ושדה נוסח
const aJew = {
name: 'Zundel',
nusach: 'Ashkenaz'
}
// נסיון השמה למשתנה מסוג Jew<'Sefarad'>
// TS מתריע על אי התאמה בין הטייפ לערך
const test: Jew<'Sefarad'> = aJew
השורה האחרונה תפלוט שגיאה, כי טייפ מסוג Jew<'Sefarad'>
לא יכול להתפלל נוסח אשכנז
extends
בדוגמה דלעיל נתקלנו לראשונה (בקורס הזה) במילת המפתח extends
, ב-TS הכוונה של extends
הוא (לפי צורת החשיבה שהצגנו בתחילת דברינו) שהטייפ שבצד שמאלי כולו חבר בסט שמיוצג על ידי הצד הימני.
ובדוגמה הנ"ל: T extends Nusach
הכוונה הוא שהפרמטר T
רק מקבל טייפים שהם חברים בסט Nusach
אם ננסה ליצור יהודי כזה: Jew<'foo'>
נקבל שגיאה שהמחרוזת foo
הוא לא חבר בקבוצת Nusach
נפגוש שוב את המילה extends
בהמשך
התחביר לכתיבת תנאי ב-TS:
T extends U ? V : W
שימו לב לנקודות הבאות:
בתכנות רגיל אנחנו מורגלים לבדיקת המון דברים בתנאים, וכן לשלוט על פעולות מגוונות על ידי תנאים אלו
ב-TS לעומת זאת:
דוגמה לשימוש בתנאי ופונקציה ביחד:
type LabelOf<T> = T extends { label: string } ? T['label'] : 'no name'
אפשר לתאר את ה-shape של אובייקט בלי לפרט בדיוק את השם של השדות, במקום זה כותבים את הטייפ של המפתחות והטייפ של הערכים
לדוגמה:
type X = {
[key: string]: number
}
הכוונה בהצהרה זו הוא שמדובר באובייקט שיש בו מפתחות מסוג string וערכים מסוג number
TS לוקח את התחביר הזה שלב נוסף קדימה באמצעות mapped types
בתחביר זה אפשר לעבור בלולאה על כל הערכים האפשריים הכלולים במפתח (key) ולקבוע את הטייפ של הערך עבור אותו מפתח לפי כל לוגיקה שתבחר
דוגמה:
type MyMap<T> = {
[K in keyof T]: K extends `${string | undefined}foo${number}` ? string : number
}
type Test = MyMap<{ foo1: any, a_foo2: any, bar3: any }>
כאן אנחנו נתקלים לראשונה במילת המפתח keyof
:
זה אופרטור שמחזיר union של כל שמות השדות של האופרנד שלו
למשל: keyof {foo:any, bar:any}
שווה ל-'foo' | 'bar'
ה"פונקציה" (יותר מקובל לקרוא לו generic type) MyMap
מקבל פרמטר T
(מכיון שלא הגבלנו אותו על ידי מילת המפתח extends
- הוא יכול להיות מכל סוג שהוא), ומחזיר אובייקט שיש לו אותם שדות של האובייקט המקורי, אבל אם התבנית של שם השדה מתאים לתבנית מחרוזת אופציונלית + foo + מספרי כלשהו, אז הערך של השדה חייב להיות string, אחרת הערך חייב להיות number
יותר מקובל ושימושי להשתמש ב-mapped types עם תנאי שבודק את הטייפ של ה_ערך_ של האובייקט המקורי במקום תנאי שבודק את הטייפ של ה_מפתח_ של האובייקט המקורי. עושים את זה על ידי אינדוקס ככה:
type MyMap<T> = {
[K in keyof T]: T[K] extends X ? Y : Z
}
נראה דוגמה שימושית לזה מיד בקטע הבא
Omit
בוא נבדוק את ההבנה שלך על ידי הדוגמה הבאה.
(ההגדרות Exclude
ו-Omit
מגיעים מובנים ב-TS)
// type Omit<T, K extends keyof any> = { [P in Exclude<keyof T, K>]: T[P]; }
// type Exclude<T, U> = T extends U ? never : T
type MyObject = {
id: number
foo: string
bar: number
}
type MyObjectWithoutId = Omit<MyObject, 'id'>
טוב, התעייפתי לבינתיים, אמשיך בעז"ה בהזדמנות הבאה...
אולי נושאים אלו יעניינו אותך
https://tchumim.com/topic/1072
https://tchumim.com/topic/1047
@pcinfogmach לא הבנתי לגמרי את דבריך.
בכל מקרה, התכוונתי רק שאת מבנה העץ תשמור כמבנה JSON. תוכן הספרים אפשר לשמור בטלאות או איך שלא תרצה
@pcinfogmach אולי תוותר על מסד טבלאי ובמקום זה תשתמש במשהו שיכול לייצג עץ נתונים בצורה יותר טבעית
אולי מבנה JSON יספק לך מענה מספיק טוב
@Whenever כתב במישהו מכיר איזה תוסף שיכול להגביל את ההכחלה של השורה:
לא כ"כ מובן מה כוונתך
הכוונה ברורה לגמרי
השואל רוצה להעתיק עמודה מתוך טבלה
אני עומד מאחורי התשובה שלי שאין אפשרות כזאת כלל בדפדפן אבל אפשר להעתיק לוורד ולעשות את זה שם
@THMV כתב במישהו מכיר איזה תוסף שיכול להגביל את ההכחלה של השורה:
ואני רוצה להעתיק רק את מספרי הטלפון ואני רוצה להכחיל רק את העמודה של מספרי הטלפון, ולא את כל השורה
אין אפשרות כזאת בדפדפן, אבל אפשר להעתיק את כל השורות לוורד ושם אפשר לבחור אזור בדף על ידי לחיצת alt תוך כדי גרירת העכבר
@ראש-פינה תעזור לנו לעזור לך
יש פה הרבה אנשים שיודעים לכתוב סקריפטים, אבל מן הסתם אין הרבה אנשים שמכירים את shelly
ככל שתמקד יותר את השאלה כך שהוא שאלה על כתיבת סקריפט ולא על ניהול shelly כך יותר סביר שתקבל תשובה
למשל אם תוכל להביא סקריפט שניסית ושגיאה שקיבלת, אולי יהיה אפשר לעזור בלי להכיר את shelly
@ראש-פינה כתב בניטרול לחצנים בהתקן בית חכם:
אבל משום מה זה לא עובד לי
אחד שמשפטים המעצבנים שחוזרים על עצמם בשאלות בפורום... אתה לא זורק לנו עצם... תן קצת פירורים שיהיה עם מה לעבוד לעזור גם בלי להכיר את shelly
@איך-ווייס-נישט תפתח נושא חדש עם שאלה מפורטת
@dovid כתב בקריאת התנ"ך:
אם אתה רוצה לפנות לקהל מגוון עדיף שברבנים יהיו גם ממגזרים אחרים (אדמורים, רבנים חרדיים, חבד וכדומה).
אפשר למצוא מכתבי רבנים בנושא בחומש "חומש על פי המסורה" שיצא לאור בשנת תשמ"ט עם מכתבי הסכמה מהרב יעקב קמינצקי והרב שמואל ווזנר זצ"ל בין השאר
@nirmasdirim כתב בקריאת התנ"ך:
האתר הוא בקוד פתוח
לא מצויין בפוסט שלך או באתר איפה אפשר למצוא קוד מקור אז אני מעיז להביא פה קישור לפרוייקט:
https://github.com/bambiker/sdarim
@nirmasdirim כתב בקריאת התנ"ך:
מה כדאי לשפר כדי שהאתר יעזור ללמוד תורה בלי החלוקה הנוצרית
צריך לשפר את חווית המשתמש באתר
כמה בעיות ששמתי לב אליהם:
@mekev כתב בקריאת התנ"ך:
לדאוג שהוא יהיה פתוח בנטפרי?
פתוח עכשיו
@mekev
אני לא יודע מה באמת יקרה
אבל זה פחות קשור לחוקים פיזיקליים
זה יותר קשור לפרוטוקול USB
כאשר המכשירים מתחברים אחד לשני מתקיים דו שיח שבו הם מחליטים מי מהם יטעין את השני ובאיזה מתח
(חפש בגוגל USB-PD negotiation)
במקרה שבאמת יש החלטות סותרות בין המכשירים, אז החוק הפיזיקלי שקובע יהיה קשור להבדלי מתח בין שני המכשירים ולא להבדלים בכמות המטען
ע"ע: https://electronics.stackexchange.com/questions/255684/connecting-two-usb-c-hosts-what-happens
@הפצת-אנקי כתב בבאיזה עדכון לווינדוס 10 הוכנס pyqt6?:
זה לא כולל את pyqt?
לא
צריך להתקין עם pip
אבל זה אמור להגיע בתוך ההתקנה של אנקי
@הפצת-אנקי כתב בבאיזה עדכון לווינדוס 10 הוכנס pyqt6?:
מחיפוש שעשיתי נראה שחסר DLL
מהודעת השגיאה יותר נראה שה-DLL קיימת אבל הגירסה לא תואמת את הגירסה שהתוכנה מצפה
אין גישה למפתחים חיצוניים
@מתושלח-הבבלי1 האם אתה בטוח שזה אפשרי?
אין לי טסלה אבל הבנתי מחיפוש ברשת שזה לא קיים, אין "חנות טסלה" לאפליקציות צד שלישי
@שלום-עולם-0 כתב באי דיוק של MouseEvent על קנבס:
אני מקודד בשביל התחביב בלבד, לא לפרנסתי. אז אולי לא תרצה לעזור לי...
הפוך, זה נותן חשק לעזור, כי זה סימן שאתה מעוניין בתשובה עצמה ולא רק ב-
כל הכבוד על הפרוייקט הנחמד
לצערי עוד לא יצא לי להתעמק בקוד שלך
אבל הצלחתי לשחזר את הבאג
לגבי אינדקס על שדה בוליאני: זה כדאי רק במקרה שהסינון על העמודה יחזיר רק מיעוט מהשורות (רוב המוחלט של השורות הוא true או false) וכדאי לאנדקס רק השורות עם הערך הפחות נפוץ (true או false), דהיינו להוסיף where לפקודה של יצירת האינדקס
עיין https://stackoverflow.com/a/42972924
יש תורה שלימה שאי אפשר למסור על רגל אחת (גם אם הייתי מכיר את זה היטב)
הכלל הבסיסי הוא שכדאי לאנדקס במקרה שאינדקס יגרום לחסכון גדול בשיעור הקריאה מהדיסק שהמסד צריך כדי לענות על השאילתה
המקרה הקלאסי הוא כאשר בלי אינדקס המסד יצטרך לעבור על כל הטבלה כדי לענות על השאלה, ועם אינדקס הוא יצטרך קריאה של רק אחוז קטן מהטבלה
למשל, שאילתה על טבלה גדולה שמחזירה רק שורות מועטות מתוך הטבלה על ידי סינון עמודה
דוגמאות למקרים שלא צריכים אינדקס:
WHERE
על עמודה נוספת (גם בלי אינדקס על העמודה המסננת, שליפת שורה לפי מפתח ראשי הוא מהיר)אני ממליץ בשלב הזה לטפל נקודתית בשאילתות שאתה רואה שהם איטיים, ולבדוק אם אפשר לשפר אותם על ידי אינדקס ולא סתם לחפש ליצור אינדקסים
לפעמים AI מצליח לענות תשובה נכונה אם אתה שואל אותו "איזה אינדקס כדאי לעשות לשפר את הביצועים של שאילתה זו"
const { HDate, Locale, gematriya } = require("@hebcal/hdate");
Locale.useLocale("he-x-nonikud");
const convertToHebrewDate = (dateString) => {
const date = new Date(dateString);
const hDate = new HDate(date);
return `${gematriya(hDate.getDate())} ב${Locale.lookupTranslation(
hDate.getMonthName()
)} ${gematriya(hDate.getFullYear())}`;
};
console.log(convertToHebrewDate("2021-09-07")); // א׳ בתשרי תשפ״ב