জাস্টে বৈশ্বিক চলকগুলি ব্যবহার করা কি সম্ভব?


108

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

মরিচ শিখতে, আমি বর্তমানে গিটহাবের স্ক্লাইট 3 এবং মরিচা / স্ক্লাইট 3 প্যাকেজ ব্যবহার করে একটি ডাটাবেস পরীক্ষা প্রোগ্রাম লিখছি। ফলস্বরূপ, এটি প্রয়োজনীয় (আমার পরীক্ষা-প্রোগ্রামে) (বৈশ্বিক ভেরিয়েবলের বিকল্প হিসাবে), যেখানে প্রায় এক ডজন রয়েছে তার কার্যকারিতাগুলির মধ্যে ডাটাবেস ভেরিয়েবল পাস করার জন্য। নীচে একটি উদাহরণ।

  1. জাস্টে বৈশ্বিক চলকগুলি ব্যবহার করা কি সম্ভব এবং সম্ভব এবং সম্ভাব্য?

  2. নীচের উদাহরণটি দেওয়া, আমি কী বিশ্বব্যাপী ভেরিয়েবল ঘোষণা করতে এবং ব্যবহার করতে পারি?

extern crate sqlite;

fn main() {
    let db: sqlite::Connection = open_database();

    if !insert_data(&db, insert_max) {
        return;
    }
}

আমি নিম্নলিখিতগুলি চেষ্টা করেছিলাম, তবে এটি পুরোপুরি সঠিক বলে মনে হচ্ছে না এবং নীচের ত্রুটিগুলির ফলস্বরূপ (আমি একটি unsafeব্লক দিয়ে চেষ্টাও করেছি ):

extern crate sqlite;

static mut DB: Option<sqlite::Connection> = None;

fn main() {
    DB = sqlite::open("test.db").expect("Error opening test.db");
    println!("Database Opened OK");

    create_table();
    println!("Completed");
}

// Create Table
fn create_table() {
    let sql = "CREATE TABLE IF NOT EXISTS TEMP2 (ikey INTEGER PRIMARY KEY NOT NULL)";
    match DB.exec(sql) {
        Ok(_) => println!("Table created"),
        Err(err) => println!("Exec of Sql failed : {}\nSql={}", err, sql),
    }
}

সংকলনের ফলে প্রাপ্ত ত্রুটিগুলি:

error[E0308]: mismatched types
 --> src/main.rs:6:10
  |
6 |     DB = sqlite::open("test.db").expect("Error opening test.db");
  |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected enum `std::option::Option`, found struct `sqlite::Connection`
  |
  = note: expected type `std::option::Option<sqlite::Connection>`
             found type `sqlite::Connection`

error: no method named `exec` found for type `std::option::Option<sqlite::Connection>` in the current scope
  --> src/main.rs:16:14
   |
