ডিফভার স্কোপিং কোনও উদ্যোগ না নিয়ে আলাদাভাবে কেন কাজ করে?


10

ধরুন আমার কাছে একটি ফাইল রয়েছে যার নাম elisp-defvar-test.elরয়েছে:

;;; elisp-defvar-test.el ---  -*- lexical-binding: t -*- 

(defvar my-dynamic-var)

(defun f1 (x)
  "Should return X."
  (let ((my-dynamic-var x))
    (f2)))

(defun f2 ()
  "Returns the current value of `my-dynamic-var'."
  my-dynamic-var)

(provide 'elisp-dynamic-test)

;;; elisp-defvar-test.el ends here

আমি এই ফাইলটি লোড করি এবং তারপরে স্ক্র্যাচ বাফারে গিয়ে রান করুন:

(setq lexical-binding t)
(f1 5)
(let ((my-dynamic-var 5))
  (f2))

(f1 5)ফেরৎ 5 আশানুরূপ, যা নির্দেশ করে লাশ f1চিকিত্সা করা হয় my-dynamic-var, একটি পরিবর্তনশীল scoped পরিবর্তনশীল হিসাবে হিসাবে প্রত্যাশিত। যাইহোক, শেষ রূপটি একটি অকার্যকর-পরিবর্তনশীল ত্রুটি my-dynamic-varদেয়, এটি নির্দেশ করে যে এটি এই চলকটির জন্য লেক্সিকাল স্কোপিং ব্যবহার করছে। এটি ডকুমেন্টেশনের সাথে মতবিরোধের সাথে মনে হয় defvar, যা বলে:

defvarফর্ম এছাড়াও "বিশেষ" হিসাবে পরিবর্তনশীল ঘোষণা, এটা সবসময় পরিবর্তনশীল আবদ্ধ হয় যাতে এমনকি যদি lexical-bindingহল t।

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

এখানে ত্রুটি ব্যাকট্রেস দেওয়া আছে, যদি তা গুরুত্বপূর্ণ হয়:

Debugger entered--Lisp error: (void-variable my-dynamic-var)
  f2()
  (let ((my-dynamic-var 5)) (f2))
  (progn (let ((my-dynamic-var 5)) (f2)))
  eval((progn (let ((my-dynamic-var 5)) (f2))) t)
  elisp--eval-last-sexp(t)
  eval-last-sexp(t)
  eval-print-last-sexp(nil)
  funcall-interactively(eval-print-last-sexp nil)
  call-interactively(eval-print-last-sexp nil nil)
  command-execute(eval-print-last-sexp)

4
আমি মনে করি বাগ # 18059আলোচনাটি প্রাসঙ্গিক।
তুলসী

দুর্দান্ত প্রশ্ন, এবং হ্যাঁ, দয়া করে বাগ # 18059 এর আলোচনাটি দেখুন।
ড্র হয়েছে

আমি দেখতে পাচ্ছি, দেখে মনে হচ্ছে এটি ইম্যাক্স 26 এ সম্বোধনের জন্য ডকুমেন্টেশন আপডেট করা হবে
রায়ান সি থম্পসন

উত্তর:


8

দু'জনের সাথে কেন অন্যরকম আচরণ করা হয় তা বেশিরভাগ "কারণ আমাদের এটিই প্রয়োজন"। আরও সুনির্দিষ্টভাবে বলা যায় যে এর একক যুক্তি রূপটি defvarঅনেক আগে প্রকাশ পেয়েছিল, তবে পরে অন্যটির তুলনায় এটি মূলত একটি "হ্যাক" ছিল কম্পাইলার সতর্কতাগুলিকে নিঃশব্দ করার জন্য: মৃত্যুদন্ড কার্যকর করার সময় এর কোনও প্রভাব ছিল না, সুতরাং এটি "দুর্ঘটনা" হিসাবে বোঝানো হয়েছিল (defvar FOO)কেবলমাত্র বর্তমান ফাইলটিতে নিঃশব্দ আচরণ প্রয়োগ করা হয়েছে (যেহেতু সংকলকটি জানার কোনও উপায়ই ছিল না যে এই জাতীয় ডেফভারটি অন্য কোনও ফাইলে কার্যকর করা হয়েছিল)।

যখন lexical-bindingইমাস -২৪ এ প্রবর্তিত হয়েছিল, আমরা এই ফর্মটি পুনরায় ব্যবহার করার সিদ্ধান্ত নিয়েছি (defvar FOO), তবে এর দ্বারা বোঝা যাচ্ছে যে এটির এখন কোনও প্রভাব রয়েছে।

আংশিকভাবে পূর্ববর্তী "কেবলমাত্র বর্তমান ফাইলটিকে প্রভাবিত করে" আচরণটি সংরক্ষণ করার জন্য, তবে আরও গুরুত্বপূর্ণ বিষয় হল একটি লাইব্রেরিকে totoঅন্যান্য লাইব্রেরিগুলিকে totoলেক্সিকালি স্কোপযুক্ত ভেরি হিসাবে ব্যবহার না করা ব্যতীত গতিশীল- স্কোপযুক্ত ভেরি হিসাবে ব্যবহার করার অনুমতি দেওয়া (সাধারণত প্যাকেজ-উপসর্গ নামকরণ কনভেনশন সেগুলি এড়ানো হয়) দ্বন্দ্ব, তবে এটি সর্বত্র দুঃখের সাথে ব্যবহার করা হয়নি), এর নতুন আচরণটি (defvar FOO)কেবলমাত্র বর্তমান ফাইলটিতে প্রয়োগ করার জন্য সংজ্ঞায়িত করা হয়েছিল এবং এমনকি এটি পরিমার্জন করা হয়েছিল সুতরাং এটি কেবলমাত্র বর্তমান স্কোপের ক্ষেত্রে প্রযোজ্য (যেমন যদি এটি কোনও ফাংশনের মধ্যে প্রদর্শিত হয় তবে এটি কেবল ব্যবহারের উপর প্রভাব ফেলে) যে ফাংশন মধ্যে পৃথক)।

