মরিচায় ডিফল্ট ফাংশন যুক্তি


101

ডিস্টেল আর্গুমেন্ট দিয়ে কোনও ফাংশন তৈরি করা কি জাস্টে সম্ভব?

fn add(a: int = 1, b: int = 2) { a + b }

4
# 6973 টি বেশ কয়েকটি কাজের আশেপাশে রয়েছে (স্ট্রাক ব্যবহার করে)।
Huon

2020 সালে, আপনি এটি কোড করতে পারেন কিভাবে?
পুঁতেদিয়াজ

@puentesdias মেনে নেওয়া উত্তর এখনও সঠিক উত্তর। মরিচায় এটি করার কোনও উপায় নেই এবং আপনাকে ম্যাক্রো লিখতে হবে, অথবা ব্যবহার করতে হবে Optionএবং স্পষ্টভাবে পাস করতে হবে None
জেরোইন

উত্তর:


55

না, এটি বর্তমানে নেই। আমি মনে করি এটি সম্ভবত শেষ পর্যন্ত বাস্তবায়িত হবে তবে বর্তমানে এই জায়গাতে কোনও সক্রিয় কাজ নেই।

এখানে নিযুক্ত সাধারণ কৌশলটি বিভিন্ন নাম এবং স্বাক্ষর সহ ফাংশন বা পদ্ধতি ব্যবহার করা use


4
@ নারেকএক্স 652: তবে নোট করুন যে পদ্ধতিটি সরকারীভাবে নিরুৎসাহিত হয়েছে।
ক্রিস মরগান

@ ক্রিসমোরগান আপনার আনুষ্ঠানিকভাবে নিরুৎসাহিত হওয়ার কোনও উত্স আছে?
জেরোয়েন

4
@ জিরোইন বোলেন কয়েক মিনিটের সন্ধানে সেরা হিসাবে আমি আসতে পারছি তা হল reddit.com/r/rust/comments/556c0g/… , যেখানে আপনারা ব্রাসনের মতো লোক ছিলেন যারা সেই সময় মরিচা প্রকল্পের নেতা ছিলেন। আইআরসি আরও থাকতে পারে, নিশ্চিত না।
ক্রিস মরগান

107

যেহেতু ডিফল্ট আর্গুমেন্টগুলি সমর্থন করে না আপনি ব্যবহার করে অনুরূপ আচরণ পেতে পারেন 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);

দুটি সমাধানের মধ্যে বড় পার্থক্যটি হ'ল "বিকল্প" -র যুক্তিগুলির সাথে এটি লেখার পক্ষে সম্পূর্ণ বৈধ add(None, Some(4)), তবে ম্যাক্রো প্যাটার্নের সাথে মিলে আপনি পারবেন না (এটি পাইথনের ডিফল্ট আর্গুমেন্টের নিয়মের অনুরূপ)।

আপনি "আর্গুমেন্ট" কাঠামো এবং 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)));
}

এই পছন্দটি অবশ্যই অনেক বেশি কোড, তবে ম্যাক্রো ডিজাইনের বিপরীতে এটি টাইপ সিস্টেমটি ব্যবহার করে যার অর্থ সংকলক ত্রুটিগুলি আপনার গ্রন্থাগার / এপিআই ব্যবহারকারীর জন্য আরও সহায়ক হবে। এটি Fromযদি ব্যবহারকারীদের পক্ষে সহায়ক হয় তবে তারা তাদের নিজস্ব বাস্তবায়ন করতে দেয়।


4
এই উত্তরটি বেশ কয়েকটি উত্তর হিসাবে ভাল হবে, প্রতিটি পদ্ধতির জন্য একটি। আমি তাদের শুধু একটা ভোট দিন করতে চান
জোএল

56

না, মরিচ ডিফল্ট ফাংশন যুক্তি সমর্থন করে না। আপনাকে বিভিন্ন নাম সহ বিভিন্ন পদ্ধতি নির্ধারণ করতে হবে। উভয়ই কোনও ক্রিয়াকলাপের ওভারলোডিং নেই, কারণ মরচে ধরণের ফাংশনের নামগুলি প্রকারভেদ করতে ব্যবহার করে (ফাংশন ওভারলোডিং এর বিপরীতে প্রয়োজন)।

