এলআইএসপি সম্পর্কে কী, যদি কিছু থাকে তবে ম্যাক্রো সিস্টেমগুলি প্রয়োগ করা সহজ করে তোলে?


21

আমি এসআইসিপি থেকে স্কিম শিখছি এবং আমি এই ধারণাটি পেয়ে যাচ্ছি যে স্কিমটি কী করে তার একটি বড় অংশ এবং আরও বেশি, এলআইএসপি বিশেষত ম্যাক্রো সিস্টেম। তবে, যেহেতু ম্যাক্রোগুলি সংকলন সময়ে প্রসারিত হয়েছে, কেন লোকেরা সি / পাইথন / জাভা / যাই হোক না কেন সমান ম্যাক্রো সিস্টেম তৈরি করে না? উদাহরণস্বরূপ, কেউ pythonকমান্ড expand-macros | pythonবা যাই হোক না কেন বাঁধাই করতে পারে । কোডটি এখনও ম্যাক্রো সিস্টেমটি ব্যবহার না করে এমন লোকদের কাছে পোর্টেবল হবে, কোড প্রকাশের আগে একজন কেবল ম্যাক্রোগুলি প্রসারিত করবে। তবে আমি সি ++ / হাস্কেলের টেম্পলেটগুলি বাদে এর মতো কিছুই জানি না, যা আমি সংগ্রহ করি তা আসলে একই নয়। এলআইএসপি সম্পর্কে কী, যদি কিছু থাকে তবে ম্যাক্রো সিস্টেমগুলি প্রয়োগ করা সহজ করে তোলে?


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

1
ম্যাক্রোগুলিকে কার্যকর করতে হবে যদিও সেই সময়ে আপনি ইতিমধ্যে ভাষার জন্য একজন দোভাষী লিখছেন।
মেহরদাদ

উত্তর:


29

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

