লিস্প ম্যাক্রোসকে কী এত বিশেষ করে তোলে?


297

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

দয়া করে পাইথন, জাভা, সি # বা সি বিকাশের পৃথিবীগুলি থেকে আমি বুঝতে পারি এমন কোনও কিছুর সাথে এটি সম্পর্কিতও করুন।


2
যাইহোক, সি # এর জন্য এলএমএসপি-স্টাইলের ম্যাক্রো প্রসেসর রয়েছে যা এলএমপি নামে পরিচিত: ecsharp.net/lemp ... জাভাস্ক্রিপ্টটিতে সুইট.জেএস নামে একটি রয়েছে: সুইডজ.এস.আরজি
কিওয়ার্টি

@ কিওয়ার্টি কি আজকাল মিষ্টিগুলি কি কাজ করে?
fredrik.hjarner

আমি এটি ব্যবহার করি নি তবে সবচেয়ে সাম্প্রতিক প্রতিশ্রুতি ছয় মাস আগে হয়েছিল ... আমার পক্ষে যথেষ্ট ভাল!
কিওয়ার্টি

উত্তর:


308

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

এখানে আরও দৃ concrete় উদাহরণ:
পাইথনের ভাষায় অন্তর্নিহিত তালিকা বোঝার রয়েছে। এটি একটি সাধারণ ক্ষেত্রে সহজ সরল বাক্য গঠন দেয়। লাইন

divisibleByTwo = [x for x in range(10) if x % 2 == 0]

0 এবং 9 এর মধ্যে সমস্ত সমান সংখ্যার সমন্বিত একটি তালিকা উত্পন্ন করে পাইথন 1.5 দিনের মধ্যে এই জাতীয় সিনট্যাক্স ছিল না; আপনি এই জাতীয় কিছু ব্যবহার করতে চান:

divisibleByTwo = []
for x in range( 10 ):
   if x % 2 == 0:
      divisibleByTwo.append( x )

এগুলি উভয়ই কার্যত সমতুল্য। আসুন আমাদের অবিশ্বাসের স্থগিতাদেশ প্রার্থনা করি এবং ভান করি লিস্পের একটি খুব সীমাবদ্ধ লুপ ম্যাক্রো রয়েছে যা কেবল পুনরাবৃত্তি করে এবং তালিকা বোধগমের সমতুল্য করার সহজ উপায় না way

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

;; the following two functions just make equivalent of Python's range function
;; you can safely ignore them unless you are running this code
(defun range-helper (x)
  (if (= x 0)
      (list x)
      (cons x (range-helper (- x 1)))))

(defun range (x)
  (reverse (range-helper (- x 1))))

;; equivalent to the python example:
;; define a variable
(defvar divisibleByTwo nil)

;; loop from 0 upto and including 9
(loop for x in (range 10)
   ;; test for divisibility by two
   if (= (mod x 2) 0) 
   ;; append to the list
   do (setq divisibleByTwo (append divisibleByTwo (list x))))

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

অবশ্যই এটি প্রচুর টাইপিং এবং প্রোগ্রামাররা অলস। সুতরাং আমরা তালিকা বোঝার জন্য ডিএসএল সংজ্ঞায়িত করতে পারি। আসলে, আমরা ইতিমধ্যে একটি ম্যাক্রো ব্যবহার করছি (লুপ ম্যাক্রো)।

