কোনও ফাংশন বা ম্যাক্রো বাই-কম্পাইলার সতর্কতা নির্দিষ্ট করতে পারে?


15

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

এখানে প্রসঙ্গের জন্য একটি জঘন্য উদাহরণ:

(defun my-caller (&rest args)
  (while args
    (call-other-function (pop args) (pop args))))

যখন একটি এলিস্প ফাইল বাইট-কম্পাইল করা হয়, বাইট-সংকলক একটি সতর্কতা ছুড়ে দেয় যখন দেখায় যে কোনও ফাংশনকে ভুল সংখ্যার যুক্তি দিয়ে ডাকা হচ্ছে। স্পষ্টতই, এটি কখনই ঘটবে না my-caller, যেহেতু এটি কোনও সংখ্যা নেওয়ার জন্য সংজ্ঞায়িত হয়েছে।

তবুও, সম্ভবত আমি সেট করতে পারি এমন একটি প্রতীক সম্পত্তি আছে বা একটি (declare)ফর্ম আমি এর সংজ্ঞাটিতে যুক্ত করতে পারি। ব্যবহারকারীকে অবহিত করার জন্য যে এই ক্রিয়াকলাপটি কেবল একটি এমনকি সংখ্যক যুক্তি দেওয়া উচিত।

  1. এই সীমাবদ্ধতার বাইট-সংকলককে জানানোর কোনও উপায় আছে কি?
  2. যদি তা না হয় তবে কোনও ফাংশনের পরিবর্তে ম্যাক্রো দিয়ে এটি সম্ভব?

"... যখন এটি দেখায় যে কোনও ক্রিয়াকলাপটি ভুল সংখ্যার যুক্তি দিয়ে আহ্বান করা হচ্ছে "?
itjeyd

উত্তর:


13

সম্পাদনা : সাম্প্রতিক ইমাসকে এটি করার আরও ভাল উপায় হ'ল আর্গুমেন্টের সংখ্যা পরীক্ষা করার জন্য একটি সংকলক ম্যাক্রো সংজ্ঞায়িত করা । একটি সাধারণ ম্যাক্রো ব্যবহার করে আমার মূল উত্তরটি নীচে সংরক্ষণ করা হয়েছে, তবে একটি সংকলক-ম্যাক্রো উচ্চতর কারণ এটি ফাংশনে funcallবা applyরানটাইমে পাস করা বাধা দেয় না ।

ইমাক্সের সাম্প্রতিক সংস্করণগুলিতে, আপনি আপনার ফাংশনের জন্য একটি সংকলক-ম্যাক্রো সংজ্ঞায়িত করে এটি করতে পারেন যা আর্গুমেন্টের সংখ্যাটি পরীক্ষা করে এবং এটি মেলে না তবে একটি সতর্কতা (বা এমনকি একটি ত্রুটি) তৈরি করে। একমাত্র সূক্ষ্মতা হ'ল মূল্যায়ন বা সংকলনের জন্য সংকলক ম্যাক্রোর মূল ফাংশন কল ফর্মটি অপরিবর্তিত করা উচিত। এটি একটি &wholeআর্গুমেন্ট ব্যবহার করে এবং এর মান ফিরিয়ে নেওয়া হয়। এটি এইভাবে সম্পাদন করা যেতে পারে:

(require 'cl-lib)

(defun my-caller (&rest args)
  (while args
    (message "%S %S" (pop args) (pop args))))

(define-compiler-macro my-caller (&whole form &rest args)
  (when (not (cl-evenp (length args)))
    (byte-compile-warn "`my-caller' requires an even number of arguments"))
  form)

(my-caller 1 2 3 4)
(my-caller 1 2)
(funcall #'my-caller 1 2 3 4)       ; ok
(apply #'my-caller '(1 2))          ; also ok
(my-caller 1)                       ; produces a warning
(funcall #'my-caller 1 2 3)         ; no warning!
(apply #'my-caller '(1 2 3))        ; also no warning

নোট করুন funcallএবং applyএখন ব্যবহার করা যেতে পারে, তবে তারা সংকলক ম্যাক্রোর দ্বারা তর্ক তদন্তকে বাইপাস করে। তাদের নাম সত্ত্বেও, কম্পাইলার ম্যাক্রো এছাড়াও মূল্যায়ন 'ব্যাখ্যা' অবশ্যই মাধ্যমে প্রসারিত হবে বলে মনে হচ্ছে C-xC-e, M-xeval-buffer, তাই আপনি মূল্যায়ন পাশাপাশি এই উদাহরণে সংকলন ত্রুটি পাবেন।


আসল উত্তর অনুসরণ:

আপনি "ম্যাক্রো ব্যবহারের জন্য যা সম্প্রসারণের সময় সতর্কতা সরবরাহ করবে" এর পরামর্শের জন্য জর্ডনের পরামর্শটি কীভাবে কার্যকর করতে পারেন তা এখানে রয়েছে। এটি খুব সহজ হতে দেখা যাচ্ছে:

(require 'cl-lib)

(defmacro my-caller (&rest args)
  (if (cl-evenp (length args))
      `(my-caller--function ,@args)
    (error "Function `my-caller' requires an even number of arguments")))

(defun my-caller--function (&rest args)
  ;; function body goes here
  args)

(my-caller 1 2 3 4)
(my-caller 1 2 3)

একটি ফাইলের উপরেরটি সংকলন করার চেষ্টা ব্যর্থ হবে (কোনও .elcফাইল তৈরি করা হয় না), সংকলন লগে একটি দুর্দান্ত ক্লিকযোগ্য ত্রুটি বার্তা সহ উল্লেখ করে:

test.el:14:1:Error: `my-caller' requires an even number of arguments

এছাড়াও আপনি প্রতিস্থাপন করতে পারে (error …)সঙ্গে (byte-compile-warn …)একটি ত্রুটির পরিবর্তে একটি সতর্কবার্তা উত্পাদন করতে, চালিয়ে যেতে সংকলন অনুমতি দেয়। (মন্তব্যগুলিতে এটিকে নির্দেশ করার জন্য জর্ডনকে ধন্যবাদ)।

সংকলনের সময়ে ম্যাক্রোগুলি প্রসারিত হওয়ায় এই চেকটির সাথে কোনও রান-টাইম জরিমানা যুক্ত নেই। অবশ্যই, আপনি অন্য লোককে my-caller--functionসরাসরি কল করা বন্ধ করতে পারবেন না তবে আপনি কমপক্ষে ডাবল হাইফেন কনভেনশনটি ব্যবহার করে এটি একটি "ব্যক্তিগত" ফাংশন হিসাবে বিজ্ঞাপন করতে পারেন।

এই উদ্দেশ্যে ম্যাক্রো ব্যবহারের একটি উল্লেখযোগ্য অসুবিধা হ'ল এটি my-callerএখন প্রথম শ্রেণির ফাংশন নয়: আপনি এটিকে funcallবা applyরানটাইমে পাস করতে পারবেন না (বা কমপক্ষে এটি আপনার প্রত্যাশা অনুযায়ী করবে না)। এই সম্মানের ক্ষেত্রে, এই সমাধানটি কেবল কোনও আসল ফাংশনটির জন্য কেবল একটি সংকলক সতর্কতা ঘোষণা করতে সক্ষম হওয়ার মতো যথেষ্ট ভাল নয়। অবশ্যই, ব্যবহারটি applyযে কোনও উপায়ে সংকলন সময়ে ফাংশনটিতে কতগুলি আর্গুমেন্ট পাস হচ্ছে তা যাচাই করা অসম্ভব করে তোলে, তাই সম্ভবত এটি একটি গ্রহণযোগ্য বাণিজ্য-বন্ধ।


2
সংকলনের সতর্কতাগুলি তৈরি করা হয়েছেbyte-compile-warn
জর্ডন বিওনডো

আমি এখন ভাবছি যদি ফাংশনের জন্য একটি সংকলক ম্যাক্রো সংজ্ঞায়িত করে আরও কার্যকরভাবে এটি সম্পাদন করা যায়। এটি ম্যাক্রো মোড়ক না হওয়া applyবা অসুবিধা দূর করবে funcall। আমি এটি ব্যবহার করে দেখুন এবং আমার উত্তরটি যদি এটি কার্যকর হয় তবে সম্পাদনা করব।
জন ও।

11

হ্যাঁ আপনি byte-defop-compilerপ্রকৃতপক্ষে কোনও ফাংশন নির্দিষ্ট করতে ব্যবহার করতে পারেন যা আপনার ফাংশনকে সংকলন করে, byte-defop-compilerকিছু বিশেষ নকশাগুলি তৈরি করে যাতে আপনাকে উল্লেখ করতে পারেন যে আপনার ফাংশনগুলিতে বেশ কয়েকটি আর্গ থাকার কারণে সতর্কতা পাওয়া উচিত।

নথিপত্র

FUNCTION এর জন্য একটি সংকলক-ফর্ম যুক্ত করুন function যদি ফাংশনটি একটি প্রতীক হয়, তবে ভেরিয়েবলটি "বাইট-সিওয়ামবোল" ব্যবহার করতে অপকোডের নাম দিতে হবে। ফাংশনটি যদি একটি তালিকা থাকে তবে প্রথম উপাদানটি হ'ল ফাংশন এবং দ্বিতীয় উপাদানটি হ'ল বাইটকোড-প্রতীক। দ্বিতীয় উপাদানটি শূন্য হতে পারে, যার অর্থ কোনও অপকোড নেই। কমপাইল-হ্যান্ডেলার হ'ল এই বাইট-ওপটি সংকলন করতে ব্যবহৃত ফাংশন, বা সংক্ষেপগুলি 0, 1, 2, 3, 0-1, বা 1-2 হতে পারে। যদি এটি শূন্য হয়, তবে হ্যান্ডেলারটি "বাইট-কম্পাইল-এসওয়াইএমবোল"।


ব্যবহার

আপনার নির্দিষ্ট ক্ষেত্রে আপনি সংক্ষিপ্তসারগুলির মধ্যে একটির সংজ্ঞাটি ব্যবহার করতে পারেন যে আপনার ফাংশনটিকে দুটি আরগ দেওয়া উচিত।

(byte-defop-compiler my-caller 2)

এখন আপনি দুটি ফাংশন সতর্কতা দিবেন যখন 2 টি আরগস ব্যতীত অন্য কোনও কিছু সংকলিত হয়।

আপনি যদি আরও নির্দিষ্ট সতর্কতা দিতে চান এবং নিজের সংকলক ফাংশন লিখতে চান। byte-compile-one-argরেফারেন্সের জন্য bytecomp.el এ এবং অন্যান্য অনুরূপ ফাংশনগুলি দেখুন।

নোট করুন যে আপনি কেবল বৈধতা হ্যান্ডেল করার জন্য কিছু ফাংশন নির্দিষ্ট করছেন না, তবে আসলে সংকলনটিও করছেন। Bytecomp.el এ আবার ফাংশনগুলি সংকলন আপনাকে একটি ভাল রেফারেন্স সরবরাহ করবে।


নিরাপদ রুট

এটি এমনটি নয় যা আমি অনলাইনে নথিভুক্ত বা আলোচিত দেখেছি তবে সামগ্রিকভাবে আমি বলব যে এটি কোনও পথ অবলম্বন করার পরামর্শ নয়। সঠিক রুট (আইএমও) হ'ল বর্ণনামূলক স্বাক্ষর সহ আপনার ডিফোনগুলি লিখতে বা কোনও ম্যাক্রো ব্যবহার করা হবে যা সম্প্রসারণের সময় সতর্কতা সরবরাহ করবে, আপনার আর্গের দৈর্ঘ্য পরীক্ষা করবে এবং ব্যবহার করবে byte-compile-warnবা errorত্রুটিগুলি দেখায়। eval-when-compileত্রুটি পরীক্ষা করা ব্যবহার করতেও এটি আপনার উপকার করতে পারে ।

আপনার ফাংশনটি এটি ব্যবহারের আগে সংজ্ঞায়িত করতে byte-defop-compilerহবে এবং সংকলকটি আপনার ফাংশনের আসল কলগুলিতে পৌঁছানোর আগে কলটি হওয়া দরকার।

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

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


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