আমি কীভাবে একটি তালিকার মাধ্যমে লুপ করে একাধিক সংঘবদ্ধ করতে পারি?


11

আমি আমার ইমাস কনফিগারটি অনুকূলকরণের জন্য কাজ করছি যেখানে আমি তালিকায় থাকা সমস্ত থিমের জন্য গতিশীল ইন্টারেক্টিভ ফাংশন তৈরি করতে পারি।

নীচে আমি কাজটি করার চেষ্টা করছি এমন নির্মাণের একটি সরলীকৃত সংস্করণ।

;; List containing names of functions that I want to create
(setq my/defun-list '(zz-abc
                      zz-def
                      zz-ghi))

;; Elisp macro to create an interactive defun whose name
;; is passed as the macro argument
(defmacro my/create-defun (defun-name)
  `(defun ,defun-name ()
     (interactive)
     (let ((fn-name (symbol-name ',defun-name)))
       (message "Testing creation of function %s" fn-name))))

;; Loop to call the above macro for each element in the list
;; DOES *NOT* WORK
(dolist (name my/defun-list)
  (my/create-defun name))

তবে যদি আমি নিজে লুপটি আনরোল করি তবে এটি কাজ করে:

;; WORKS
(my/create-defun zz-abc)
(my/create-defun zz-def)
(my/create-defun zz-ghi)

তবে নীচে কাজ করা হয় না যেখানে আমি প্রতীকী নামগুলিতে পাস করি (যা সম্ভবত লুপটি নিজেই আনরোল হয়ে যাওয়ার পরে ঘটে)। ম্যাক্রোর যুক্তিগুলির আগে উদ্ধৃতিগুলি নোট করুন।

;; DOES *NOT* WORK
(my/create-defun 'zz-abc)
(my/create-defun 'zz-def)
(my/create-defun 'zz-ghi)

হালনাগাদ

@Wvxvw এর সহায়তায় ধন্যবাদ , অবশেষে আমি এই কাজটি পেয়েছি !

@Wvxvw এর পরামর্শ অনুসারে, আমি কোনও এবং প্রতিটি ব্যবহারের ক্ষেত্রে ব্যাচ-জেনারেটিং সংশোধন করব না। এটি একটি বিশেষ ব্যবহারের XYZক্ষেত্র ছিল যেখানে নামের থিমের জন্য , আমি একটি ডিফুন জেনারেট করতে চাই load-theme/XYZযা এর কাজটি করে

  • সক্রিয় হতে পারে এমন অন্যান্য সমস্ত থিম অক্ষম করা হচ্ছে
  • কলিং load-themeজন্যXYZ
  • থিম সম্পর্কিত আরও কিছু কাস্টম স্টাফ করা; আমি তালিকার প্রতিটি থিমের জন্য কাস্টম সেটিংসে পাস করি my/themes

1
সব defunsভিতরে রাখুন ক prognprognএকটি শীর্ষ-স্তরের ফর্ম হতে দেওয়া হয় (এই অর্থে যে শীর্ষ-স্তরের ফর্মগুলিতে প্রযোজ্য প্রতিটি জিনিসই এর বিষয়বস্তুতে প্রযোজ্য progn)। তবে আমি এইভাবে ফাংশন তৈরির যৌক্তিকতা সম্পর্কে প্রশ্ন করব: লাম্বদাসের সাথে মান হিসাবে একটি টেবিল কেন নেই?
wvxvw

@wvxvw আমি এই পরামর্শটি বুঝতে পারি নি। আমার কাছে কেবল একটি ডিফুন তৈরি ম্যাক্রো রয়েছে যা আমি লুপে একাধিকবার কল করতে চাই। আমি এই সমস্যাটি বের করার চেষ্টা করার সময় ম্যানুয়ালি নিবন্ধভুক্ত উদাহরণগুলি হ'ল যা কাজ করেছে এবং কী কাজ করে নি তা দেখানো। আমার লক্ষ্য হ'ল তালিকার পরিবর্তে একটি তালিকা তৈরি করা এবং বিভিন্ন থিমের জন্য ইন্টারেক্টিভ ফাংশন তৈরি করা । বর্তমানে consতালিকার তালিকায় কেবল এস এস রয়েছে তবে আমি প্রতিটি থিমের জন্য কাস্টম বৈশিষ্ট্যযুক্ত তালিকায় সেগুলিকে রূপান্তর করার পরিকল্পনা করছি।
कौशल মোদী 21

ভাল, আপনি (my/create-defun name)3 বার কল করেছেন, সুতরাং আপনি name3 বার বলা একটি ফাংশন সংজ্ঞায়িত করা উচিত ।
ওমর

উত্তর:


13

এখানে একটি ব্যাখ্যা দেওয়ার চেষ্টা এবং কিছু পরামর্শ।

(defmacro my/create-defun (defun-name)
  `(defun ,defun-name ()
     (interactive)
     (let ((fn-name (symbol-name ',defun-name)))
       (message "Testing creation of function %s" fn-name))))

(dolist (name my/defun-list)
  ;; Macros are meant to create code, not execute it.  Think
  ;; about simply substituting the contents of your macro here
  ;; what would you expect it to do?
  (my/create-defun name))

(dolist (name my/defun-list)
  ;; This is not something a compiler (or interpreter)
  ;; can work with, it needs all sources of the code it
  ;; is going to execute
  (defun defun-name ()
    (interactive)
    (let ((fn-name (symbol-name 'defun-name)))
      (message "Testing creation of function %s" fn-name))))

;; This works because you, indeed created three defuns
(my/create-defun zz-abc)
(my/create-defun zz-def)
(my/create-defun zz-ghi)

;; This doesn't work because `defun' macro expect the name of
;; the function to be a symbol (but you are giving it a list
;; `(quote zz-abc)'.
(my/create-defun 'zz-abc)
(my/create-defun 'zz-def)
(my/create-defun 'zz-ghi)

এখন, এটি ঠিক করার চেষ্টা করা যাক:

;; Rewriting the original macro as a function and using a
;; macro to collect the generated forms gives:
(defun my/create-defun (defun-name)
  `(defun ,defun-name ()
     (interactive)
     (let ((fn-name (symbol-name ',defun-name)))
       (message "Testing creation of function %s" fn-name))))

(defmacro my/create-defuns (defuns)
  `(progn ,@(mapcar 'my/create-defun defuns)))

(macroexpand '(my/create-defuns (zz-abc zz-def zz-ghi)))
;; Just to make sure
(progn
  (defun zz-abc nil
    (interactive)
    (let ((fn-name (symbol-name (quote zz-abc))))
      (message "Testing creation of function %s" fn-name)))
  (defun zz-def nil
    (interactive)
    (let ((fn-name (symbol-name (quote zz-def))))
      (message "Testing creation of function %s" fn-name)))
  (defun zz-ghi nil
    (interactive)
    (let ((fn-name (symbol-name (quote zz-ghi))))
      (message "Testing creation of function %s" fn-name))))

একটি ভেরিয়েবল থেকে ফাংশন নাম পড়ার উদাহরণ

(defvar my/functions '((func-1 . 1) (func-2 . 2) (func-3 . 3)))

(defun my/create-defun-n (defun-name n)
  `(defun ,defun-name ()
     (message "function: %s, n %d" ',defun-name ,n)))

(defmacro my/create-defuns-var ()
  `(progn ,@(mapcar
             (lambda (x) (my/create-defun-n (car x) (cdr x)))
             my/functions)))

(macroexpand '(my/create-defuns-var))
(progn
  (defun func-1 nil (message "function: %s, n %d" (quote func-1) 1))
  (defun func-2 nil (message "function: %s, n %d" (quote func-2) 2))
  (defun func-3 nil (message "function: %s, n %d" (quote func-3) 3)))

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


একটি প্রান্তিক নোট: আমি একসাথে বেশ কয়েকজনকে লম্পট দেওয়ার বিরুদ্ধে পরামর্শ দেব defuns। কারণ হ'ল এটি ডিবাগিনকে আরও জটিল করে তোলে। আপনার পুনরাবৃত্তি সংজ্ঞাগুলিতে যে সামান্য অতিরিক্ত অতিরিক্ত কাজ হয়েছে তা রক্ষণাবেক্ষণের পর্যায়ে খুব ভাল অর্থ প্রদান করে (এবং রক্ষণাবেক্ষণ সাধারণত প্রোগ্রামটির জীবনের দীর্ঘতম পর্যায় হয়)।


4
আমি মনে করি শেষ প্রান্তিক নোটটি সমস্ত সাহসী ক্যাপগুলিতে হওয়া উচিত :)
আবু-অ্যাবো

ধন্যবাদ! উদাহরণ সহ এটি দুর্দান্ত তথ্য। mapcarতালিকাগুলি ব্যবহার করে সনাক্ত করার সাথে সাথে আমি এটিকে উত্তর হিসাবে গ্রহণ করব । এটি আমার আসল ব্যবহারের ক্ষেত্রে কাজ করবে বলে মনে হচ্ছে না। আমি যত তাড়াতাড়ি সম্ভব এটি খনন করব।
দক্ষ মোদী

@ কৈশালমোদি আপনি (mapcar (lambda (x) (message "argument: %s" x)) some-alist)কী যুক্তি পেয়েছেন তা দেখতে এবং সেখান থেকে কাজ করতে পারেন। যদি এটি কোনও সহযোগী তালিকা থাকে তবে আমি আউটপুটটিকে এমন কিছু বলে মনে করব argument: (foo . bar), তাহলে আপনি ফাংশনগুলি ব্যবহার fooকরে carএবং barব্যবহার করতে পারবেন cdr
wvxvw

হ্যাঁ, আমি সেই একই কাজ করল (ঠিক যে আমি ব্যবহৃত nthপরিবর্তে FN carএবং cadr) কিন্তু sequencepচেক mapcarআউট errored। আমি ইনপুট হিসাবে একটি তালিকার সরবরাহ করছিলাম তবে এখনও ম্যাপকার এটিকে একটি অনুক্রম বলে মনে করেনি। আমি যদি তা করি তবে তা (sequencep my-alist)শূন্য ছিল না। সুতরাং আমি বিভ্রান্ত .. আমি এখনও এটি ডিবাগ করতে হবে।
কুশল মোদী

@kaushalmodi আমি দুটি কারণে কল্পনা হবে: my-alistছিল nilঅথবা আপনি ভুলে গেছি (অথবা অতিরিক্ত যোগ করা হয়েছে) কোট যাতে my-alistহয় একটি প্রতীক ছিল, নাকি অন্য কিছু হতে এমনকি আরও মূল্যায়ন করা হয়। উত্তরটি আরও সহজ করার জন্য আপনি সম্ভবত নতুন প্রশ্ন দিয়ে আপনার প্রশ্নটি প্রসারিত করতে চান।
wvxvw

2
(dolist (fun '(foo bar baz))
  (defalias fun (lambda (a)
                  "I'm a function defined in `dolist'!"
                  (interactive)
                  (message a))))
(bar "See? No macro!")

হুবুহু না হলেও কেন? : P: P


0

আমার উদ্যোগে আমার কাছে নিম্নলিখিতগুলি রয়েছে:

(my/work-properties '("hostname" "username" "location"))

(defmacro jlp/make-def (name props doc &rest body)
  "Shortcut to programatically create new functions"
  (let ((funsymbol (intern name)))
    `(defun ,funsymbol ,props ,doc ,@body)))

(defun my/make-work-props (properties)
  "Create functions to retrieve properties from Org headlines."
  (dolist (prop properties)
    (let ((funsym   (format "my/org-get-%s" prop))
          (property (intern (format ":%s" (upcase prop))))
          (doc      (format "Retrieves `%s' from current headline"
                            (upcase prop)))
          (err (format "%s is not set" (capitalize prop))))
      (eval
       `(jlp/make-def ,funsym
                      ()
                      ,doc
                      (interactive)
                      (let ((x (or
                                (save-excursion
                                  (org-back-to-heading)
                                  (org-element-property
                                   ,property
                                   (org-element-at-point)))
                                (user-error ,err))))
                        (message "%s" x)
                         (kill-new x)))))))

(my/make-work-props my/org-work-properties)

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

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