লিস্প কয়েকটি বিশেষ সিনট্যাক্স ফর্ম সংজ্ঞায়িত করে। উদ্ধৃতি ( ') নির্দেশ করে যে পরবর্তী টোকেনটি আক্ষরিক। কোয়াশিকোট বা ব্যাকটিক ( `) নির্দেশ করে যে পরবর্তী টোকেনটি আটকানো সহ আক্ষরিক। পালানো কমা অপারেটর দ্বারা নির্দেশিত হয়। আক্ষরিক '(1 2 3)পাইথনের সমতুল্য [1, 2, 3]। আপনি এটিকে অন্য পরিবর্তনশীলকে বরাদ্দ করতে পারেন বা এটি জায়গায় ব্যবহার করতে পারেন। আপনি `(1 2 ,x)পাইথনের সমতুল্য হিসাবে ভাবতে পারেন [1, 2, x]যেখানে xপূর্বে সংজ্ঞাযুক্ত একটি পরিবর্তনশীল। এই তালিকা স্বরলিপিটি ম্যাক্রোতে চলে যাওয়া যাদুটির অংশ। দ্বিতীয় অংশটি লিস্প রিডার যা বুদ্ধিমানের সাথে কোডের জন্য ম্যাক্রোগুলিকে প্রতিস্থাপন করে তবে নীচে এটি সর্বোত্তম চিত্রিত:

সুতরাং আমরা একটি ম্যাক্রো সংজ্ঞায়িত করতে পারি lcomp(তালিকা বোঝার জন্য সংক্ষিপ্ত)। এটি সিনট্যাক্স হ'ল পাইথনের মতো হবে যা আমরা উদাহরণে ব্যবহার করেছি [x for x in range(10) if x % 2 == 0] -(lcomp x for x in (range 10) if (= (% x 2) 0))

(defmacro lcomp (expression for var in list conditional conditional-test)
  ;; create a unique variable name for the result
  (let ((result (gensym)))
    ;; the arguments are really code so we can substitute them 
    ;; store nil in the unique variable name generated above
    `(let ((,result nil))
       ;; var is a variable name
       ;; list is the list literal we are suppose to iterate over
       (loop for ,var in ,list
            ;; conditional is if or unless
            ;; conditional-test is (= (mod x 2) 0) in our examples
            ,conditional ,conditional-test
            ;; and this is the action from the earlier lisp example
            ;; result = result + [x] in python
            do (setq ,result (append ,result (list ,expression))))
           ;; return the result 
       ,result)))

এখন আমরা কমান্ড লাইনে কার্যকর করতে পারি:

CL-USER> (lcomp x for x in (range 10) if (= (mod x 2) 0))
(0 2 4 6 8)

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


51
লিস্পে তালিকা বোঝার বাস্তবায়ন করার জন্য +1, কেন হবে না?
সেকেবি

9
: @ckb বাস্তবিক পাতার মর্মর ইতিমধ্যে মান লাইব্রেরিতে একটি তালিকা ধী ম্যাক্রো হয়েছে (loop for x from 0 below 10 when (evenp x) collect x), এখানে আরো উদাহরণ । তবে প্রকৃতপক্ষে, লুপটি "কেবলমাত্র একটি ম্যাক্রো" (আমি আসলে এটি কিছুক্ষণ আগে স্ক্র্যাচ থেকে পুনরায় প্রয়োগ করেছি )
সুজান ডুপোরন

