কিভাবে একটি স্বচ্ছ "পাস-মাধ্যমে" ফাংশন র‌্যাপার লিখবেন?


10

আমি একটি "স্বচ্ছ 'পাস-থ্রো' ফাংশন র‌্যাপার" বলতে যা বুঝি তা একটি ফাংশন, আসুন এটি কল করুন wrapper, এটি তার সমস্ত যুক্তিটি অন্য কোনও ফাংশনে পাস করে ফলাফলটি ফিরিয়ে দেয়, আসুন এটি কল করুন wrappee

এটি ইমাস লিস্পে কীভাবে হয়?

বিশেষ দ্রষ্টব্য: আদর্শ wrapperফাংশন অজ্ঞেয়বাদী সম্পর্কে wrappeeফাংশন স্বাক্ষর; যেমন এটি wrappeeযুক্তিগুলির সংখ্যা, অবস্থান, নাম ইত্যাদির কিছুই জানে না ; এটি কেবল তার সমস্ত তর্ক যুক্ত করে দেয় wrappee, ঠিক যেমন wrappeeএকটি বলা হয়েছিল। (যাইহোক, কল স্ট্যাকের সাথে কলটি কলটির সাথে প্রতিস্থাপনের wrapperসাথে গোলযোগ করার দরকার নেই wrappee))

আমি আমার প্রশ্নের একটি আংশিক উত্তর পোস্ট করেছি:

