سؤال

هل من الممكن في Rust إنشاء دالة ذات وسيطة افتراضية؟

fn add(a: int = 1, b: int = 2) { a + b }
هل كانت مفيدة؟

المحلول

لا، إنه ليس في الوقت الحاضر.أعتقد أنه من المحتمل أن يتم تنفيذها في نهاية المطاف، ولكن لا يوجد عمل نشط في هذه المساحة في الوقت الحالي.

التقنية النموذجية المستخدمة هنا هي استخدام الوظائف أو الأساليب بأسماء وتوقيعات مختلفة.

نصائح أخرى

نظرًا لأن الوسائط الافتراضية غير مدعومة، يمكنك الحصول على سلوك مماثل باستخدام Option<T>

fn add(a: Option<i32>, b: Option<i32>) -> i32 {
    a.unwrap_or(1) + b.unwrap_or(2)
}

يحقق هذا الهدف المتمثل في الحصول على القيمة الافتراضية والوظيفة المشفرة مرة واحدة فقط (بدلاً من كل مكالمة)، ولكن بالطبع هناك الكثير مما يجب كتابته.سيبدو استدعاء الوظيفة add(None, None), ، وهو ما قد يعجبك أو لا يعجبك حسب وجهة نظرك.

إذا رأيت عدم كتابة أي شيء في قائمة الوسيطات حيث من المحتمل أن ينسى المبرمج الاختيار، فإن الميزة الكبيرة هنا تكمن في الوضوح؛يقول المتصل صراحةً أنه يريد استخدام القيمة الافتراضية الخاصة بك، وسيحصل على خطأ في الترجمة إذا لم يضع أي شيء.فكر في الأمر على أنه كتابة add(DefaultValue, DefaultValue).

يمكنك أيضًا استخدام ماكرو:

fn add(a: i32, b: i32) -> i32 {
    a + b
}

macro_rules! add {
    ($a: expr) => {
        add($a, 2)
    };
    () => {
        add(1, 2)
    };
}
assert_eq!(add!(), 3);
assert_eq!(add!(4), 6);

الفرق الكبير بين الحلين هو أنه مع وسيطات "Option"-al تكون الكتابة صالحة تمامًا add(None, Some(4)), ، ولكن مع مطابقة نمط الماكرو لا يمكنك ذلك (وهذا مشابه لقواعد الوسيطة الافتراضية في Python).

يمكنك أيضًا استخدام بنية "الوسائط" و From/Into سمات:

pub struct FooArgs {
    a: f64,
    b: i32,
}

impl Default for FooArgs {
    fn default() -> Self {
        FooArgs { a: 1.0, b: 1 }
    }
}

impl From<()> for FooArgs {
    fn from(_: ()) -> Self {
        Self::default()
    }
}

impl From<f64> for FooArgs {
    fn from(a: f64) -> Self {
        Self {
            a: a,
            ..Self::default()
        }
    }
}

impl From<i32> for FooArgs {
    fn from(b: i32) -> Self {
        Self {
            b: b,
            ..Self::default()
        }
    }
}

impl From<(f64, i32)> for FooArgs {
    fn from((a, b): (f64, i32)) -> Self {
        Self { a: a, b: b }
    }
}

pub fn foo<A>(arg_like: A) -> f64
where
    A: Into<FooArgs>,
{
    let args = arg_like.into();
    args.a * (args.b as f64)
}

fn main() {
    println!("{}", foo(()));
    println!("{}", foo(5.0));
    println!("{}", foo(-3));
    println!("{}", foo((2.0, 6)));
}

من الواضح أن هذا الاختيار يحتوي على الكثير من التعليمات البرمجية، ولكن على عكس تصميم الماكرو، فإنه يستخدم نظام الكتابة مما يعني أن أخطاء المترجم ستكون أكثر فائدة لمستخدم مكتبتك/واجهة برمجة التطبيقات (API).وهذا يسمح أيضًا للمستخدمين بصنع منتجاتهم الخاصة From التنفيذ إذا كان ذلك مفيدًا لهم.

لا، لا يدعم الصدأ حجج الوظيفة الافتراضية.يجب عليك تحديد طرق مختلفة بأسماء مختلفة.لا توجد حملة زائدة من الوظيفة إما، لأن أسماء وظيفة استخدام الصدأ للاستمتاع بأنواعها (تتطلب التحميل الزائد الوظيفي العكس).

في حالة تهيئة البنية، يمكنك استخدام بناء جملة تحديث الهيكل مثل هذا:

giveacodicetagpre.

[عند الطلب، أرسلت هذه الإجابة من سؤال مكررة]

إذا كنت تستخدم Rust 1.12 أو إصدار أحدث، فيمكنك على الأقل تسهيل استخدام وسائط الدالة Option و into():

fn add<T: Into<Option<u32>>>(a: u32, b: T) -> u32 {
    if let Some(b) = b.into() {
        a + b
    } else {
        a
    }
}

fn main() {
    assert_eq!(add(3, 4), 7);
    assert_eq!(add(8, None), 8);
}

الصدأ لا يدعم وسيطات الوظائف الافتراضية، ولا أصدق أنه سيتم تنفيذه في المستقبل. لذلك كتبت proc_macro Duang لتطبيقه في نموذج الماكرو.

على سبيل المثال:

giveacodicetagpre.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top