8
আমি জানি এটি প্রায় অপ্রাসঙ্গিক, তবে আমি সিনট্যাক্স এবং পার্সিংটি আসলে কীভাবে কাজ করে তা নিয়ে ভাবছি ... বলুন যে আমি lcompকে সেভাবে ডাকি (তার জন্য আইটেমটি "" থেকে "অ্যাজারটিইওপ" তে পরিবর্তন করেছি): (lcomp x azertyuiop x in ( পরিসর 10) যদি (= (% x 2) 0%) ম্যাক্রো এখনও প্রত্যাশার মতো কাজ করবে? অথবা লুপটিতে "ফর" পরামিতি ব্যবহার করা হয়েছে যাতে ডাকা হলে এটি "স্ট্রিং" হতে হবে?
বাবা

2
@ دادার সুতরাং, লুপটি আসলে অন্য একটি ম্যাক্রো এবং এর জন্য সেই ম্যাক্রোতে ব্যবহৃত একটি বিশেষ প্রতীক। আমি সহজেই লুপ ম্যাক্রো ছাড়াই ম্যাক্রো সংজ্ঞায়িত করতে পারতাম। যাইহোক, আমি থাকলে পোস্টটি আরও দীর্ঘ হত। লুপ ম্যাক্রো এবং এর সমস্ত বাক্য গঠন সিএলটিএল-এ সংজ্ঞায়িত করা হয়েছে ।
gte525u

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

105

আপনি এখানে লিস্প ম্যাক্রোর চারপাশে একটি বিস্তৃত বিতর্ক পাবেন ।

এই নিবন্ধটির একটি আকর্ষণীয় উপসেট:

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

তবে লিসপ আলাদা। পাতার মর্মর ম্যাক্রো না পার্সার এক্সেস আছে, এবং এটি একটি অত্যন্ত সহজ পার্সার হয়। একটি লিস্প ম্যাক্রো একটি স্ট্রিং হস্তান্তর করা হয় না, তবে তালিকার আকারে উত্স কোডের একটি প্রস্তুত টুকরো টুকরো কারণ লিস্প প্রোগ্রামের উত্স একটি স্ট্রিং নয়; এটি একটি তালিকা। এবং লিস্প প্রোগ্রামগুলি তালিকাগুলি আলাদা করে এনে আবার একত্রে রাখার পক্ষে সত্য good তারা প্রতিদিন এটি নির্ভরযোগ্যভাবে করে।

এখানে একটি বর্ধিত উদাহরণ। লিস্পের একটি ম্যাক্রো রয়েছে, যার নাম "সেটফ", যা কার্য সম্পাদন করে। সেটফের সহজতম রূপটি

  (setf x whatever)

যা "x" চিহ্নটির মান "যাই হোক না কেন" এক্সপ্রেশনটির মান সেট করে।

লিস্পেরও তালিকা রয়েছে; আপনি তালিকার প্রথম উপাদান বা তালিকার বাকি উপাদানগুলি যথাক্রমে পেতে "গাড়ী" এবং "সিডিআর" ফাংশন ব্যবহার করতে পারেন।

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

  (setf (car somelist) whatever)

কারও তালিকার গাড়ি সেট করতে।

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

  (rplaca somelist whatever)

5
সেটফ ম্যাক্রোগুলির শক্তির একটি দুর্দান্ত চিত্রণ, এটি অন্তর্ভুক্ত করার জন্য ধন্যবাদ।
জোয়েল

আমি হাইলাইটটি পছন্দ করি .. কারণ লিস্প প্রোগ্রামের উত্সটি কোনও স্ট্রিং নয়; এটি একটি তালিকা। ! এলআইএসপি ম্যাক্রোটির বন্ধনীর কারণে অন্যান্যদের চেয়ে বেশিরভাগের চেয়ে বড় হওয়ার মূল কারণ কি?
শিক্ষার্থী

@ স্টুডেন্ট আমার ধারণা তাই: Books.google.fr/… আপনাকে সঠিক বলে প্রস্তাব দেয়।
ভোনসি

55

সাধারণ লিস্প ম্যাক্রোগুলি মূলত আপনার কোডটির "সিনট্যাকটিক আদিম" প্রসারিত করে।

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

তবে, যেহেতু একটি লিস্প ম্যাক্রো (মূলত) একটি লিস্প প্রোগ্রাম যা ম্যাক্রোর "অনুরোধ" প্রতিস্থাপনের জন্য কোডের স্নিপেটগুলি ইনপুট হিসাবে গ্রহণ করে এবং কোডটি রিটার্ন করে, আপনি আপনার "আদিম" পুস্তকটি যতটা ইচ্ছা প্রসারিত করতে পারেন, সাধারণত শেষ পর্যন্ত আরও পঠনযোগ্য প্রোগ্রাম সহ।

সি তে এটি করার জন্য, আপনাকে একটি কাস্টম প্র-প্রসেসর লিখতে হবে যা আপনার প্রাথমিক (প্রচুর সি নয়) উত্সটি খায় এবং কোনও সি কম্পাইলার বুঝতে পারে এমন কিছু স্পিট করে। এটি যাওয়ার কোনও ভুল উপায় নয়, তবে এটি সহজতম নয় not


41

লিস্প ম্যাক্রো আপনাকে কখন (কোনও অংশে) কোনও অংশ বা ভাবের মূল্যায়ন হবে তা সিদ্ধান্ত নিতে দেয় decide একটি সাধারণ উদাহরণ রাখার জন্য, সি এর কথা চিন্তা করুন:

expr1 && expr2 && expr3 ...

এটি যা বলে তা হ'ল: মূল্যায়ন করুন expr1এবং এটি কি সত্য হওয়া উচিত, মূল্যায়ন করা expr2ইত্যাদি

এখন এটিকে &&কোনও ফাংশনে পরিণত করার চেষ্টা করুন ... ঠিক আছে, আপনি পারবেন না। এরকম কিছু কল করা:

and(expr1, expr2, expr3)

মিথ্যা exprsকিনা তা নির্বিশেষে উত্তর দেওয়ার আগে তিনটিকেই মূল্যায়ন করবে expr1!

লিসপ ম্যাক্রোগুলির সাহায্যে আপনি এমন কিছু কোড করতে পারেন:

(defmacro && (expr1 &rest exprs)
    `(if ,expr1                     ;` Warning: I have not tested
         (&& ,@exprs)               ;   this and might be wrong!
         nil))