(defun wrapper (&rest args) (apply 'wrappee args))

ইন্টারেক্টিভ না হলে wrappeeএটি কেবল তখনই কাজ করে। স্পষ্টতই, ইন্টারেক্টিভ ফাংশনগুলি তাদের আর্গুমেন্টগুলি যেভাবে পেয়েছে তা জ্বলন্তভাবে আবৃত বিষয়গুলি থেকে আলাদা "চ্যানেল" উপস্থাপন করে । আমার এখনও যা প্রয়োজন, তাই ইন্টারেক্টিভ ফাংশন যেখানে রয়েছে তার ক্ষেত্রে স্বাক্ষরের সমান- জ্ঞানস্টিক অংশ p(&rest args)wrappee(&rest args)wrappee

(এই প্রশ্নটি এই আগের প্রশ্নটিতে বর্ণিত একটি সমস্যা দ্বারা অনুপ্রাণিত হয়েছিল ))


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

পাইথনে এমন একটি মোড়কের বাস্তবায়নের কয়েকটি মানক উপায় নীচে দেখানো হয়েছে:

def wrapper(*args, **kwargs):
    return wrappee(*args, **kwargs)

# or

wrapper = lambda *args, **kwargs: wrappee(*args, **kwargs)

(এখানে *args"সমস্ত অবস্থানগত আর্গুমেন্ট" **kwargsবোঝায় , এবং "সমস্ত কীওয়ার্ড আর্গুমেন্ট" বোঝায় stands)

জাভাস্ক্রিপ্ট সমতুল্য এই জাতীয় কিছু হবে:

function wrapper () { return wrappee.apply(this, arguments); }

// or

wrapper = function () { return wrappee.apply(this, arguments); }

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


আপনি পরামর্শ / nadvice ব্যবহার বিবেচনা করেছেন?
wasamasa

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

1
@ ওসামাসা: পরামর্শ একই সমস্যা উপস্থাপন করে। কোনও আর্গুমেন্টের সাথে কী করবেন তা আপনি এটি বলতে পারেন, তবে এটিকে ইন্টারেক্টিভ করার জন্য আপনাকে কীভাবে যুক্তি সরবরাহ করা হবে তা নির্দিষ্ট করতে হবে। আইওডাব্লু, আপনার একটি interactiveঅনুমান সরবরাহ করা প্রয়োজন।
অঙ্কিত

1
আমি যা বলতে চাইছিলাম তা হ'ল আসল ইন্টারেক্টিভ ফাংশনকে আপনি এর আগে ও পরে যা কিছু করতে চান তা করার পরামর্শ দিচ্ছেন, এইভাবে আপনাকে ইন্টারেক্টিভ স্পেস সম্পর্কে চিন্তা করার দরকার নেই।
ওয়াসামাস

2
@ ওসামাসা: হ্যাঁ, তবে এটি আলাদা। ইন্টারেক্টিভ থাকুক বা না থাকুক, পরামর্শ কোনও নির্দিষ্ট কাজের জন্য সর্বদা থাকে । এবং যদি এটি একটি আদেশ হয় তবে কোনও সমস্যা নেই - এর ইন্টারেক্টিভ আচরণটি পরামর্শযুক্ত কমান্ডের জন্য উত্তরাধিকার সূত্রে প্রাপ্ত হয় (যদি না পরামর্শটি ইন্টারেক্টিভ আচরণের পুনরায় সংজ্ঞা দেয়)। এই প্রশ্নটি একটি স্বেচ্ছাসেবী ফাংশন / কমান্ড সম্পর্কে , কোনও নির্দিষ্টটি নয়।
ড্র হয়েছে

উত্তর:


11

অবশ্যই এটি interactiveস্পেসিফিকেশন সহ অন্তর্ভুক্ত । আমরা এখানে এলিস্পের সাথে কাজ করছি ! (লিস্প হ'ল এমন ভাষা যেখানে সর্বাধিক গুরুত্বপূর্ণ নির্মাণগুলি তালিকাগুলি Cal কলযোগ্য ফর্মগুলি কেবলমাত্র তালিকাগুলি So তাই আপনার পছন্দ অনুসারে আপনি এগুলি নির্মাণ করতে পারেন))

অ্যাপ্লিকেশন: আপনি কিছু কার্যকারিতাটিতে স্বয়ংক্রিয়ভাবে কিছু কার্যকারিতা যুক্ত করতে চান। বর্ধিত ফাংশনগুলিকে নতুন নাম দেওয়া উচিত যাতে এটি defadviceপ্রযোজ্য নয়।

প্রথমে এমন একটি সংস্করণ যা আপনার উদ্দেশ্যকে পুরোপুরি ফিট করে। আমরা আমাদের অতিরিক্ত স্টাফ থেকে সমস্ত প্রয়োজনীয় তথ্য সহ fsetপ্রতীকটির ফাংশন সেল ( ) সেট করি ।wrapperwrappee

এটি উভয় wrappeeসংজ্ঞা জন্য কাজ করে । প্রথম সংস্করণটি wrappeeইন্টারেক্টিভ দ্বিতীয়টি নয়।

(defun wrappee (num str)
  "Nontrivial wrappee."
  (interactive "nNumber:\nsString:")
  (message "The number is %d.\nThe string is \"%s\"." num str))

(defun wrappee (num str)
  "Noninteractive wrappee."
  (message "The number is %d.\nThe string is \"%s\"." num str))

(fset 'wrapper (list 'lambda
             '(&rest args)
             (concat (documentation 'wrappee t) "\n Wrapper does something more.")
             (interactive-form 'wrappee)
             '(prog1 (apply 'wrappee args)
            (message "Wrapper does something more."))))

তবে ম্যাক্রো সংজ্ঞায়িত করা আরও সুবিধাজনক যা বর্ধিত ফাংশনগুলি তৈরি করে। এর সাথে আমরা পরে ফাংশনটির নামগুলিও নির্দিষ্ট করতে পারি। (একটি স্বয়ংক্রিয় সংস্করণের জন্য ভাল।)

নীচের কোডটি কার্যকর করার পরে আপনি wrapper-interactiveইন্টারেক্টিভ এবং wrapper-non-interactiveঅ-ইন্টারেক্টিভ কল করতে পারেন ।

(defmacro make-wrapper (wrappee wrapper)
  "Create a WRAPPER (a symbol) for WRAPPEE (also a symbol)."
  (let ((arglist (make-symbol "arglist")))
  `(defun ,wrapper (&rest ,arglist)
     ,(concat (documentation wrappee) "\n But I do something more.")
     ,(interactive-form wrappee)
     (prog1 (apply (quote ,wrappee) ,arglist)
       (message "Wrapper %S does something more." (quote ,wrapper))))))

(defun wrappee-interactive (num str)
  "That is the doc string of wrappee-interactive."
  (interactive "nNumber:\nsString:")
  (message "The number is %d.\nThe string is \"%s\"." num str))

(defun wrappee-non-interactive (format &rest arglist)
  "That is the doc string of wrappee-non-interactive."
  (apply 'message format arglist))

(make-wrapper wrappee-interactive wrapper-interactive)
(make-wrapper wrappee-non-interactive wrapper-non-interactive)
;; test of the non-interactive part:
(wrapper-non-interactive "Number: %d, String: %s" 1 "test")

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


2
এইচএম, কেউ এই উত্তরটি নিচে ভোট দিয়েছেন। আমি স্কোরটি সম্পর্কে আসলেই চিন্তা করি না তবে উত্তরটি নিচে ভোট দেওয়ার কারণটি আমি কী যত্ন করি। আপনি যদি ভোট-প্রদান করেন, দয়া করে একটি মন্তব্যও দিন! এটি আমাকে উত্তরকে উন্নত করার সুযোগ দেবে।
টোবিয়াস

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

2
@ ওসামাসা আমি আংশিকভাবে একমত তবুও, এমন কিছু ঘটনা রয়েছে যেখানে স্বয়ংক্রিয় যন্ত্র প্রয়োগ বাধ্যতামূলক। একটি উদাহরণ edebuginteractiveতদতিরিক্ত , এমন ফাংশন রয়েছে যেখানে -স্পেসিফিকেশন ফাংশন বডি থেকে যথেষ্ট বড়। এই জাতীয় ক্ষেত্রে interactiveস্পেসিফিকেশনটির পুনর্লিখন বেশ ক্লান্তিকর হতে পারে। প্রশ্ন এবং উত্তর প্রয়োজনীয় নীতিগুলি সম্বোধন করে।
টোবিয়াস

1
ব্যক্তিগতভাবে, আমি এই প্রশ্নের উত্তরটি বেশ শিক্ষণীয় মনে করি, কেবলমাত্র প্রশ্নের ক্ষেত্রের ক্ষেত্রেই নয়, তবে এটি ম্যাক্রোগুলির প্রাকৃতিক প্রয়োগও দেখায় এবং ম্যাক্রো থেকে কীভাবে এক পদক্ষেপ নেওয়া যায়। ধন্যবাদ!
gsl

11

আমি একটি খুব অনুরূপ সমস্যা সমাধান করতে হয়েছিল nadvice.el, তাই এখানে একটি সমাধান (যা nadvice.el থেকে কোড কিছু ব্যবহার করে):

(defun wrapper (&rest args)
  (interactive (advice-eval-interactive-spec
                (cadr (interactive-form #'wrappee))))
  (apply #'wrappee args))

এখনও অবধি পোস্ট করা অন্যান্য সমাধানের সাথে তুলনা করে, এটির একটি সঠিকভাবে কাজ করার সুবিধা রয়েছে যদি wrappeeকোনও ভিন্ন ইন্টারেক্টিভ স্পেসের সাথে নতুন সংজ্ঞা দেওয়া হয় (যেমন এটি পুরানো অনুমানটি ব্যবহার করে না)।

অবশ্যই, আপনি যদি নিজের মোড়কটি সত্যিকারের স্বচ্ছ হতে চান তবে আপনি আরও সহজভাবে এটি করতে পারেন:

(defalias 'wrapper #'wrappee)

এটিই কেবলমাত্র একটি উত্তর যা একটি মোড়ক সংজ্ঞায়িত করতে দেয় যা রানটাইমটিতে এটি কী আবৃত করে তা আবিষ্কার করে। উদাহরণস্বরূপ, আমি একটি শর্টকাট যুক্ত করতে চাই যা রানটাইমের সময় দেখা কিছু আদেশ দ্বারা নির্ধারিত একটি ক্রিয়া সম্পাদন করে। advice-eval-interactive-specএখানে প্রস্তাবিত হিসাবে ব্যবহার করে আমি ইন্টারেক্টিভ নির্দিষ্টটি তৈরি করতে পারি যা সেই গতিশীল র‌্যাপারের সাথে মিলে যায়।
ইগর বুকানভ

এটি তৈরি করতে কি সম্ভব called-interactively-pআসতে tমধ্যে wrappee? নেই funcall-interactivelyতবে নেইapply-interactively
ক্লেমেরা

1
@ কম্পুনাট: অবশ্যই আপনি (apply #'funcall-interactively #'wrappee args)চাইলে করতে পারেন। কিন্তু আপনি শুধু এটা করা উচিৎ ফাংশন ইন্টারেক্টিভ বলা হয় যদি, তাই ভালো কিছু (apply (if (called-interactively-p 'any) #'funcall-interactively #'funcall) #'wrappee args)
স্টিফান

হা, ধন্যবাদ! কোনওভাবেই আমার বাক্সের বাইরে ভাবতে পারেনি।
ক্লেমেরা

1

সম্পাদনা করুন: টোবিয়াসের উত্তরটি এর চেয়ে সুন্দর, কারণ এটি মোড়ানো ফাংশনের সুনির্দিষ্ট ইন্টারেক্টিভ ফর্ম এবং ডাস্ট্রিং গ্রহণ করে।


হারুন হ্যারিস এবং কোজোর উত্তরগুলির সংমিশ্রণ, আপনি এর মতো কিছু ব্যবহার করতে পারেন:

(defmacro my-make-wrapper (fn &optional name)
  "Return a wrapper function for FN defined as symbol NAME."
  `(defalias ',(or (eval name)
                   (intern (concat "my-" (symbol-name (eval fn)) "-wrapper")))
     (lambda (&rest args)
       ,(format "Generic wrapper for %s."
                (if (symbolp (eval fn))
                    (concat "`" (symbol-name (eval fn)) "'")
                  fn))
       (interactive)
       (if (called-interactively-p 'any)
           (call-interactively ,fn)
         (apply ,fn args)))))

ব্যবহার:

(my-make-wrapper 'find-file 'wrapper-func)

যেকোন একটির সাথে র‍্যাপারকে কল করুন:

(wrapper-func "~/.emacs.d/init.el")

M-x wrapper-func

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