মূলত, (defvar FOO VAL)এবং (defvar FOO)কেবল দুটি "সম্পূর্ণ আলাদা" জিনিস। তারা কেবল keyতিহাসিক কারণে একই কীওয়ার্ডটি ব্যবহার করে।


1
উত্তরের জন্য +1। আইএমএইচও, তবে কমন লিস্পের পদ্ধতি আরও স্পষ্ট এবং আরও ভাল
ড্র হয়েছে

@ ড্রু: আমি বেশিরভাগ ক্ষেত্রেই একমত, কিন্তু পুনরায় ব্যবহার করা (defvar FOO)নতুন মোডকে পুরানো কোডের সাথে অনেক বেশি সামঞ্জস্য করে। এছাড়াও, আইআরসি-এর কমনলিস্পের সমাধানের সমস্যাটি হ'ল এলিস্পের মতো খাঁটি-দোভাষী এর জন্য এটি বেশ ব্যয়বহুল (উদাহরণস্বরূপ যখন আপনি কোনও বারের উপর প্রভাব ফেলেন এমন letক্ষেত্রে তার দেহের অভ্যন্তরে সন্ধান করতে হবে declare)।
স্টিফান 21

উভয় বিবেচনায় একমত
ড্র করেছেন

4

পরীক্ষার উপর ভিত্তি করে, আমি বিশ্বাস করি যে সমস্যাটি হ'ল (defvar VAR)কোনও দীক্ষাগুলির সাথে তার উপস্থিত গ্রন্থাগার (গুলি) তে কেবল তার প্রভাব পড়ে না।

আমি যখন যোগ (defvar my-dynamic-var)করার *scratch*বাফার, ত্রুটি আর ঘটেছে।

আমি প্রথমে ভেবেছিলাম যে এটি সেই ফর্মটি মূল্যায়নের কারণেই ছিল , তবে আমি প্রথমে লক্ষ্য করেছি যে কেবল সেই ফর্মটি উপস্থিত ফাইলটি পরিদর্শন করা যথেষ্ট ছিল; এবং তদুপরি যে বাফারে এই ফর্মটি কেবল যুক্ত (বা অপসারণ) করা হয়েছে তা মূল্যায়ন না(let ((my-dynamic-var 5)) (f2)) করে একই বাফারের সাথে মূল্যায়ন করার সময় যা ঘটেছিল তা পরিবর্তন করার পক্ষে যথেষ্ট ছিল eval-last-sexp