স্ট্রাক্ট ইনিশিয়ালাইজের ক্ষেত্রে আপনি স্ট্রাক আপডেট সিনট্যাক্সটি এটির মতো ব্যবহার করতে পারেন:

use std::default::Default;

#[derive(Debug)]
pub struct Sample {
    a: u32,
    b: u32,
    c: u32,
}

impl Default for Sample {
    fn default() -> Self {
        Sample { a: 2, b: 4, c: 6}
    }
}

fn main() {
    let s = Sample { c: 23, .. Sample::default() };
    println!("{:?}", s);
}

[অনুরোধে, আমি একটি সদৃশ প্রশ্ন থেকে এই উত্তরটি ক্রস পোস্ট করেছি]


4
এটি ডিফল্ট আর্গুমেন্টগুলির জন্য খুব ব্যবহারযোগ্য প্যাটার্ন। উচ্চতর হওয়া উচিত
বেন

9

মরিচা ডিফল্ট ফাংশন আর্গুমেন্টকে সমর্থন করে না এবং আমি বিশ্বাস করি না এটি ভবিষ্যতে বাস্তবায়িত হবে। সুতরাং আমি ম্যাক্রো আকারে এটি বাস্তবায়নের জন্য একটি প্রো_ম্যাক্রো দুআআং লিখেছি ।

উদাহরণ স্বরূপ:

duang! ( fn add(a: i32 = 1, b: i32 = 2) -> i32 { a + b } );
fn main() {
    assert_eq!(add!(b=3, a=4), 7);
    assert_eq!(add!(6), 8);
    assert_eq!(add(4,5), 9);
}

7

আপনি যদি মরিচা ১.১২ বা তার বেশি ব্যবহার করে থাকেন তবে আপনি কমপক্ষে ফাংশন আর্গুমেন্টগুলি এর সাথে 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);
}

7
প্রযুক্তিগতভাবে সঠিক হওয়ার পরেও মরিচা সম্প্রদায়টি এটি একটি "ভাল" ধারণা কিনা তা নিয়ে কথায় কথায় বিভক্ত। আমি ব্যক্তিগতভাবে "ভাল না" শিবিরে পড়ি।
শিপমাস্টার

4
@ শেপমাস্টার এটি কোডের আকার বাড়িয়ে তুলতে পারে, এবং এটি সুপার পঠনযোগ্য নয়। সেই প্যাটার্নটি ব্যবহার করার ক্ষেত্রে কি তাদের আপত্তি রয়েছে? আমি এখনও অবধি ট্রেড-অফগুলি এর্গোনমিক এপিআইয়ের সেবায় সার্থক হিসাবে খুঁজে পেয়েছি তবে বিবেচনা করব যে আমি অন্য কিছু গোটাচা মিস করছি।
স্কুইডপিকলস

2

অন্য উপায় হতে পারে বৈকল্পিক হিসাবে alচ্ছিক প্যারামগুলির সাথে একটি এনাম ঘোষণা করা, যা প্রতিটি বিকল্পের জন্য সঠিক ধরণের নিতে প্যারামিটারাইজ করা যেতে পারে। এনাম ভেরিয়েন্টগুলির একটি পরিবর্তনশীল দৈর্ঘ্যের টুকরো নিতে ফাংশনটি প্রয়োগ করা যেতে পারে। এগুলি যে কোনও ক্রম এবং দৈর্ঘ্যে হতে পারে। ডিফল্টগুলি প্রাথমিক কার্যাদি হিসাবে ফাংশনটির মধ্যে প্রয়োগ করা হয়।

enum FooOptions<'a> {
    Height(f64),
    Weight(f64),
    Name(&'a str),
}
use FooOptions::*;

fn foo(args: &[FooOptions]) {
    let mut height   = 1.8;
    let mut weight   = 77.11;
    let mut name     = "unspecified".to_string();

    for opt in args {
        match opt {
            Height(h) => height = *h,
            Weight(w) => weight = *w,
            Name(n)   => name   =  n.to_string(),
        }
    }
    println!("  name: {}\nweight: {} kg\nheight: {} m", 
             name, weight, height);
}

fn main() { 

            foo( &[ Weight(90.0), Name("Bob") ] );

}

আউটপুট:

  name: Bob
weight: 90 kg
height: 1.8 m
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.