16 |     match DB.exec(sql) {
   |              ^^^^


আমার এখানে নোট করা উচিত যে ওপি যে ত্রুটিগুলি অনুভব করছে তা Connectionএকটি Option<Connection>ধরণের অভ্যন্তর সংরক্ষণের চেষ্টা এবং একটি Option<Connection>হিসাবে ব্যবহার করার চেষ্টা করে Connection। যদি এই ত্রুটিগুলি সমাধান করা হয় (ব্যবহার করে Some()) এবং তারা একটি unsafeব্লক ব্যবহার করেছিল, যেমন তারা মূলত চেষ্টা করেছিল, তাদের কোডটি কাজ করবে (থ্রেড-অনিরাপদভাবে হলেও)।
TheHansinator

উত্তর:


67

এটি সম্ভব তবে সরাসরি কোনও গাদা বরাদ্দ অনুমোদিত নয়। গাদা বরাদ্দ রানটাইম এ সঞ্চালিত হয়। এখানে কিছু উদাহরণ আছে:

static SOME_INT: i32 = 5;
static SOME_STR: &'static str = "A static string";
static SOME_STRUCT: MyStruct = MyStruct {
    number: 10,
    string: "Some string",
};
static mut db: Option<sqlite::Connection> = None;

fn main() {
    println!("{}", SOME_INT);
    println!("{}", SOME_STR);
    println!("{}", SOME_STRUCT.number);
    println!("{}", SOME_STRUCT.string);

    unsafe {
        db = Some(open_database());
    }
}

struct MyStruct {
    number: i32,
    string: &'static str,
}

13
সঙ্গে static mutবিকল্প, তার মানে যে কোড সংযোগ ব্যবহার করে প্রতিটি স্থানের অনিরাপদ হিসাবে চিহ্নিত করা হয়েছে কি?
কামেক

4
@ কামেক প্রাথমিক প্রবেশাধিকারটি অনিরাপদ হতে হবে। আমি এটি মাস্ক করার জন্য সাধারণত ম্যাক্রোর একটি পাতলা মোড়ক ব্যবহার করি।
jhpratt

48

যতক্ষণ না তারা থ্রেড-লোকাল হয় ততক্ষণ আপনি স্ট্যাটিক ভেরিয়েবলগুলি মোটামুটি সহজেই ব্যবহার করতে পারেন।

অবক্ষয়টি হ'ল আপনার প্রোগ্রামটি অন্য থ্রেডগুলিতে দৃশ্যমান হবে না the উত্সাহটি হ'ল সত্যিকারের বিশ্বব্যাপী রাষ্ট্রের বিপরীতে, এটি সম্পূর্ণ নিরাপদ এবং ব্যবহারের জন্য কোনও ব্যথা নয় - সত্যিকারের বিশ্বব্যাপী রাষ্ট্র যে কোনও ভাষায় একটি ব্যথা। এখানে একটি উদাহরণ:

extern mod sqlite;

use std::cell::RefCell;

thread_local!(static ODB: RefCell<sqlite::database::Database> = RefCell::new(sqlite::open("test.db"));

fn main() {
    ODB.with(|odb_cell| {
        let odb = odb_cell.borrow_mut();
        // code that uses odb goes here
    });
}

এখানে আমরা একটি থ্রেড-স্থানীয় স্ট্যাটিক ভেরিয়েবল তৈরি করি এবং তারপরে এটি কোনও ফাংশনে ব্যবহার করি। নোট করুন যে এটি স্থির এবং অপরিবর্তনীয়; এর অর্থ এই যে ঠিকানাটিতে এটি অবস্থান করে তা স্থাবর, তবে RefCellমানটির জন্য ধন্যবাদ নিজেই পরিবর্তনযোগ্য হবে।

নিয়মিত ভিন্ন static, এ thread-local!(static ...)আপনি ঐ যে যেমন আরম্ভের জন্য গাদা বরাদ্দ প্রয়োজন সহ প্রায় কাছাকাছি নির্বিচারে বস্তু তৈরি করতে পারেন, Vec, HashMapএবং অন্যদের।

আপনি যদি এখনই মানটি আরম্ভ করতে না পারেন, উদাহরণস্বরূপ এটি ব্যবহারকারীর ইনপুটের উপর নির্ভর করে, আপনাকে Optionসেখানেও ফেলে দিতে হতে পারে , সেক্ষেত্রে এটি অ্যাক্সেস করা কিছুটা অনর্থক হয়ে যায়:

extern mod sqlite;

use std::cell::RefCell;

thread_local!(static ODB: RefCell<Option<sqlite::database::Database>> = RefCell::New(None));

fn main() {
    ODB.with(|odb_cell| {
        // assumes the value has already been initialized, panics otherwise
        let odb = odb_cell.borrow_mut().as_mut().unwrap();
        // code that uses odb goes here
    });
}

23

তাকান constএবং staticমরচে বইয়ের অধ্যায়

আপনি নিম্নলিখিত হিসাবে কিছু ব্যবহার করতে পারেন:

const N: i32 = 5; 

বা

static N: i32 = 5;

গ্লোবাল স্পেসে।

তবে এগুলি পরিবর্তনযোগ্য নয়। পরিবর্তনের জন্য, আপনি এর মতো কিছু ব্যবহার করতে পারেন:

static mut N: i32 = 5;

তারপরে এগুলি উল্লেখ করুন:

unsafe {
    N += 1;

    println!("N: {}", N);
}

4
দয়া করে const Var: Tyএবং এর মধ্যে পার্থক্যটি ব্যাখ্যা করবেন static Var: Ty?
নওয়াজ

6

আমি মরচে নতুন, কিন্তু এই সমাধানটি কার্যকর বলে মনে হচ্ছে:

#[macro_use]
extern crate lazy_static;

use std::sync::{Arc, Mutex};

lazy_static! {
    static ref GLOBAL: Arc<Mutex<GlobalType> =
        Arc::new(Mutex::new(GlobalType::new()));
}

আরেকটি সমাধান হ'ল ক্রসবিয়াম চ্যানেল টিএক্স / আরএক্স জুটিকে একটি অপরিবর্তনীয় বৈশ্বিক পরিবর্তনশীল হিসাবে ঘোষণা করা। চ্যানেলটি আবদ্ধ হওয়া উচিত এবং কেবলমাত্র 1 টি উপাদান থাকতে পারে। আপনি যখন গ্লোবাল ভেরিয়েবলটি আরম্ভ করবেন, তখন চ্যানেলটিতে গ্লোবাল দৃষ্টান্তটি চাপুন। গ্লোবাল ভেরিয়েবল ব্যবহার করার সময়, এটি অর্জন করতে চ্যানেলটি পপ করুন এবং এটি ব্যবহার করার পরে এটি পিছনে চাপ দিন।

উভয় সমাধানের বৈশ্বিক ভেরিয়েবলগুলি ব্যবহারের জন্য একটি নিরাপদ দৃষ্টিভঙ্গি সরবরাহ করা উচিত।


11
&'static Arc<Mutex<...>>এটির কোনও কারণ নেই কারণ এটি কখনই ধ্বংস হতে পারে না এবং এটির ক্লোন করার কোনও কারণ নেই; আপনি শুধু ব্যবহার করতে পারেন &'static Mutex<...>
ট্রেন্টক্লা

1

যদি আপনি ব্যবহার গাদা বরাদ্দ স্ট্যাটিক ভেরিয়েবলের জন্য সম্ভব lazy_static ম্যাক্রো যেমন দেখা ডক্স

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

// Declares a lazily evaluated constant HashMap. The HashMap will be evaluated once and
// stored behind a global static reference.

use lazy_static::lazy_static;
use std::collections::HashMap;

lazy_static! {
    static ref PRIVILEGES: HashMap<&'static str, Vec<&'static str>> = {
        let mut map = HashMap::new();
        map.insert("James", vec!["user", "admin"]);
        map.insert("Jim", vec!["user"]);
        map
    };
}

fn show_access(name: &str) {
    let access = PRIVILEGES.get(name);
    println!("{}: {:?}", name, access);
}

fn main() {
    let access = PRIVILEGES.get("James");
    println!("James: {:?}", access);

    show_access("Jim");
}

একটি বিদ্যমান উত্তর ইতিমধ্যে অলস স্থির সম্পর্কে কথা বলে । বিদ্যমান উত্তরগুলির তুলনায় এই উত্তরটি কী মান নিয়ে আসে তা পরিষ্কার করে দেখানোর জন্য দয়া করে আপনার উত্তরটি সম্পাদনা করুন।
শেপমাস্টার
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.