এখন আপনার একটি রয়েছে &&, যা আপনি ঠিক একটি ফাংশনের মতো কল করতে পারেন এবং এটি যদি সত্য হয় না তবে আপনি এতে যে কোনও ফর্ম পাঠিয়েছেন তা মূল্যায়ন করবে না।

এটি কীভাবে কার্যকর তা দেখতে, বিপরীতে:

(&& (very-cheap-operation)
    (very-expensive-operation)
    (operation-with-serious-side-effects))

এবং:

and(very_cheap_operation(),
    very_expensive_operation(),
    operation_with_serious_side_effects());

ম্যাক্রোগুলির সাহায্যে আপনি যা করতে পারেন সেগুলি নতুন কীওয়ার্ড এবং / বা মিনি-ভাষা তৈরি করছে ( (loop ...)উদাহরণস্বরূপ ম্যাক্রোটি পরীক্ষা করে দেখুন ), অন্যান্য ভাষাগুলি লিস্পে সংহত করে, উদাহরণস্বরূপ, আপনি একটি ম্যাক্রো লিখতে পারেন যা আপনাকে এমন কিছু বলতে দেয়:

(setvar *rows* (sql select count(*)
                      from some-table
                     where column1 = "Yes"
                       and column2 like "some%string%")

এবং এমনকি রিডার ম্যাক্রোতেও gettingুকছে না ।

আশাকরি এটা সাহায্য করবে.


আমি মনে করি এটি হওয়া উচিত: "(&&&, @ exprs প্রয়োগ করুন); এটি এবং ভুল হতে পারে!"
সোভান্তে

1
@ সোভান্তে - দুটি গুণে: প্রথমটি, && একটি ম্যাক্রো, কোনও ফাংশন নয়; প্রয়োগ শুধুমাত্র ফাংশন উপর কাজ করে। দ্বিতীয়ত, পাস করার জন্য আর্গুমেন্টের একটি তালিকা নিয়ে প্রয়োগ করুন, সুতরাং আপনি "(ফানক্যাল এফএন, @ এক্সপ্রেস)", "(এফএন (তালিকা, @ এক্সপ্রেস প্রয়োগ করুন)" বা "(এফএন, @ এক্সপ্রেস নীল প্রয়োগ করুন)" চান না "(FN আবেদন, @ exprs)"।
হারুন

(and ...মিথ্যাতে মূল্যায়ন না করা পর্যন্ত অভিব্যক্তিগুলির মূল্যায়ন করা হবে, নোট করুন যে মিথ্যা মূল্যায়নের ফলে উত্পন্ন পার্শ্ব-প্রতিক্রিয়া সংঘটিত হবে, কেবল পরবর্তী অভিব্যক্তিগুলি এড়িয়ে যাবে।
অক্টোডো

31

আমি মনে করি না যে আমি লিপ ম্যাক্রোগুলি এই সহকর্মীর চেয়ে আরও ভালভাবে ব্যাখ্যা করতে দেখেছি: http://www.defmacro.org/ramblings/lisp.html


3
বিশেষত আপনার যদি জাভা / এক্সএমএল ব্যাকগ্রাউন্ড থাকে।
রোদ

1
শনিবার বিকেলে আমার সোফায় শুয়ে পড়ে এটি কী আনন্দ! খুব স্পষ্টভাবে লিখিত এবং সংগঠিত।
কলিন

10

আপনি ম্যাক্রো এবং টেম্পলেটগুলির সাহায্যে সি বা সি ++ এ কী করতে পারেন তা ভেবে দেখুন। পুনরাবৃত্ত কোড পরিচালনার জন্য এগুলি খুব কার্যকর সরঞ্জাম, তবে তারা বেশ গুরুতর উপায়ে সীমিত।

  • সীমিত ম্যাক্রো / টেমপ্লেট সিনট্যাক্স তাদের ব্যবহারকে সীমাবদ্ধ করে। উদাহরণস্বরূপ, আপনি কোনও টেম্পলেট লিখতে পারবেন না যা শ্রেণি বা ফাংশন ব্যতীত অন্য কিছুতে প্রসারিত হয়। ম্যাক্রো এবং টেম্পলেটগুলি সহজেই অভ্যন্তরীণ ডেটা বজায় রাখতে পারে না।
  • সি এবং সি ++ এর জটিল, খুব অনিয়মিত বাক্য গঠন খুব সাধারণ ম্যাক্রোগুলি লিখতে অসুবিধা সৃষ্টি করে।

লিস্প এবং লিস্প ম্যাক্রোগুলি এই সমস্যাগুলি সমাধান করে।

  • লিস্প ম্যাক্রোগুলি লিপ্পে লেখা হয়। আপনার কাছে ম্যাক্রো লেখার পুরো শক্তি আছে।
  • লিস্পের খুব নিয়মিত বাক্য গঠন রয়েছে।

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


11
ভাল, সত্যি কথা বলতে, সি ++ টেম্পলেট মেটাপোগ্র্যামিংয়ের সমস্যাটি নয় যে রূপক ভাষা আলাদা , তবে এটি ভয়াবহ - এটি এতটা ডিজাইন করা হয়নি যা সর্বাধিক সরল টেম্পলেট কার্যকারিতা হিসাবে চিহ্নিত হয়েছিল in
ব্রুকস মুসা

@ ব্রুকস শিওর জরুরী বৈশিষ্ট্যগুলি সবসময় খারাপ হয় না। দুর্ভাগ্যক্রমে, একটি ধীর চলমান কমিটি চালিত ভাষায়, তারা যখন থাকে তখন তাদের সংশোধন করা কঠিন। এটি লজ্জার বিষয় যে C ++ এর আধুনিক দরকারী নতুন বৈশিষ্ট্যগুলি এমন একটি ভাষায় লেখা আছে যা কয়েক জন এমনকি পড়তে পারে এবং গড় প্রোগ্রামার এবং "মহাযাজক" এর মধ্যে বিশাল ব্যবধান রয়েছে।
ম্যাট কার্টিস

2
@ ডাউনভোটার: আমার উত্তরে যদি কিছু ভুল হয় তবে দয়া করে একটি মন্তব্য দিন যাতে আমরা সবাই জ্ঞান ভাগ করে নিতে পারি।
ম্যাট কার্টিস

10

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

সি # এর ম্যাক্রো সুবিধা নেই, তবে একটি সমতুল্য হবে যদি সংকলক কোডটি কোডডোম-ট্রিতে পার্স করে এবং কোনও পদ্ধতিতে পাস করে, যা এটি অন্য কোডডোমে রূপান্তরিত করে, যা পরে আইএলে সংকলিত হয়।

এই বাস্তবায়ন মত "চিনি" সিনট্যাক্স ব্যবহার করা যেতে পারে for each-statement using-clause, linq select, -expressions ইত্যাদি ম্যাক্রো যেমন অন্তর্নিহিত কোড রূপান্তরিত হয়।

জাভাতে যদি ম্যাক্রোগুলি থাকে তবে আপনি জাভাতে লিনক সিনট্যাক্স প্রয়োগ করতে পারবেন, বেস ভাষা পরিবর্তন করার জন্য সূর্যের প্রয়োজন ছাড়াই।

বাস্তবায়নের জন্য সি # তে লিস্প-স্টাইলের ম্যাক্রো usingকীভাবে দেখতে পারে তার জন্য সিউডো কোডটি এখানে রয়েছে :

define macro "using":
    using ($type $varname = $expression) $block
into:
    $type $varname;
    try {
       $varname = $expression;
       $block;
    } finally {
       $varname.Dispose();
    }

এখন যেহেতু সেখানে আসলে হয় C # এর জন্য একটি পাতার মর্মর-শৈলী ম্যাক্রো প্রসেসর, আমি নির্দেশ করবে যে জন্য একটি ম্যাক্রো usingহবে ভালো চেহারা ;)
Qwertie

9

যেহেতু বিদ্যমান উত্তরগুলি ম্যাক্রোগুলি কী অর্জন করে এবং কীভাবে তা ব্যাখ্যা করার জন্য ভাল কংক্রিটের উদাহরণ দেয়, সম্ভবত ম্যাক্রো সুবিধাগুলি অন্যান্য ভাষার সাথে সম্পর্কিত হওয়ার জন্য এটি কেন কিছু ধারণা একত্রিত করতে সহায়তা করবে ; প্রথমে এই উত্তরগুলি থেকে, তারপরে অন্য কোথাও একটি দুর্দান্ত:

... সি তে, আপনাকে একটি কাস্টম প্র-প্রসেসর লিখতে হবে [যা সম্ভবত যথেষ্ট জটিল সি প্রোগ্রাম হিসাবে যোগ্যতা অর্জন করবে ] ...

- ভ্যাটাইন

সি ++ তে আয়ত্তকৃত যেকোন ব্যক্তির সাথে কথা বলুন এবং তাদের সমস্ত টেম্পলেট ফজরি শিখতে কত দিন ব্যয় করেছেন তাদের জিজ্ঞাসা করুন টেমপ্লেট মেটাপ্রগ্রামিং করা (যা এখনও তেমন শক্তিশালী নয়)।

- ম্যাট কার্টিস

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

- মিগুয়েল পিং

ডোলিস্ট পার্লের পূর্বাভাস বা পাইথনের জন্য অনুরূপ। জাভা জেএসআর -2018 এর অংশ হিসাবে জাভা 1.5 তে লুপের জন্য "বর্ধিত" সাথে একই ধরণের লুপ কনস্ট্রাক্ট যুক্ত করেছে। ম্যাক্রোগুলি কী পার্থক্য করে তা লক্ষ্য করুন। একটি লিস্প প্রোগ্রামার যিনি তাদের কোডে একটি সাধারণ প্যাটার্ন লক্ষ্য করেন তারা নিজেরাই সেই ধরণের একটি উত্স-স্তরের বিমূর্ততা দিতে ম্যাক্রো লিখতে পারেন। কোনও জাভা প্রোগ্রামার যিনি একই প্যাটার্নটি লক্ষ্য করেন তাদের সানকে বোঝাতে হবে যে এই বিশেষ বিমূর্ততা ভাষায় যুক্ত করার মতো। তারপরে সানকে জেএসআর প্রকাশ করতে হবে এবং সমস্ত কিছু বের করার জন্য একটি শিল্প-প্রশস্ত "বিশেষজ্ঞ গ্রুপ" ডেকে আনতে হবে। এই প্রক্রিয়া - সূর্যের মতে - গড়ে 18 মাস সময় লাগে। এর পরে, সংকলক লেখকগণকে নতুন বৈশিষ্ট্য সমর্থন করার জন্য তাদের সংকলকগুলি আপগ্রেড করতে হবে। এমনকি একবারও জাভা প্রোগ্রামারের প্রিয় সংকলক জাভার নতুন সংস্করণ সমর্থন করে, তারা সম্ভবত '' এখনও '' নতুন বৈশিষ্ট্যটি ব্যবহার করতে পারবেন না যতক্ষণ না তাদের জাভার পুরানো সংস্করণগুলির সাথে উত্সের সামঞ্জস্যতা ভঙ্গ করার অনুমতি দেওয়া হয়। সুতরাং একটি বিরক্তি যা প্রচলিত লিস্প প্রোগ্রামাররা কয়েক বছর ধরে জাভা প্রোগ্রামারদের পাঁচ মিনিটের মধ্যে নিজের জন্য সমাধান করতে পারে।

- পিটার Seibel, "ব্যবহারিক প্রচলিত লিপ"


8

আমি নিশ্চিত নই যে আমি প্রত্যেকের (দুর্দান্ত) পোস্টগুলিতে কিছুটা অন্তর্দৃষ্টি যুক্ত করতে পারি তবে ...

লিসপ ম্যাক্রোস লিস্প সিনট্যাক্স প্রকৃতির কারণে দুর্দান্ত কাজ করে।

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

সম্পাদনা: আমি যা বলতে চাইছিলাম তা হ'ল লিস্প হমাইকোনিক , যার অর্থ একটি লিস্প প্রোগ্রামের ডেটা স্ট্রাকচারটি লিস্পে নিজেই লেখা হয়।

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

বাস্তবে, ম্যাক্রো সঙ্গে আপনি আপনার নিজের বিল্ডিং শেষ মিনি ভাষার , আর নিজেই ভাষার পূর্ণ ক্ষমতা ব্যবহার করে অতিরিক্ত languages বা সাধনী দ্বারা প্রয়োগকরণ শেখা প্রয়োজন ছাড়াই, পাতার মর্মর উপরে।


1
এটি অন্তর্দৃষ্টিপূর্ণ মন্তব্য, তবে এই ধারণাটি যে "সবকিছুই একটি তালিকা" আগতদেরকে ভয় দেখাতে পারে। একটি তালিকা বুঝতে আপনার কনস, গাড়ি, সিডিআর, সেলগুলি বুঝতে হবে। আরও স্পষ্টভাবে বলতে গেলে, লিস্পটি S-expressionsতালিকা তৈরি করেই তৈরি ।
ribamar

6

লিসপ ম্যাক্রো এমন একটি প্যাটার্ন উপস্থাপন করে যা প্রায় কোনও আকারের প্রোগ্রামিং প্রকল্পে ঘটে। শেষ পর্যন্ত একটি বড় প্রোগ্রামে আপনার একটি কোডের একটি নির্দিষ্ট বিভাগ থাকে যেখানে আপনি বুঝতে পারেন যে এটি এমন একটি প্রোগ্রাম লিখতে আপনার পক্ষে সহজ এবং কম ত্রুটি প্রবণতা হবে যা উত্স কোডটিকে পাঠ্য হিসাবে আউটপুট করে যা আপনি কেবল এতে পেস্ট করতে পারেন।

পাইথন অবজেক্টে দুটি পদ্ধতি রয়েছে __repr__এবং __str____str__সহজভাবে মানুষের পাঠযোগ্য উপস্থাপনা। __repr__বৈধ পাইথন কোড, এমন একটি উপস্থাপনা ফেরত দেয় যা বলতে হয়, এমন কিছু যা দোভাষীকে বৈধ পাইথন হিসাবে প্রবেশ করতে পারে। এইভাবে আপনি পাইথনের সামান্য স্নিপেট তৈরি করতে পারেন যা বৈধ কোড তৈরি করে যা আপনার প্রকৃত উত্সে আটকানো যেতে পারে।

লিস্পে এই পুরো প্রক্রিয়াটি ম্যাক্রো সিস্টেম দ্বারা আনুষ্ঠানিকভাবে করা হয়েছে। নিশ্চিত হয়ে নিন যে এটি আপনাকে সিনট্যাক্সের জন্য এক্সটেনশান তৈরি করতে এবং সমস্ত ধরণের অভিনব কাজ করতে সক্ষম করে, তবে এটি প্রকৃত উপযোগিতা সংক্ষেপে উপরে বর্ণিত হয়েছে। অবশ্যই এটি সাহায্য করে যে লিস্প ম্যাক্রো সিস্টেম আপনাকে এই "স্নিপেটগুলি" পুরো ভাষার সম্পূর্ণ ক্ষমতা দিয়ে পরিচালনা করতে দেয়।


1
আপনার প্রথম অনুচ্ছেদটি লিস্পের বহিরাগতের কাছে খুব স্পষ্ট, যা গুরুত্বপূর্ণ।
ওয়াইল্ডকার্ড

5

সংক্ষেপে, ম্যাক্রোজ হ'ল কোডের রূপান্তর। তারা অনেকগুলি নতুন সিনট্যাক্স কনস্ট্রাক্টস প্রবর্তনের অনুমতি দেয়। উদাহরণস্বরূপ, সি # তে লাইনকিউ বিবেচনা করুন। লিসপে, অনুরূপ ভাষার বর্ধন রয়েছে যা ম্যাক্রো দ্বারা প্রয়োগ করা হয় (যেমন বিল্ট-ইন লুপ কনস্ট্রাক্ট, পুনরাবৃত্তি)। ম্যাক্রোগুলি কোডের নকলকে উল্লেখযোগ্যভাবে হ্রাস করে। ম্যাক্রোসগুলি «ছোট ভাষাগুলি e এম্বেড করার অনুমতি দেয় (উদাহরণস্বরূপ, যেখানে সি # / জাভাতে কেউ কনফিগার করার জন্য এক্সএমএল ব্যবহার করবে, লিস্পে ম্যাক্রো দিয়ে একই জিনিস অর্জন করা যেতে পারে)। ম্যাক্রোগুলি গ্রন্থাগার ব্যবহারের সমস্যাগুলি আড়াল করতে পারে।

যেমন, লিস্পে আপনি লিখতে পারেন

(iter (for (id name) in-clsql-query "select id, name from users" on-database *users-database*)
      (format t "User with ID of ~A has name ~A.~%" id name))

এবং এটি সমস্ত ডাটাবেস স্টাফগুলি লুকিয়ে রাখে (লেনদেন, সঠিক সংযোগ বন্ধ, ডেটা আনা ইত্যাদি) যেখানে সি # তে এর জন্য এসকিএল সংযোগগুলি, এসকিএলকম্যান্ডস তৈরি করা প্রয়োজন, স্কেলকম্যান্ডগুলিতে স্ক্যালিপ্যারামিটার যুক্ত করা, স্ক্যালডেটারেডারগুলিতে লুপিং করা, সেগুলি সঠিকভাবে বন্ধ করা দরকার।


3

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

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

    (defmacro working-timer (b) 
      (let (
            (start (get-universal-time))
            (result (eval b))) ;; not splicing here to keep stuff simple
        ((- (get-universal-time) start))))
    
    (defun my-broken-timer (b)
      (let (
            (start (get-universal-time))
            (result (eval b)))    ;; doesn't even need eval
        ((- (get-universal-time) start))))
    
    (working-timer (sleep 10)) => 10
    
    (broken-timer (sleep 10)) => 0

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

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

0

আমি এটি সাধারণ লিস্প কুকবুক থেকে পেয়েছি তবে আমি মনে করি এটি কেন লিস্প ম্যাক্রোগুলি দুর্দান্ত উপায়ে ভাল।

"ম্যাক্রো লিস্প কোডের একটি সাধারণ টুকরা যা পুটিটিভ লিস্প কোডের অন্য টুকরোতে চালিত হয়, এটি এক্সিকিউটেবল লিস্পে অনুবাদ করে (এটির কাছাকাছি সংস্করণ) কার্যকর করা যায় That যা কিছুটা জটিল মনে হতে পারে, তাই আসুন একটি সহজ উদাহরণ দেওয়া যাক ose ধরুন আপনি একটি চান সেটকের সংস্করণ যা একই মানতে দুটি ভেরিয়েবল সেট করে So সুতরাং আপনি যদি লিখেন

(setq2 x y (+ z 3))

যখন z=8x এবং y উভয়ই ১১ এ সেট করা হয় (আমি এর জন্য কোনও ব্যবহারের কথা ভাবতে পারি না, তবে এটি কেবল একটি উদাহরণ))

এটা স্পষ্ট হওয়া উচিত যে আমরা setq2 কে একটি ফাংশন হিসাবে সংজ্ঞায়িত করতে পারি না। যদি x=50এবং y=-5, এই ফাংশনটি 50, -5 এবং 11 মানগুলি গ্রহণ করবে; কোন ভেরিয়েবল সেট করার কথা ছিল তার কোনও জ্ঞান থাকবে না। আমরা যা বলতে চাই তা হ'ল আপনি যখন (লিস্প সিস্টেম) দেখেন তখন (setq2 v1 v2 e)এটি সমতুল্য হিসাবে বিবেচনা করুন (progn (setq v1 e) (setq v2 e))। আসলে, এটি বেশ সঠিক নয়, তবে এটি এখনই করবে for (setq2 v1 v2 e)"আউটপুট প্যাটার্নে" ইনপুট প্যাটার্নকে রূপান্তর করার জন্য একটি প্রোগ্রাম নির্দিষ্ট করে একটি ম্যাক্রো আমাদের সঠিকভাবে এটি করতে দেয় (progn ...)

যদি আপনি ভেবেছিলেন এটি দুর্দান্ত ছিল আপনি এখানে পড়া চালিয়ে যেতে পারেন: http : //cl-cookbook.s Sourceforge.net/macros.html


1
এটা তোলে সংজ্ঞায়িত করা সম্ভব setq2যদি একটি ফাংশন হিসাবে xএবং yরেফারেন্স দ্বারা পাঠানো হয়। তবে সিএল এ সম্ভব কিনা তা আমি জানি না। সুতরাং যে কেউ বিশেষত লিপস বা সিএল জানেন না তাদের পক্ষে এটি খুব উদাহরণস্বরূপ উদাহরণ নয় আইএমও
নিউওসেসটিক

@ নিউওসেসটিক সিএল আর্গুমেন্টটি কেবল মূল্য দিয়ে হয় (এজন্য এটির জন্য প্রথম স্থানে ম্যাক্রোগুলির প্রয়োজন হয়)। কিছু মান পয়েন্টার হলেও (তালিকার মতো)।
নেস 16

-5

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

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