Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> Ruby

ทำไม Ruby จึงใช้ ARGV: การเข้าใจ Argument Vectors ใน Ruby

คุณอาจรู้ว่า Ruby ใส่อาร์กิวเมนต์บรรทัดคำสั่งลงในอาร์เรย์สากลชื่อ ARGV แต่ทำไมมันถึงเรียกว่า ARGV? นี่เป็นบทเรียนประวัติศาสตร์น่าสนใจที่เน้นที่รากฐานของ Ruby ในภาษา C

Argument Vector (เวกเตอร์อาร์กิวเมนต์)

ARGV ย่อมาจาก Argument Vector และ "Vector" ในความหมายเก่าๆ นี้หมายถึง "อาร์เรย์มิติเดียว"

ในภาษา C ทุกโปรแกรมมีฟังก์ชัน main() ซึ่งมักจะมีลักษณะประมาณนี้:

int main(int argc, char *argv[]) {
  ... your code here
}

คุณอาจสังเกตเห็นว่าฟังก์ชัน main มีอาร์กิวเมนต์ 2 ตัว ซึ่งคือ จำนวน (count) และอาร์เรย์ของอาร์กิวเมนต์บรรทัดคำสั่ง ตามลำดับ

เมื่อคุณสั่งให้ bash รันโปรแกรม มันจะทำ system call ซึ่งทำให้ OS เรียกฟังก์ชัน main ของโปรแกรมคุณและส่งค่า argc และ argv เข้าไป

Ruby

Ruby interpreter — MRI อย่างน้อย — เป็นเพียงโปรแกรม C นี่คือฟังก์ชัน main ของ Ruby:

int main(int argc, char **argv) {
  #ifdef RUBY_DEBUG_ENV
  ruby_set_debug_option(getenv("RUBY_DEBUG"));
  #endif
  #ifdef HAVE_LOCALE_H
  setlocale(LC_CTYPE, "");
  #endif
  ruby_sysinit(&argc, &argv);
  {
    RUBY_INIT_STACK;
    ruby_init();
    return ruby_run_node(ruby_options(argc, argv));
  }
}

เห็นได้ชัดว่า มันส่ง argc และ argv ไปยังฟังก์ชัน ruby_options ซึ่งเรียก ruby_process_options ซึ่งเรียก process_options

ฟังก์ชันนี้จัดการออปชันของ Ruby interpreter ทั้งหมด และในที่สุดเรียก ruby_set_argv ซึ่งตั้งค่า ARGV ที่คุณเห็นในโค้ด Ruby ของคุณ

void ruby_set_argv(int argc, char **argv) {
  int i;
  VALUE av = rb_argv;
  #if defined(USE_DLN_A_OUT)
  if (origarg.argv)
    dln_argv0 = origarg.argv[0];
  else
    dln_argv0 = argv[0];
  #endif
  rb_ary_clear(av);
  for (i = 0; i < argc; i++) {
    VALUE arg = external_str_new_cstr(argv[i]);
    OBJ_FREEZE(arg);
    rb_ary_push(av, arg);
  }
}

ค่อนข้างสะดวก ผมยังใหม่ในการดำดุ้นเข้า codebase ของ MRI แต่สนุกมากที่จะดูกันว่าสิ่งต่างๆ ทำงานอย่างไรจริงๆ