(এখানে কী ঘটছে সে সম্পর্কে আমার সত্যিকারের কোনও ধারণা নেই the আমি আচরণটি আশ্চর্যজনক মনে করি, তবে কীভাবে এই কার্যকারিতাটি বাস্তবায়িত হয় তার বিবরণ সম্পর্কে আমি অজানা।

আমি যুক্ত করব যে এই ফর্মটি defvar(কোনও আরম্ভ করে মান ছাড়াই) বাইট সংকলককে এলিজপ ফাইলটিতে একটি বাহ্যিক-সংজ্ঞায়িত ডায়নামিক ভেরিয়েবলের ব্যবহার সম্পর্কে অভিযোগ করা থেকে বিরত রাখে, তবে নিজস্বভাবে এটি পরিবর্তনশীল হওয়ার কারণ করে নাboundp ; সুতরাং এটি কঠোরভাবে পরিবর্তনশীল সংজ্ঞায়িত করা হয় না। (মনে রাখবেন যদি পরিবর্তনশীল ছিল boundp তারপর এই সমস্যা সব সময়ে ঘটতে না।)

বাস্তবে আমি এই ঠিক কাজ প্রদান করা যে আপনার যাচ্ছে অনুমান করা না অন্তর্ভুক্ত (defvar my-dynamic-var)কোন আভিধানিক-বাঁধাই গ্রন্থাগার যা আপনার ব্যবহার মধ্যে my-dynamic-varপরিবর্তনশীল (যা সম্ভবতঃ একটি বাস্তব সংজ্ঞা অন্যত্র হবে)।


সম্পাদনা:

মন্তব্যে @ এনপস্টাভসের পয়েন্টারকে ধন্যবাদ:

উভয় eval-last-sexpএবং ক্রম eval-defunব্যবহার eval-sexp-add-defvars:

বাফারে defvarএর আগে যে সমস্ত গুলি রয়েছে তার সাথে এক্সপ প্রস্তুত করুন ।

বিশেষ করে এটা সব অবস্থান নির্ণয় করে defvar, defconstএবং defcustomদৃষ্টান্ত। (এমনকি মন্তব্য করার সময়ও আমি লক্ষ্য করি))

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


2
IIUC, বাগ # 18059 আপনার সীমাবদ্ধতার বিষয়টি নিশ্চিত করে।
তুলসী

2
মনে হয় যে eval-sexp-add-defvarsবাফার পাঠ্যে ডিফারদের জন্য পরীক্ষা করে।
npostavs

1
+1 টি। স্পষ্টতই এই বৈশিষ্ট্যটি পরিষ্কার নয় বা ব্যবহারকারীদের কাছে স্পষ্টভাবে উপস্থাপন করা হয়নি। # 18059 বাগের জন্য ডক ফিক্সটি সহায়তা করে তবে এটি এখনও রহস্যজনক কিছু, যদিও ভঙ্গুর না হলেও ব্যবহারকারীদের জন্য।
ড্র হয়েছে

0

আমি এখানে মোটেও পুনরুত্পাদন করতে পারি না, উত্তরোত্তর স্নিপেটটি এখানে ঠিক সূক্ষ্মভাবে কাজ করে এবং প্রত্যাশার হিসাবে 5 ফেরত দেয়। আপনি কি নিশ্চিত যে আপনি my-dynamic-varনিজেরাই মূল্যায়ন করছেন না ? এটি ত্রুটি ছুঁড়ে দেবে কারণ ভেরিয়েবলটি শূন্য, এটি একটি মান হিসাবে সেট করা হয়নি এবং আপনি কেবল এটির সাথে গতিবদ্ধভাবে আবদ্ধ হলে এটির একটি থাকবে।


1
আপনি lexical-bindingফর্মগুলি মূল্যায়নের আগে নন-নীল সেট করেছেন ? আপনি lexical-bindingশূন্যের সাথে বর্ণিত আচরণটি পেয়েছি , কিন্তু আমি যখন এটি অ-শৃঙ্খলে সেট করি তখন আমি অকার্যকর-ত্রুটিযুক্ত ত্রুটি পাই।
রায়ান সি থম্পসন

হ্যাঁ, আমি এটিকে একটি পৃথক ফাইলে সংরক্ষণ করেছি, বিপরীত করেছি, যাচাই করেছি যা lexical-bindingফর্মগুলি ক্রমানুসারে নির্ধারণ করা হয়েছে এবং মূল্যায়ন করা আছে।
wasamasa

@ ওয়াসমাসা আমার জন্য পুনরুত্পাদন করে, সম্ভবত আপনি my-dynamic-varআপনার বর্তমান সেশনে ভুলক্রমে কোনও শীর্ষ-স্তরের গতিশীল মান দিয়েছেন ? আমি মনে করি এটি স্থায়ীভাবে বিশেষ হিসাবে চিহ্নিত করতে পারে।
npostavs
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.