লিসপ ম্যাক্রোস কতটা কার্যকর?


22

কমন লিস্প আপনাকে ম্যাক্রোগুলি লিখতে দেয় যা আপনার উত্স রূপান্তরটি যা চান তা করতে দেয়।

স্কিম আপনাকে একটি স্বাস্থ্যকর প্যাটার্ন-ম্যাচিং সিস্টেম দেয় যা আপনাকে পাশাপাশি রূপান্তরগুলি সম্পাদন করতে দেয়। অনুশীলনে ম্যাক্রোগুলি কতটা কার্যকর? পল গ্রাহাম পিটিং অ্যাভারেজে বলেছেন যে:

ভায়াবেব সম্পাদকের উত্স কোডটি সম্ভবত প্রায় 20-25% ম্যাক্রো ছিল।

মানুষ ম্যাক্রোগুলির সাথে আসলে কী ধরণের জিনিস শেষ করে?


আমি মনে করি এটি অবশ্যই ভাল সাবজেক্টিভের মধ্যে পড়ে , আমি ফর্ম্যাট করার জন্য আপনার প্রশ্নটি সম্পাদনা করেছি। এটি একটি সদৃশ হতে পারে, কিন্তু আমি একটি খুঁজে পেল না।
টিম পোস্ট

1
পুনরাবৃত্তিযোগ্য সমস্ত কিছুই যা কোনও ফাংশনে ফিট করে না, আমি অনুমান করি।

2
লিসপকে অন্য কোনও ভাষায়, যেকোন সিনট্যাক্স এবং যেকোন শব্দার্থবিজ্ঞানের সাথে রূপান্তর করতে আপনি ম্যাক্রোগুলি ব্যবহার করতে পারেন : বিট.ইলি
এসকে-যুক্তি

প্রোগ্রামার্স.সটাকেক্সচেঞ্জ / প্রশ্নগুলি / ৮১২০২/২ এখানে দেখার মতো, তবে এটি কোনও সদৃশ নয়।
ডেভিড থর্নলি

উত্তর:


15

২০০২ সালে এলটিএল আলোচনার তালিকায় ম্যাথিয়াস ফেলেলিসেনের এই পোস্টিংটি একবার দেখুন He তিনি ম্যাক্রোগুলির জন্য তিনটি প্রধান ব্যবহারের পরামর্শ দেন:

  1. ডেটা সাবল্যাংগুয়েজস : আমি সরল চেহারার এক্সপ্রেশন লিখতে পারি এবং উদ্ধৃতি, আনকোট, ইত্যাদি সহ জটিল নেস্টেড তালিকাগুলি / অ্যারে / টেবিল তৈরি করতে পারি at
  2. বাইন্ডিং কনস্ট্রাক্টস : আমি ম্যাক্রোর সাথে নতুন বাঁধাই কনস্ট্রাক্টস প্রবর্তন করতে পারি। এটি আমাকে ল্যাম্বডাস থেকে মুক্তি পেতে এবং জিনিসগুলিকে একসাথে থাকা জিনিসগুলিকে আরও কাছাকাছি রাখতে সহায়তা করে।
  3. মূল্যায়ন পুনঃক্রম : আমি এমন নির্মাণের সাথে পরিচয় করিয়ে দিতে পারি যা প্রয়োজন অনুযায়ী অভিব্যক্তির মূল্যায়ন বিলম্ব / স্থগিত করে। লুপস, নতুন শর্তসাপেক্ষ, বিলম্ব / বল ইত্যাদি সম্পর্কে চিন্তা করুন [দ্রষ্টব্য: হাস্কেল বা কোনও অলস ভাষায়, এটি অপ্রয়োজনীয়]]

18

আমি বেশিরভাগ সময়-সাশ্রয়ী ভাষা রচনাগুলি যুক্ত করার জন্য ম্যাক্রোগুলি ব্যবহার করি, অন্যথায় একগুচ্ছ বয়লারপ্লেট কোডের প্রয়োজন হয়।

উদাহরণস্বরূপ, আমি সম্প্রতি নিজেকে for-loopC ++ / জাভার অনুরূপ একটি আবশ্যকীয় চাইছি । তবে, একটি কার্যকরী ভাষা হওয়ায় ক্লোজুর বাক্সের বাইরে চলে আসেনি। সুতরাং আমি কেবল এটি ম্যাক্রো হিসাবে প্রয়োগ করেছি:

(defmacro for-loop [[sym init check change :as params] & steps]
  `(loop [~sym ~init value# nil]
     (if ~check
       (let [new-value# (do ~@steps)]
         (recur ~change new-value#))
       value#)))

এবং এখন আমি করতে পারি:

 (for-loop [i 0 , (< i 10) , (inc i)] 
   (println i))

এবং সেখানে এটি আপনার কাছে রয়েছে - ছয় লাইনের কোডে একটি নতুন সাধারণ-উদ্দেশ্য কম্পাইল-টাইম ল্যাঙ্গুয়েজ।


13

মানুষ ম্যাক্রোগুলির সাথে আসলে কী ধরণের জিনিস শেষ করে?

ভাষার এক্সটেনশন বা ডিএসএল এর লিখন।

লিস্প-জাতীয় ভাষায় এটির জন্য অনুভূতি পেতে, র‌্যাকেট অধ্যয়ন করুন , যার বেশ কয়েকটি ভাষার রূপ রয়েছে: টাইপড র‌্যাকেট, আর 6 আরএস এবং ডেটাগলজ।

আরও দেখুন বু ভাষা, যা আপনি ম্যাক্রো মাধ্যমে ডোমেইন নির্দিষ্ট ভাষায় তৈরি করার নির্দিষ্ট উদ্দেশ্যের জন্য কম্পাইলার পাইপলাইন অ্যাক্সেস দেয়।


4

এখানে কিছু উদাহরন:

পরিকল্পনা:

  • defineফাংশন সংজ্ঞা জন্য। মূলত এটি একটি ফাংশন সংজ্ঞায়িত করার জন্য একটি ছোট উপায় করে।
  • let লাক্ষিকভাবে স্কোপযুক্ত ভেরিয়েবলগুলি তৈরি করার জন্য।

Clojure:

  • defnএর ডক্স অনুসারে:

    (ডিএফ নাম (এফএন [প্যারামস *] এক্সপ্রারস *)) বা (ডিফ নেম (এফএন ([প্যারামস]] এক্সপ্রারস *) +)) এর মতোই কোনও ডক-স্ট্রিং বা ভেরি মেটাডাটাতে সংযুক্তকারীদের সাথে

  • for: তালিকা বোঝা
  • defmacro: বিড়ম্বনা?
  • defmethod, defmulti: বহু-পদ্ধতিতে কাজ করা
  • ns

এই ম্যাক্রোগুলির অনেকগুলি একটি আরও বিমূর্ত স্তরে কোড লিখতে অনেক সহজ করে তোলে। আমি ম্যাক্রোগুলিকে নন-লিসপসে সিনট্যাক্সের জন্য বিভিন্নভাবে অনুরূপ বলে মনে করি।

প্লটিং লাইব্রেরি ইনকান্টার কিছু জটিল ডেটা ম্যানিপুলেশনের জন্য ম্যাক্রো সরবরাহ করে।


4

ম্যাক্রোস কিছু নিদর্শন এম্বেড করতে দরকারী।

উদাহরণস্বরূপ, কমন লিস্প whileলুপটি সংজ্ঞায়িত করে না তবে এটির do সংজ্ঞা দেওয়ার জন্য এটি ব্যবহার করা যেতে পারে।

অন ​​লিস্পের একটি উদাহরণ এখানে ।

(defmacro while (test &body body)
  `(do ()
       ((not ,test))
     ,@body))

(let ((a 0))
  (while (< a 10)
    (princ (incf a))))

এটি "12345678910" মুদ্রণ করবে এবং আপনি যদি কী হয় তা দেখার চেষ্টা করেন macroexpand-1:

(macroexpand-1 '(while (< a 10) (princ (incf a))))

এটি ফিরে আসবে:

(DO () ((NOT (< A 10))) (PRINC (INCF A)))

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

loopম্যাক্রো ম্যাক্রো কি করতে পারি একটি ভাল উদাহরণ।

(loop for i from 0 to 10
      if (and (= (mod i 2) 0) i)
        collect it)
=> (0 2 4 6 8 10)
(loop for i downfrom 10 to 0
      with a = 2
      collect (* a i))
=> (20 18 16 14 12 10 8 6 4 2 0)               

কমন লিস্পে রিডার ম্যাক্রো নামে আরও একটি ধরণের ম্যাক্রো রয়েছে যা পাঠক কোডটিকে কীভাবে ব্যাখ্যা করে তা সংশোধন করতে ব্যবহার করা যেতে পারে, আপনি তাদের ব্যবহার করতে # {এবং # use ব্যবহার করতে পারেন # (এবং #) এর মতো সীমানার রয়েছে।


3

আমি এখানে একটি ডিবাগিংয়ের জন্য ব্যবহার করি (ক্লোজারে):

user=> (defmacro print-var [varname] `(println ~(name varname) "=" ~varname))
#'user/print-var
=> (def x (reduce * [1 2 3 4 5]))
#'user/x
=> (print-var x)
x = 120
nil

আমাকে সি ++ এ হ্যান্ড-রোলড হ্যাশ-টেবিলের সাথে মোকাবিলা করতে হয়েছিল, যেখানে getপদ্ধতিটি একটি যুক্তি হিসাবে একটি অ-কনস্ট্রিং স্ট্রিং রেফারেন্স নিয়েছিল, যার অর্থ আমি এটি আক্ষরিক দিয়ে বলতে পারি না। মোকাবেলা করা সেই সহজ করার জন্য আমি নীচের মতো কিছু লিখেছিলাম:

#define LET(name, value, body)  \
    do {                        \
        string name(value);     \
        body;                   \
        assert(name == value);  \
    } while (false)

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

আমি do ... while (false)এমনভাবে মোড়ানো জিনিসগুলির ভয়াবহ কুৎসিত হ্যাকেরও অবলম্বন করি যাতে আপনি এটি যদি কোনও অংশের মধ্যে ব্যবহার করতে পারেন এবং এখনও অন্য অংশের প্রত্যাশা মতো কাজ করতে পারেন। আপনার লিস্পে এটির দরকার নেই, এটি স্ট্রিং (বা টোকেন ক্রমগুলি সি, সি এবং সি ++ এর ক্ষেত্রে) এর চেয়ে সিনট্যাক্স গাছগুলিতে পরিচালিত ম্যাক্রোগুলির একটি ক্রিয়া যা পার্সিংয়ের মধ্য দিয়ে চলেছে।

কয়েকটি বিল্ট-ইন থ্রেডিং ম্যাক্রোগুলি রয়েছে যা আপনার কোডটি পুনরায় সাজানোর জন্য ব্যবহার করা যেতে পারে যাতে এটি আরও পরিষ্কার করে পড়ে ('থ্রেডিং' যেমন 'আপনার কোড একসাথে বপন করা' সমান্তরালতা নয়)। উদাহরণ স্বরূপ:

(->> (range 6) (filter even?) (map inc) (reduce *))

এটি প্রথম রূপ নেয় (range 6), এবং এটি পরবর্তী ফর্মের (filter even?)শেষ যুক্তি হিসাবে তৈরি করে, যা পরবর্তী ফর্মের শেষ যুক্তি হিসাবে তৈরি করা হয় এবং এর ফলে উপরেরটি আবার লিখিত হয়

(reduce * (map inc (filter even? (range 6))))

আমি মনে করি প্রথমটি আরও স্পষ্টভাবে পড়েছে: "এই ডেটাগুলি নিয়ে নিন, এটি এটি করুন, তারপরে এটি করুন, তারপরে অন্যটি করুন এবং আমরা সম্পন্ন করেছি", তবে এটি বিষয়গত; বস্তুগতভাবে সত্য এমন কিছু হ'ল আপনি যে ক্রমগুলি সম্পাদন করছেন সেগুলি ক্রিয়াকলাপগুলি পড়েন (অলসতা উপেক্ষা করে)।

এখানে একটি বৈকল্পিকও রয়েছে যা পূর্বের রূপটিকে প্রথম (শেষের চেয়ে বরং) যুক্তি হিসাবে সন্নিবেশ করায়। একটি ব্যবহারের ক্ষেত্রে পাটিগণিত:

(-> 17 (- 2) (/ 3))

"17 নিন, 2 কে বিয়োগ করুন এবং 3 দ্বারা ভাগ করুন" হিসাবে পড়ে।

পাটিগণিতের কথা বললে, আপনি এমন ম্যাক্রো লিখতে পারেন যা ইনফিক্স নোটেশন পার্সিং করে, যাতে আপনি উদাহরণস্বরূপ বলতে পারেন (infix (17 - 2) / 3)এবং এটি থুতুতে পারে (/ (- 17 2) 3)যা কম পঠনযোগ্য হওয়ার অসুবিধা এবং বৈধ লিস্প এক্সপ্রেশন হওয়ার সুবিধা রয়েছে। এটি ডিএসএল / ডেটা সাবল্যাংয়েজি অংশ।


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