(define (hypot x y)
  (sqrt (+ (square x) (square y))))

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

  1. (define #2# #3#)
  2. (hypot x y)
  3. (sqrt #4#)
  4. (+ #5# #6#)
  5. (square x)
  6. (square y)

ম্যাক্রোস আপনাকে উত্স কোডটি ঠিক তেমন আচরণ করার অনুমতি দেয়: স্টাফের তালিকা। সেই 6 "sublists" এর একে অপরের তালিকাতে পারেন পয়েন্টার থাকে, বা প্রতীক (এই উদাহরণে: define, hypot, x, y, sqrt, +, square)।


সুতরাং, আমরা কীভাবে হোমকোনসিটিটি সিনট্যাক্সকে "আলাদা" করতে এবং ম্যাক্রো তৈরি করতে পারি? এখানে একটি সহজ উদাহরণ। আসুন letম্যাক্রোটিকে পুনরায় প্রতিস্থাপন করুন , যা আমরা কল করব my-let। একটি অনুস্মারক হিসেবে,

(my-let ((foo 1)
         (bar 2))
  (+ foo bar))

মধ্যে প্রসারিত করা উচিত

((lambda (foo bar)
   (+ foo bar))
 1 2)

এখানে স্কিম "স্পষ্ট পুনঃনামকরনের" ম্যাক্রো ব্যবহার করে একটি বাস্তবায়ন এর :

(define-syntax my-let
  (er-macro-transformer
    (lambda (form rename compare)
      (define bindings (cadr form))
      (define body (cddr form))
      `((,(rename 'lambda) ,(map car bindings)
          ,@body)
        ,@(map cadr bindings)))))

formপরামিতি প্রকৃত ফর্ম আবদ্ধ হয়, তাই আমাদের উদাহরণস্বরূপ, এটি হবে (my-let ((foo 1) (bar 2)) (+ foo bar))। সুতরাং, আসুন উদাহরণের মাধ্যমে কাজ করা যাক:

  1. প্রথমে, আমরা ফর্মটি থেকে বাইন্ডিংগুলি পুনরুদ্ধার করি। ফর্ম অংশ cadrধরে ((foo 1) (bar 2))
  2. তারপরে, আমরা ফর্মটি থেকে দেহটি পুনরুদ্ধার করি। ফর্ম অংশ cddrধরে ((+ foo bar))। (নোট করুন যে এটি বাইন্ডিংয়ের পরে সমস্ত সাবফর্মগুলি দখল করার উদ্দেশ্যে; তাই যদি ফর্মটি থাকে

    (my-let ((foo 1)
             (bar 2))
      (debug foo)
      (debug bar)
      (+ foo bar))
    

    তাহলে শরীর হবে ((debug foo) (debug bar) (+ foo bar))।)

  3. এখন, আমরা প্রকৃতপক্ষে ফলাফলটি lambdaপ্রকাশ করি এবং আমাদের সংগ্রহ করা বাইন্ডিং এবং বডি ব্যবহার করে কল করি। ব্যাকটিক একটি "quasiquote", যা আক্ষরিক datums যেমন quasiquote ভিতরে আচরণ সবকিছু মানে বলা হয়, ব্যতীত কমা ( "উদ্ধতি") পর বিট।
    • (rename 'lambda)কোনো পদ্ধতি ব্যবহার করার জন্য lambdaএই ম্যাক্রো হয় বহাল বাঁধাই সংজ্ঞায়িত , বরং যাই হোক না কেন চেয়ে lambdaবাঁধাই কাছাকাছি হতে পারে এই ম্যাক্রো হয় ব্যবহৃত । (এটি স্বাস্থ্যবিধি হিসাবে পরিচিত ))
    • (map car bindings)রিটার্ন দেয় (foo bar): প্রতিটি বাইন্ডিংয়ের প্রথম ডেটাম।
    • (map cadr bindings)রিটার্ন দেয় (1 2): প্রতিটি বাইন্ডিংয়ের মধ্যে দ্বিতীয় ডাটাম।
    • ,@ "স্প্লাইকিং" করে, যা একটি তালিকা ফেরত দেওয়ার মত প্রকাশের জন্য ব্যবহৃত হয়: এটি তালিকার উপাদানগুলিকে তালিকার পরিবর্তে ফলাফলের মধ্যে আটকে দেয়।
  4. এই সমস্ত একসাথে রেখে, আমরা ফলস্বরূপ, তালিকাটি পাই (($lambda (foo bar) (+ foo bar)) 1 2), যেখানে $lambdaএখানে নাম পরিবর্তন করা হয়েছে lambda

সোজা, ঠিক? ;-) (এটি যদি আপনার পক্ষে সোজা না হয় তবে অন্য ভাষার জন্য ম্যাক্রো সিস্টেমটি প্রয়োগ করা কতটা কঠিন হবে তা ভেবে দেখুন))


সুতরাং, আপনার কাছে অন্যান্য ভাষার জন্য ম্যাক্রো সিস্টেম থাকতে পারে, যদি আপনার কাছে একটি উপায় থাকে তবে নন-ক্লঙ্কি উপায়ে সোর্স কোডটিকে "আলাদা" করতে সক্ষম হবেন। এ নিয়ে কিছু চেষ্টা আছে। উদাহরণস্বরূপ, sweet.js জাভাস্ক্রিপ্টের জন্য এটি করে।

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

রেফারেন্সের জন্য, my-letম্যাক্রো যা ব্যবহার করে তা এখানে syntax-rules:

(define-syntax my-let
  (syntax-rules ()
    ((my-let ((id val) ...)
       body ...)
     ((lambda (id ...)
        body ...)
      val ...))))

সম্পর্কিত syntax-caseসংস্করণটি দেখতে খুব অনুরূপ:

(define-syntax my-let
  (lambda (stx)
    (syntax-case stx ()
      ((_ ((id val) ...)
         body ...)
       #'((lambda (id ...)
            body ...)
          val ...)))))

দুই এর মধ্যে পার্থক্য যে সবকিছু মধ্যে syntax-rulesএকটি অন্তর্নিহিত রয়েছে #', ফলিত যাতে আপনি করতে পারেন শুধুমাত্র মধ্যে প্যাটার্ন / টেমপ্লেট জোড়া আছে syntax-rules, অত এটা সম্পূর্ণরূপে ঘোষণামূলক আছে। বিপরীতে, এর মধ্যে syntax-case, প্যাটার্নের পরে বিটটি আসল কোড যা শেষ পর্যন্ত একটি সিনট্যাক্স অবজেক্ট ( #'(...)) ফিরিয়ে দিতে হবে তবে অন্যান্য কোডও এতে থাকতে পারে।


2
একটি সুবিধা আপনি উল্লেখ করেননি: হ্যাঁ, অন্যান্য ভাষায় যেমন জেএস এর জন্য মিষ্টি.জেএস এর চেষ্টা রয়েছে। যাইহোক, লিসপ্সে, কোনও ফাংশন লেখার মতো একই ভাষায় ম্যাক্রো লেখা হয়।
ফ্লোরিয়ান মার্জাইন

ঠিক আছে, আপনি লিস্প ভাষায় প্রক্রিয়াভিত্তিক (বনাম ঘোষিত) ম্যাক্রোগুলি লিখতে পারেন, এটিই আপনাকে সত্যিকারের উন্নত স্টাফগুলি করতে দেয়। বিটিডাব্লু, স্কিম ম্যাক্রো সিস্টেমগুলি সম্পর্কে এটি আমার পছন্দ: চয়ন করার জন্য একাধিক রয়েছে। সাধারণ ম্যাক্রোগুলির জন্য, আমি ব্যবহার করি syntax-rules, যা নিখুঁতভাবে ঘোষিত। জটিল ম্যাক্রোগুলির জন্য, আমি এটি ব্যবহার করতে পারি syntax-case, যা আংশিক ঘোষণামূলক এবং আংশিক পদ্ধতিগত। এবং তারপরে সুস্পষ্ট পুনঃনামকরণ রয়েছে যা খাঁটি পদ্ধতিগত। (বেশিরভাগ স্কিম বাস্তবায়ন উভয়ই syntax-caseবা ER সরবরাহ করবে both আমি উভয় সরবরাহ করে এমন একটিও দেখিনি They তারা ক্ষমতার সমতুল্য))
ক্রিস জেস্টার-ইয়ং

ম্যাক্রোগুলিকে কেন এএসটি সংশোধন করতে হবে? কেন তারা উচ্চ স্তরে কাজ করতে পারে না?
এলিয়ট গোরোকভস্কি

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

3
@ রেনজি যেমন আমি আমার প্রথম মন্তব্যে বলেছি, একটি বড় সুবিধা হ'ল আপনি এখনও একই ভাষায় লিখছেন।
ফ্লোরিয়ান মার্জাইন

23

ভিন্নমত পোষণকারী মতামত: বেশিরভাগ লিস্প ফ্যানদের বিশ্বাসের চেয়ে লিস্পের হোমসাইকোনসিটি কোনও দরকারী জিনিসের চেয়ে অনেক কম।

সিনট্যাকটিক ম্যাক্রোগুলি বুঝতে, সংকলকগুলি বুঝতে গুরুত্বপূর্ণ। সংকলকের কাজ হ'ল মানব-পঠনযোগ্য কোডটিকে সম্পাদনযোগ্য কোডে পরিণত করা। খুব উচ্চ-স্তরের দৃষ্টিকোণ থেকে, এর দুটি সামগ্রিক পর্যায় রয়েছে: পার্সিং এবং কোড জেনারেশন

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

কোড জেনারেশন পার্সারের এএসটিটিকে তার ইনপুট হিসাবে গ্রহণ করে এবং আনুষ্ঠানিক বিধি প্রয়োগের মাধ্যমে এটিকে সম্পাদনযোগ্য কোডে রূপান্তর করে। পারফরম্যান্সের দৃষ্টিকোণ থেকে, এটি অনেক সহজ কাজ; অনেক উচ্চ-স্তরের ভাষা সংকলক পার্সিংয়ে তাদের 75% বা তার বেশি সময় ব্যয় করে।

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

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

সংকলক তত্ত্বটি ১৯60০ এর দশক থেকে লিস্পের আবিষ্কারের পরে অনেক এগিয়ে এসেছিল এবং যখন এটি সম্পাদিত জিনিসগুলি তার দিনের জন্য চিত্তাকর্ষক ছিল, তারা এখন বরং আদিম বলে মনে হয়। একটি আধুনিক রূপক পদ্ধতির উদাহরণের জন্য, (দু: খজনকভাবে underappreciated) বু ভাষাটি দেখুন। বু স্ট্যাটিচ্যালি টাইপড, অবজেক্ট-ওরিয়েন্টেড, এবং ওপেন সোর্স, তাই প্রতিটি এএসটি নোডের একটি সু-সংজ্ঞায়িত কাঠামোর একটি টাইপ থাকে যা ম্যাক্রো বিকাশকারী কোডটি পড়তে পারে। ভাষার পাইথন দ্বারা অনুপ্রাণিত একটি অপেক্ষাকৃত সরল বাক্য গঠন রয়েছে যা বিভিন্ন কীওয়ার্ড দিয়ে তৈরি করা হয়েছে যা তাদের থেকে নির্মিত গাছের কাঠামোগুলিকে স্বতন্ত্র অর্থ দেয় এবং এর রূপকোষে নতুন এএসটি নোডগুলি তৈরির সহজতর করার জন্য একটি স্বজ্ঞাত কোয়াসিকোট সিনট্যাক্স রয়েছে।

গতকাল আমি এখানে একটি ম্যাক্রো তৈরি করেছি যখন আমি বুঝতে পেরেছিলাম যে আমি জিইউআই কোডের বিভিন্ন জায়গাগুলিতে একই প্যাটার্নটি প্রয়োগ করছি, যেখানে আমি BeginUpdate()কোনও ইউআই নিয়ন্ত্রণে ফোন করব, একটি tryব্লকে একটি আপডেট করব এবং তারপরে কল করুন EndUpdate():

macro UIUpdate(value as Expression):
    return [|
        $value.BeginUpdate()
        try:
            $(UIUpdate.Body)
        ensure:
            $value.EndUpdate()
    |]

macroকমান্ড, আসলে, হয় একটি ম্যাক্রো নিজেই , এক যে ইনপুট হিসাবে একটি ম্যাক্রো শরীর নেয় এবং ম্যাক্রো প্রক্রিয়া করতে একটি বর্গ জেনারেট করে। এটি ম্যাক্রোর নামটি একটি চলক হিসাবে ব্যবহার করে যা MacroStatementএএসটি নোডের জন্য দাঁড়িয়ে থাকে যা ম্যাক্রো আহ্বানের প্রতিনিধিত্ব করে। দি [| ... |] একটি কোয়াসিকোট ব্লক, এটিএসটি তৈরি করে যা কোডের সাথে মিলে যায় এবং কোয়াসিকোট ব্লকের অভ্যন্তরে, $ চিহ্নটি "নকল" সুবিধা প্রদান করে, যেমন একটি নোডকে নির্দিষ্ট করে রাখা হয়।

এটি দিয়ে এটি লেখা সম্ভব:

UIUpdate myComboBox:
   LoadDataInto(myComboBox)
   myComboBox.SelectedIndex = 0

এবং এটিতে প্রসারিত করুন:

myComboBox.BeginUpdate()
try:
   LoadDataInto(myComboBox)
   myComboBox.SelectedIndex = 0
ensure:
   myComboBox.EndUpdate()

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

হাস্কেল, পাইথন, জাভা, স্কালা ইত্যাদিতে ম্যাক্রো গ্রাফটিং করা কঠিন নয় কারণ এই ভাষাগুলি হোমোকোনিক নয়; এটি কঠিন কারণ ভাষাগুলি তাদের জন্য ডিজাইন করা হয়নি এবং এটি যখন আপনার ভাষার এএসটি হায়ারার্কি স্থল থেকে ম্যাক্রো সিস্টেমের দ্বারা পরীক্ষা করা ও ম্যানিপুলেট করার জন্য তৈরি করা হয় তখন এটি সর্বোত্তম কাজ করে। আপনি যখন প্রথম থেকেই মেটাপগ্রোমিংয়ের সাথে ডিজাইন করা একটি ভাষা নিয়ে কাজ করছেন, তখন ম্যাক্রোগুলি আরও সহজ এবং এর সাথে কাজ করা সহজ!


4
পড়তে আনন্দ, ধন্যবাদ! নন-লিস্প ম্যাক্রোগুলি সিনট্যাক্স পরিবর্তন করার মতো প্রসারিত? কারণ লিস্পের অন্যতম শক্তি বাক্য গঠন সমস্ত একই, সুতরাং এটি কোনও ফাংশন, শর্তাধীন বিবৃতি যোগ করা সহজ, কারণ তারা সমস্ত একই। অ-লিস্প ভাষার সাথে একটি জিনিস অন্যর থেকে পৃথক হয় -if... উদাহরণস্বরূপ কোনও ফাংশন কলের মতো লাগে না। আমি বুকে জানি না, তবে কল্পনা করুন যে বু এর সাথে প্যাটার্ন মিল ছিল না, আপনি কি এটিকে ম্যাক্রো হিসাবে নিজস্ব সিনট্যাক্সের সাথে পরিচয় করিয়ে দিতে পারেন? আমার বক্তব্যটি হল - লিস্পে যে কোনও নতুন ম্যাক্রো 100% প্রাকৃতিক অনুভব করে, অন্য ভাষাগুলিতে তারা কাজ করে তবে আপনি সেলাইগুলি দেখতে পারেন can
গ্রীনল্ডম্যান

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

5
"সহজ এবং আরও স্বজ্ঞাত": দুঃখিত, তবে কীভাবে তা আমি দেখছি না। "আপডেটিং.আরগমেন্টস [0]" অর্থবহ নয় , বরং আমি একটি যুক্তিযুক্ত যুক্তি দিয়েছিলাম এবং সংকলকটি তর্ক করার সংখ্যাটি মেলে কিনা তা নিজেই পরীক্ষা করতে দেই: পেস্টবিন.
coredump

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

5
দুর্ভাগ্যক্রমে আপনার উদাহরণ এটি দেখায় না। ম্যাক্রোগুলির সাথে কোনও লিস্পে এটি প্রয়োগ করা আদিম। আসলে এটি বাস্তবায়নের ক্ষেত্রে অন্যতম আদিম ম্যাক্রো। এটি আমাকে সন্দেহ করে তোলে যে আপনি লিস্পে ম্যাক্রোগুলি সম্পর্কে খুব বেশি জানেন না। "লিস্পের বাক্য গঠনটি ১৯60০ এর দশকে আটকে আছে": লিস্পে ম্যাক্রো সিস্টেমগুলি ১৯60০ সাল থেকে প্রচুর অগ্রগতি করেছে (১৯ 19০ সালে লিস্পে ম্যাক্রোও ছিল না!)।
রেনার জোসভিগ

3

আমি এসআইসিপি থেকে স্কিম শিখছি এবং আমি এই ধারণাটি পেয়ে যাচ্ছি যে স্কিমটি কী করে তার একটি বড় অংশ এবং আরও বেশি, এলআইএসপি বিশেষত ম্যাক্রো সিস্টেম।

কেমন করে? এসআইসপিতে সমস্ত কোড ম্যাক্রো-ফ্রি স্টাইলে লেখা হয়। এসআইসিপিতে কোনও ম্যাক্রো নেই। কেবলমাত্র 373 পৃষ্ঠার পাদটীকাতে ম্যাক্রোগুলির উল্লেখ রয়েছে।

তবে, যেহেতু ম্যাক্রোগুলি সংকলন সময়ে প্রসারিত

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

আসুন পরীক্ষা করি যে এসবিসিএল ব্যবহার করে, একটি সাধারণ লিস্প বাস্তবায়ন।

এসবিসিএলকে দোভাষীর বদলে নেওয়া যাক:

* (setf sb-ext:*evaluator-mode* :interpret)

:INTERPRET

এখন আমরা একটি ম্যাক্রো সংজ্ঞায়িত করি। কোডটি প্রসারিত করার জন্য ডাকলে ম্যাক্রো কিছু প্রিন্ট করে। উত্পন্ন কোড মুদ্রণ করে না।

* (defmacro my-and (a b)
    (print "macro my-and used")
    `(if ,a
         (if ,b t nil)
         nil))

এখন ম্যাক্রো ব্যবহার করা যাক:

MY-AND
* (defun foo (a b) (my-and a b))

FOO

দেখুন। উপরের ক্ষেত্রে লিস্প কিছুই করে না। সংজ্ঞা সময়ে ম্যাক্রো প্রসারিত হয় না।

* (foo t nil)

"macro my-and used"
NIL

কিন্তু রানটাইমে, কোডটি ব্যবহার করা হলে ম্যাক্রো প্রসারিত হয়।

* (foo t t)

"macro my-and used"
T

আবার রানটাইমে, কোডটি ব্যবহার করা হলে ম্যাক্রো প্রসারিত হয়।

নোট করুন যে এসপিসিএল কেবল একবার সংকলক ব্যবহার করার সময় প্রসারিত হবে। তবে বিভিন্ন লিস্প প্রয়োগগুলি এসবিসিএল-এর মতো দোভাষীও সরবরাহ করে।

লিস্পে ম্যাক্রোগুলি কেন সহজ? ঠিক আছে, এগুলি আসলে সহজ নয়। কেবল লিস্পসে, এবং এমন অনেকগুলি রয়েছে যার ম্যাক্রো সমর্থন অন্তর্নির্মিত রয়েছে many তবে ম্যাক্রো প্রক্রিয়াগুলি অত্যন্ত জটিল হতে পারে।


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

@ রেনজি রেইনারের বক্তব্য, আমি বিশ্বাস করি যে আপনি evalবা loadকোনও লিস্প ভাষায় কোড দিলে সেগুলির ম্যাক্রোগুলিও প্রক্রিয়াভুক্ত হবে। যদিও আপনি যদি আপনার প্রশ্নে প্রস্তাবিত প্রিপ্রসেসর সিস্টেম ব্যবহার evalকরেন এবং ম্যাক্রো সম্প্রসারণের মাধ্যমে এই পছন্দটি উপকৃত হবে না।
ক্রিস জেস্টার-ইয়ং

@ রেনজিও এছাড়াও, "পার্স" readলিস্পে ডাকা হয়। এই পার্থক্যটি গুরুত্বপূর্ণ, কারণ evalপাঠ্য ফর্মে নয়, প্রকৃত তালিকার ডেটা স্ট্রাকচারগুলিতে (আমার উত্তরে উল্লিখিত) কাজ করে। সুতরাং আপনি (eval '(+ 1 1))2 ব্যবহার করতে পারেন এবং ফিরে পেতে পারেন তবে আপনি যদি হন তবে আপনি (স্ট্রিং) (eval "(+ 1 1)")ফিরে পাবেন "(+ 1 1)"। আপনি (7 টি অক্ষরের একটি স্ট্রিং) থেকে (একটি প্রতীক এবং দুটি ফিক্সনাম সহ একটি তালিকা ) readপেতে ব্যবহার করুন । "(+ 1 1)"(+ 1 1)
ক্রিস জেস্টার-ইয়ং

@ রেনজি এই বোঝার সাথে ম্যাক্রোগুলি সময়ে কাজ করে না read। তারা সংকলন-সময়ে এই অর্থে কাজ করে যে আপনার কোডটি যদি থাকে তবে কোডটি লোড হয়ে গেলে, একবারে কোডটি চালিত হওয়ার পরে এটি একবারে (স্কিমে) (and (test1) (test2))বিস্তৃত হবে (if (test1) (test2) #f), তবে আপনি যদি কিছু করেন তবে (eval '(and (test1) (test2))), যা রানটাইমে, সেই অভিব্যক্তিটি যথাযথভাবে সংকলন করবে (এবং ম্যাক্রো-প্রসারিত)।
ক্রিস জেস্টার-ইয়ং

@ রেনজি হোমোসোনিসিটি হ'ল লিস্প ভাষাগুলি পাঠ্য ফর্মের পরিবর্তে তালিকার কাঠামোগুলিতে প্রদর্শিত হতে পারে এবং সেই তালিকা কাঠামোগুলি কার্যকর করার পূর্বে (ম্যাক্রোর মাধ্যমে) রূপান্তরিত হতে পারে। বেশিরভাগ ভাষার ভাষাগুলি evalকেবল পাঠ্য স্ট্রিংগুলিতেই কাজ করে এবং সিনট্যাক্স পরিবর্তনের জন্য তাদের ক্ষমতাগুলি অনেক বেশি অনুন্নত এবং / বা জটিল।
ক্রিস জেস্টার-ইয়ং

1

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

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

অ-হোমসাইকোনসিটি বাদ দিয়ে সিনট্যাক্স ম্যাক্রো ব্যবহারের বৃহত্তম সমস্যাটি হ'ল ইচ্ছামত উত্পন্ন সিনট্যাক্সের বিষয়টি। তারা প্রচুর নমনীয়তা এবং শক্তি সরবরাহ করে কিন্তু সেই মূল্যে যে আপনার উত্স কোডটি আর বুঝতে বা বজায় রাখা তত সহজ হতে পারে না।

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