ToCode
Ir al canal en Telegram
1 419
Suscriptores
Sin datos24 horas
Sin datos7 días
-430 días
Archivo de publicaciones
1 419
ללמוד כי-
הכי קל ללמוד כי צריך. ללמוד כדי להצליח במבחן, כדי להצליח בעבודה, כדי להצליח לתקשר עם אנשים. כשלומדים בשביל להצליח אנחנו מוכנים להשקיע את השעות, להגיע כל יום, להתאמץ להבין גם כשקשה. אין ברירה. מה שמחזיק אותנו זה שיש נקודת סיום וגמול מיידי להשקעה.
הרבה אנשים לומדים בשביל הכיף. אנחנו אוהבים לבשל או לגנן או לכתוב שירים, והתחביב מוביל אותנו להבין טוב יותר את העולם. מעניין איך זה עובד, מעניין איך אחרים עושים את זה, מעניין מה יקרה אם ... כשלומדים בשביל הכיף אנחנו שמחים להשקיע את השעות ותמיד מוצאים זמן כדי להתקדם בתחביב שלנו, עד שיש עומס ואז תקופה לא מוצאים זמן או שהגענו לחלק קשה או משעמם ואז מתקדמים בלימוד לכיוון אחר. תחביב אפשר להמשיך לפתח לאורך שנים ומה שמחזיק אותנו הוא העניין בתחום.
ולפעמים אנחנו לומדים משהו בגלל שהוא חשוב.
כשכולם היו צריכים ללמוד כל שבוע JavaScript Framework חדש היו אנשים שעצרו כדי ללמוד איך בנוי דפדפן, איך JavaScript עובדת ואיך לבנות JavaScript Framework מאפס. מה האתגרים בפיתוח Single Page Application ואיך פותרים אותם בלי Framework, איך לכתוב פיתרון Router מאפס. לא היה לידע הזה ערך מיידי. זה לא הופיע בשום רשימת דרישות במודעות דרושים ולא הופיע באף סילבוס. ובכל זאת אנשים שהשקיעו את העבודה בלימוד היסודות הצליחו ללמוד פריימוורקים חדשים הרבה יותר מהר ולעבוד נכון יותר.
האתגר עם דברים חשובים הוא שכמו דברים שאנחנו לומדים בשביל להצליח גם הם דורשים השקעה עצומה, אבל הם לא כוללים גמול מיידי או נקודת סיום. הם מעניינים בהתחלה אבל מהר מאוד מגיע החלק הקשה, המוטיבציה נעלמת ואנחנו צריכים למצוא סיבה אחרת להמשיך להשקיע.
כשמתחילים ללמוד משהו חדש כדאי להבין למה אני לומד את זה, איך יראה תהליך הלמידה ואיך תשתנה המוטיבציה שלי לאורך התהליך. כשאני יוצא לדרך עם הבנה של המסלול הסיכוי להצלחה גדל משמעותית.
1 419
</div>
<div className="carousel-indicators">
{images.map((_, index) => (
<button
key={index}
className={\carousel-indicator ${index === currentIndex ? 'active' : ''}\}
onClick={() => goToSlide(index)}
aria-label={\Go to slide ${index + 1}\}
/>
))}
</div>
{images.length > 1 && (
<div className="carousel-countdown">
Next image in: {countdown}s
</div>
)}
</div>
)
}
export default ImageCarousel
גם הוא עובד הפעם עם משתנה סטייט יחיד.
כיוון אחר לשבור את הקשר הוא לפרק את הקומפוננטה לשתי קומפוננטות - קומפוננטה אחת של קרוסלת תמונות וקומפוננטה שניה היא השעון עצר. זה הקוד עם הפרדת קומפוננטות:
import { useState, useEffect } from 'react'
import './ImageCarousel.css'
interface CountdownTimerProps {
interval: number
onTimeout: () => void
}
const CountdownTimer: React.FC<CountdownTimerProps> = ({ interval, onTimeout }) => {
const [countdown, setCountdown] = useState(interval / 1000)
useEffect(() => {
const timer = setInterval(() => {
setCountdown((prevCountdown) => {
if (prevCountdown <= 1) {
onTimeout()
return interval / 1000 // Reset countdown
}
return prevCountdown - 1
})
}, 1000) // Update every second
return () => clearInterval(timer)
}, [interval, onTimeout])
return (
<div className="carousel-countdown">
Next image in: {countdown}s
</div>
)
}
interface ImageCarouselProps {
images: string[]
interval?: number
}
const ImageCarousel: React.FC<ImageCarouselProps> = ({ images, interval = 3000 }) => {
const [currentIndex, setCurrentIndex] = useState(0)
const goToSlide = (index: number) => {
setCurrentIndex(index)
}
const goToPrevious = () => {
setCurrentIndex((prevIndex) =>
prevIndex === 0 ? images.length - 1 : prevIndex - 1
)
}
const goToNext = () => {
setCurrentIndex((prevIndex) => (prevIndex + 1) % images.length)
}
if (images.length === 0) {
return <div className="carousel-empty">No images to display</div>
}
return (
<div className="carousel-container">
<div className="carousel-wrapper">
<button
className="carousel-btn carousel-btn-prev"
onClick={goToPrevious}
aria-label="Previous image"
>
‹
</button>
<div className="carousel-image-container">
<img
src={images[currentIndex]}
alt={\Slide ${currentIndex + 1}\}
className="carousel-image"
/>
</div>
<button
className="carousel-btn carousel-btn-next"
onClick={goToNext}
aria-label="Next image"
>
›
</button>
</div>
<div className="carousel-indicators">
{images.map((_, index) => (
<button
key={index}
className={\carousel-indicator ${index === currentIndex ? 'active' : ''}\}
onClick={() => goToSlide(index)}
aria-label={\Go to slide ${index + 1}\}
/>
))}
</div>
{images.length > 1 && (
<CountdownTimer
key={currentIndex}
interval={interval}
onTimeout={goToNext}
/>
)}
</div>
)
}
export default ImageCarousel
כאן שוב יש לנו את ה set בתוך set, אבל הפעם הזזתי את האפקט רק לקומפוננטה של השעון שהיא הרבה יותר קטנה וכל משתנה סטייט שמור בקומפוננטה שלו.
מה דעתכם? איזה גירסה אתם הכי אוהבים ולמה?1 419
עדכון סטייט בתוך עדכון סטייט
בוובינר היום ביקשנו מקלוד לעדכן קומפוננטת ריאקט שמציגה קרוסלת תמונות ולהוסיף לה שעון עצר שמראה כמה זמן עד החלפת התמונה הבאה. בהתחלה הוא יצר שני אפקטים וכשהתעקשנו ליצור אפקט אחד קיבלנו את הקוד הבא:
useEffect(() => {
if (images.length <= 1) return
// Reset countdown when component mounts or when interval changes
setCountdown(interval / 1000)
const timer = setInterval(() => {
setCountdown((prevCountdown) => {
if (prevCountdown <= 1) {
// Time to switch image
setCurrentIndex((prevIndex) => (prevIndex + 1) % images.length)
return interval / 1000 // Reset countdown
}
return prevCountdown - 1
})
}, 1000) // Update every second
return () => clearInterval(timer)
}, [images.length, interval])
שימו לב לקריאה ל setCurrentIndex בתוך פונקציית העדכון שעוברת ל setCountdown. יצא לי לכתוב קוד בסגנון הזה וכל פעם שזה קרה זה העיד על איזושהי בעיה בתכנון הקומפוננטה ובסופו של דבר יצא משליטה וגרם לבאגים מוזרים במקומות אחרים. ובכל זאת הקוד של קלוד עובד.
אחרי הוובינר ניסיתי להבין מה הפריע לי בפיתרון ואני חושב שהבעיה היא כפילות בסטייט - בעצם יש פה שני משתני סטייט קשורים ואנחנו צריכים את העדכון בתוך עדכון כדי לבטא את הקשר הזה. אפשר לחשוב על זה שרצוי שמשתני סטייט של קומפוננטה יהיו אורתוגונליים וכשיש קשר ביניהם זה אומר שמשהו לא מדויק בארכיטקטורה.
אם יש משתני סטייט קשורים אולי זה אומר שאחד מהם יכול להיות ערך מחושב? כיוון אחד יכול להיות לספור רק את הזמן שעבר מאז שהקומפוננטה נכנסה למסך, ואז אפשר לחשב את אינדקס התמונה להצגה עם חילוק ושארית. הבעיה היא מה עושים עם הלחיצות. אם ממשיכים באותו כיוון אפשר להגדיר שהלחיצות "יקדמו" את השעון, ואז יש לנו את הקוד הבא:
import { useState, useEffect } from 'react'
import './ImageCarousel.css'
interface ImageCarouselProps {
images: string[]
interval?: number
}
const ImageCarousel: React.FC<ImageCarouselProps> = ({ images, interval = 3000 }) => {
const [elapsedTime, setElapsedTime] = useState(0)
// Derive currentIndex and countdown from elapsedTime
const currentCycle = Math.floor(elapsedTime / interval)
const currentIndex = currentCycle % images.length
const timeInCurrentCycle = elapsedTime % interval
const countdown = Math.ceil((interval - timeInCurrentCycle) / 1000)
useEffect(() => {
if (images.length <= 1) return
const timer = setInterval(() => {
setElapsedTime((prevTime) => prevTime + 1000)
}, 1000) // Update every second
return () => clearInterval(timer)
}, [images.length, interval])
const goToSlide = (index: number) => {
// Calculate the elapsed time that would result in the desired index
const targetCycle = Math.floor(elapsedTime / interval) + (index - currentIndex)
const adjustedCycle = targetCycle >= 0 ? targetCycle : targetCycle + Math.ceil(Math.abs(targetCycle) / images.length) * images.length
setElapsedTime(adjustedCycle * interval)
}
const goToPrevious = () => {
const prevIndex = currentIndex === 0 ? images.length - 1 : currentIndex - 1
goToSlide(prevIndex)
}
const goToNext = () => {
const nextIndex = (currentIndex + 1) % images.length
goToSlide(nextIndex)
}
if (images.length === 0) {
return <div className="carousel-empty">No images to display</div>
}
return (
<div className="carousel-container">
<div className="carousel-wrapper">
<button
className="carousel-btn carousel-btn-prev"
onClick={goToPrevious}
aria-label="Previous image"
>
‹
</button>
<div className="carousel-image-container">
<img
src={images[currentIndex]}
alt={\Slide ${currentIndex + 1}\}
className="carousel-image"
/>
</div>
<button
className="carousel-btn carousel-btn-next"
onClick={goToNext}
aria-label="Next image"
>
›
</button>1 419
בואו נפסיק להגיד "עדיין"
עוזר לחבר לפתור באג, אחרי חיפושים מצאנו את הבעיה, פתרנו וגם שיפרנו את כל הארכיטקטורה של הקוד כדי שבאגים כאלה לא יוכלו לחזור. נזכר במנכל של סופטבנק שבטוח שעד סוף השנה הוא מפטר את כל המתכנתים ומחליף את כולנו ב AI ומחייך לחבר:
״אתה רואה, שום AI לא יחליף אותנו בזמן הקרוב״
רק בשביל לשמוע שוב את ה ״עדיין...״.
כדאי לזכור:
1. טכנולוגיית AI הנוכחית משכפלת תבניות ומייצרת טקסטים חדשים לפי תבניות. היא לא חושבת.
2. חלק משמעותי מהעבודה שלכם הוא חשיבה.
3. כל פרויקט תוכנה מעניין שראיתי דרש יצירתיות ופיתרונות מחוץ למה שכתוב בספר. ראיתי מספיק פעמים מה קורה לפרויקטים כשמעתיקים בצורה עיוורת תבניות מספרים. זה לא נגמר טוב.
כן יום אחד אולי מישהו יבנה AI שיכול להבין. כתבתי על החלום הזה:
https://www.tocode.co.il/blog/2025-05-emergent-is-crazy
אנחנו לא שם והטכנולוגיה הנוכחית לא מקרבת אותנו לשם יותר ממה שהיינו לפני ChatGPT. אם כבר העבודה עם AI רק חידדה אצלי את ההבנה כמה המקצוע שלנו מורכב וכמה תשומת לב דרושה כדי לייצר מודל מנטלי של מערכת תוכנה ולשים לב לכל פרט קטן. להגיד "עדיין" זה כמו להגיד שמחשבון "עדיין" לא מסוגל לכתוב הוכחות. זה חוסר הבנה של הכלי. מחשבון לעולם לא יהיה מסוגל לכתוב הוכחה מתמטית כי הוא לא נועד לזה, בדיוק כמו שמערכת בינה מלאכותית גנרטיבית לעולם לא תהיה מסוגלת לתחזק קוד. זאת לא הטכנולוגיה.
1 419
התמונה מתחלפת כל שלוש שניות אפילו אם משתמשים מעבירים תמונה ידנית. הבעיה היא שאם אני מחליף ידנית תמונה אז יכול להיות שאני מחליף בדיוק ברגע שעוברות 3 שניות ואז אני לוחץ אבל הקרוסלה זזה בשתי תמונות. יותר הגיוני יהיה לספור 3 שניות מרגע שהתמונה מתחלפת, בלי קשר אם היא התחלפה בגלל משתמש או בגלל שינוי אוטומטי. כשנבקש מקלוד לתקן הוא יכתוב את הקוד הבא:
useEffect(() => {
if (images.length <= 1) return
const timer = setInterval(() => {
setCurrentIndex((prevIndex) => (prevIndex + 1) % images.length)
}, interval)
return () => clearInterval(timer)
}, [images.length, interval, currentIndex])
כלומר קלוד שם לב שכדאי לו לאפס את האפקט כל פעם שהאינדקס משתנה אבל הוא לא חשב לשנות את setInterval ל setTimeout, למרות ש setTimeout יותר קריא ונכון בהקשר הזה.
לאחר מכן ביקשתי ממנו שיוסיף שעון ספירה לאחור עד השינוי הבא. קלוד הבין שהוא צריך עוד משתנה סטייט של "כמה זמן נשאר" והוסיף אותו, אבל הוא לא ראה שבעצם שני האפקטים קשורים ואפשר לאחד אותם.
זאת אחת הסיבות שאנחנו רואים הרבה כפל קוד בקוד ש AI מייצר, וכשלונות כשאנשים מנסים להשתמש ב AI כדי לשכתב קוד. הניסיון של AI לשמר קוד ישן מוביל לקוד ארוך ומסורבל יותר ופעמים רבות כפול.
רוצים לשמוע יותר פרטים על הדוגמאות, לראות דוגמאות נוספות או לשתף דוגמאות משלכם? אל תתביישו להצטרף לזום מחר בעשר נפתח את הכל וגם נראה איך כשאני מודע לבעיות האלה אני יכול למנוע אותן או להתמודד איתן.1 419
# Count cows by counting occurrences of each digit in both sequences
# and taking the minimum, then subtracting bulls
secret_counts: dict[int, int] = {}
guess_counts: dict[int, int] = {}
for digit in self.secret_code:
secret_counts[digit] = secret_counts.get(digit, 0) + 1
for digit in guess:
guess_counts[digit] = guess_counts.get(digit, 0) + 1
total_matches = sum(min(secret_counts.get(digit, 0), guess_counts.get(digit, 0))
for digit in set(secret_counts.keys()) | set(guess_counts.keys()))
cows = total_matches - bulls
# Store the guess and result
self.guesses.append(guess.copy())
self.results.append((bulls, cows))
return bulls, cows
כל זה בשביל לספור כמה ספרות מופיעות במקום הנכון, וכמה ספרות מופיעות במספר אבל באינדקס אחר. זה קוד שלי שפותר את אותה בעיה:
def compare(guess, code):
bulls = 0
cows = 0
for i in range(len(code)):
if guess[i] == code[i]:
cows += 1
elif guess[i] in code:
bulls += 1
return (bulls, cows)
הדרך שקלוד החליט שצריך לחשב את מספר הפגיעות מנוסחת בהערה המוזרה הזאת:
> Count cows by counting occurrences of each digit in both sequences and taking the minimum, then subtracting bulls.
גם אם הרעיון נכון הוא פשוט יותר מדי מסורבל לתרגיל הזה.
קוד ישן הוא קוד טוב
הטעות הבאה של AI שחוזרת כל פעם שהוא כותב קוד זו ההעדפה לקוד הקיים. קוד קיים הוא חלק מהפרומפט ולכן AI מאוד נזהר לא לגעת בכלום אלא אם כן ביקשתם במפורש וגם אז לא בטוח. בדוגמה הבאה ביקשתי מקלוד לכתוב קומפוננטה של קרוסלת תמונות שכל כמה שניות התמונה משתנה וקיבלתי את הקומפוננטה הבאה:
const ImageCarousel: React.FC<ImageCarouselProps> = ({ images, interval = 3000 }) => {
const [currentIndex, setCurrentIndex] = useState(0)
useEffect(() => {
if (images.length <= 1) return
const timer = setInterval(() => {
setCurrentIndex((prevIndex) => (prevIndex + 1) % images.length)
}, interval)
return () => clearInterval(timer)
}, [images.length, interval])
const goToSlide = (index: number) => {
setCurrentIndex(index)
}
const goToPrevious = () => {
setCurrentIndex((prevIndex) =>
prevIndex === 0 ? images.length - 1 : prevIndex - 1
)
}
const goToNext = () => {
setCurrentIndex((prevIndex) => (prevIndex + 1) % images.length)
}
if (images.length === 0) {
return <div className="carousel-empty">No images to display</div>
}
return (
<div className="carousel-container">
<div className="carousel-wrapper">
<button
className="carousel-btn carousel-btn-prev"
onClick={goToPrevious}
aria-label="Previous image"
>
‹
</button>
<div className="carousel-image-container">
<img
src={images[currentIndex]}
alt={\Slide ${currentIndex + 1}\}
className="carousel-image"
/>
</div>
<button
className="carousel-btn carousel-btn-next"
onClick={goToNext}
aria-label="Next image"
>
›
</button>
</div>
<div className="carousel-indicators">
{images.map((_, index) => (
<button
key={index}
className={\carousel-indicator ${index === currentIndex ? 'active' : ''}\}
onClick={() => goToSlide(index)}
aria-label={\Go to slide ${index + 1}\}
/>
))}
</div>
</div>
)
}
רואים את הבעיה? בואו נתמקד באפקט:
useEffect(() => {
if (images.length <= 1) return
const timer = setInterval(() => {
setCurrentIndex((prevIndex) => (prevIndex + 1) % images.length)
}, interval)
return () => clearInterval(timer)
}, [images.length, interval])1 419
שלוש הטיות של AI שחשוב להכיר כשכותבים קוד
כולם מתלוננים על הקוד הגרוע ש AI מייצר אבל מה זה בדיוק אומר? מתי ה AI טועה? ואיך בדיוק הוא מסבך את התוכניות שלנו? מחר בעשר בבוקר אני אעביר וובינר של שעה עם הסברים ודוגמאות ספציפיים על ההטיות של AI בכתיבת קוד ולמה חשוב לשים לב כשאנחנו נעזרים בו בקידוד. מודעות והיכרות עם הטיות אלה יכולה לעשות את ההבדל בין קידוד אפקטיבי עם AI לבזבוז זמן, כי כשאנחנו יודעים למה לצפות אנחנו יודעים לתקן את זה. אם מסתדר לכם מוזמנים להצטרף אלינו בזום - צריך רק להירשם כאן ומקבלים קישור למייל:
https://tocode.ravpage.co.il/tocodeai
עכשיו בואו נראה את עיקרי הדברים.
העדפה לתכנות מונחה עצמים
אתגר ראשון בעבודה עם AI הוא ההעדפה שלו לגישת Object Oriented. על פניו תכנות מונחה עצמים היא גישה פופולרית בתכנות, שפות רבות משתמשות בה בתור פרדיגמה מובילה או אף יחידה ומצופה ממפתחים להכיר את הפרדיגמה.
אבל הבעיה היא ה"איך". בחירת הקלאסים והגדרת האבסטרקציות דורשת היכרות עם המערכת, ניסיון והרבה פעמים חשיבה יצירתית. כש AI מארגן קוד לקלאסים הוא מפספס הזדמנויות לקלאסים טובים, מייצר כפל קוד בין קלאסים ומגדיר קלאסים שיהיה קשה להתאים אותם לתנאים המשתנים בעתיד.
דוגמה ראשונה היא Rails ו Stimulus - ביקשתי מ AI לכתוב מונה לחיצות ב Stimulus וקיבלתי את הקוד הבא:
import { Controller } from "@hotwired/stimulus"
// Connects to data-controller="click-counter"
export default class extends Controller {
static targets = ["count"]
static values = { count: Number }
connect() {
// Initialize count if not set
if (!this.hasCountValue) {
this.countValue = 0
}
}
increment() {
this.countValue++
}
countValueChanged() {
this.countTarget.textContent = this.countValue
}
}
מדובר בקלאס JavaScript וצריך להגיד - הקוד עובד. קלוד שמע מונה לחיצות ומיד יצר קלאס שמספר הלחיצות הוא משתנה Instance Variable בתוך הקלאס. הבעיה? הערך של מספר הלחיצות כבר כתוב ב DOM בתוך האלמנט this.countTarget. אפשר לראות אפילו בקוד שנוצר שכל מה שהוא עושה שם זה להעלות את הערך של אותו משתנה this.countValue ואז לכתוב אותו ל textContent של האלמנט.
קוד נכון וקצר יותר יהיה:
import { Controller } from "@hotwired/stimulus"
// Connects to data-controller="click-counter"
export default class extends Controller {
static targets = ["count"]
increment() {
this.countTarget.textContent++
}
}
ההטיה של AI לכיוון פיתוח מונחה עצמים והכמסת מידע גרמו ליצירת קוד מנופח שיהיה קשה יותר לשנות ולתחזק בעתיד.
מסובך יותר טוב מפשוט
בזן של פייתון כתוב Simple is better than Complex אבל אצל AI הסיפור הוא הפוך - איפה שאפשר לבנות פיתרון לבעיה מסובכת יותר הוא יעדיף את הפיתרון המסובך. איפה שיש קוד מסובך שפותר בעיה זה מקבל עדיפות.
בדוגמה ראשונה ביקשתי מקלוד לייצר משחק איקס עיגול נגד המחשב. בלי לציין איך לממש את שחקן המחשב, קלוד בחר לממש אלגוריתם min-max כדי לייצר את שחקן המחשב הטוב ביותר שהוא מכיר. בהשוואה לבני אדם, כל התלמידים האנושיים שלי בקורסי פייתון שקיבלו משימה לממש איקס עיגול מימשו קודם שחקן מחשב שזז באופן אקראי ורק אחר כך כמשימת בונוס את שחקן המחשב החכם.
בדוגמה שניה ביקשתי משחק בול פגיעה. זה הקוד שקלוד יצר כדי לזהות כמה בולים וכמה פגיעות יש בניחוש מסוים:
def evaluate_guess(self, guess: List[int]) -> Tuple[int, int]:
"""
Evaluate a guess and return the number of bulls and cows.
Args:
guess: List of integers representing the guess
Returns:
Tuple of (bulls, cows) where:
- Bulls: correct digits in correct positions
- Cows: correct digits in wrong positions
"""
if len(guess) != self.code_length:
raise ValueError(f"Guess must be {self.code_length} digits long")
if not all(self.min_digit <= digit <= self.max_digit for digit in guess):
raise ValueError(f"All digits must be between {self.min_digit} and {self.max_digit}")
bulls = sum(1 for i in range(self.code_length) if guess[i] == self.secret_code[i])1 419
התחושה שהנה יש כלי חדש שנקרא AI והוא יפתור לנו את כל הבעיות מגיעה מהייפ גדול סביב ה AI
ואז כשאנשים באים להשתמש בזה הם מגלים שיש עקומת למידה ושאפילו אחרי עקומת הלמידה הם כן מהירים יותר אבל לא פי 100 וגם לא פי 10
אני האחרון שיזלזל ב AI. אלה כלים מדהימים. אבל צריך להגיד
לא כל ההייפ מוצדק
מתכנתים לא הולכים להיעלם
יש עקומת למידה
1 419
קטע מתוך מייל ששלח אדם וות׳ן (היוצר של טיילווינד) על פרויקט שהם בנו - שימו לב ל AI
But even with all this effort, the results were honestly so inconsistent that I'm absolutely certain that reviewing + polishing all of the work done by the robots took more time than if we just did every single block by hand in the first place 😆 We signed up for this project thinking that with AI we could do it in maybe ~6 weeks, and it turned out to be more like ~12 weeks.
1 419
טיפ פייתון - הרצת תוכנית והחזרת התוצאה
הפקודה eval בפייתון מריצה פקודה בודדת ומחזירה את התוצאה:
result = eval('2 + 5')
אבל בניגוד ל JavaScript, ה eval של פייתון מקבל רק פקודה אחת. זה לא עובד:
result = eval("""
import os
os.name
""")
במקום eval, הפקודה exec יודעת לקבל קוד ולהריץ אותו. הבעיה עם exec היא שהיא לא מחזירה ערך ולכן בשביל להשתמש בה אני ארצה בתוך הקוד שאני מריץ לשים ערך לתוך גלובאלי. אני מעביר ל exec מילון בתור פרמטר שני וכל המשתנים הגלובאליים יישמרו לאותו מילון. זה נראה ככה:
ns = {}
exec("""
import os
result = os.name
""")
print(ns['result'])
לסיום הרבה פעמים נרצה לעטוף את ה exec ב try/except כדי לטפל בשגיאות תחביר לדוגמה:
try:
ns = {}
exec("""
import os
result = os.name
""")
print(ns['result'])
except SyntaxError as e:
print(f"Syntax error: {e}")
פקודת exec יכולה לעזור כשאני רוצה לטעון קונפיגורציה מקובץ שנראה כמו פייתון לדוגמה קובץ כזה:
* settings.conf *
font_face = ""
font_size = 10
line_numbers = True
tab_size = 4
auto_indent = True
הפעלת הקובץ ב exec והעברת מילון ריק בפרמטר השני תמלא את המילון במפתחות מהקובץ. נשים לב שגם exec וגם eval מגיעים עם סיכוני אבטחה משמעותיים ויש להיזהר ולהפעיל אותם רק בתוך סביבת sandbox. אפילו אם אנחנו רק רוצים להריץ קוד ש AI יצר מתוך פרומפט שאני שלחתי.
למידע נוסף ועוד דוגמאות על exec שווה לקרוא כאן:
https://realpython.com/python-exec/1 419
אין עקומת לימוד
זה מרגיש ככה עם AI לפעמים, לא?
שפת התכנות הראשונה שלמדתי נקראה Turbo Pascal. היה לי ספר בשם המדריך השלם ל Turbo Pascal 6 והיו בו הסברים וקטעי קוד והייתי מעתיק קטעי קוד מהספר למחשב ומנסה להבין מההסברים מה כל דבר עושה וגם לשנות את הקוד. אפילו לכתוב תוכניות פשוטות לקח הרבה זמן וכל שינוי קטן היה כרוך בהמון ניסיונות שלא עבדו.
עברנו הרבה מאז.
היום אפשר להיכנס לקופיילוט או קרסר או בייס44 ולקבל את התוכנית שאתה רוצה, לבקש שינוי ולקבל אותו. בלי טעויות תחביר, בלי בעיות קומפילציה ועם הסבר מלא ובעברית מה כל שורה עושה.
לא פלא שאנשים חכמים כותבים:
> Learning how to use LLMs in a coding workflow is trivial
אם עברת את כל הדרך שאנחנו עברנו. אם אתה כבר יודע לכתוב קוד, אז AI יסבך אותך? אתה רק כותב שאלה באנגלית ומקבל תשובה. מה יותר קל מזה? כששאלתי חבר אחר איך הם מתכוננים לשילוב קופיילוט בצוותי הפיתוח הגישה היתה "פשוט ניתן למתכנתים גישה והם כבר יבינו מה צריך לעשות". חבר אחר הסביר לי שזה פשוט "טאב טאב טאב".
אבל אז הפוסט מסתיים עם התלונה:
> Every time I tried using an LLM for core features of applications I develop at work, the implementations were questionable and I spent at least as much time rewriting the code than I would have spent writing it from scratch.
ולמעשה זאת התלונה שאני שומע הכי הרבה פעמים ממפתחים שעובדים עם AI כשאני שואל איך הולך עם זה.
עקומת הלימוד של AI מבלבלת. כשרוכבים על אופניים אתה יודע אם אתה מצליח כי אחרת אתה נופל. כשלמדתי לכתוב קוד ולא הצלחתי התוכנית לא רצה או זרקה שגיאות. אבל AI? אם הוא לא נותן תוצאה מספיק טובה מיד אומרים שזה בגלל שיש יותר מדי הייפ, שכלי AI לא חכמים מספיק או סיפור דומה.
כדאי לזכור:
1. גם ל AI יש עקומת לימוד.
2. אף אחד לא יכול להחליף מתכנתים ב AI.
3. היכרות עם היכולות, המגבלות ואופן העבודה של AI משפרת משמעותית את התוצאה שמקבלים מהכלי.
¡Ya disponible! Investigación de Telegram 2025 — los principales insights del año 
