সংক্ষিপ্ত উত্তর:
উদ্ধৃতি অপারেটর এমন একটি অপারেটর যা এটির অপারেন্ডে ক্লোজার সিঁটমিককে প্ররোচিত করে । ধ্রুবকগুলি কেবল মান।
কোট এবং ধ্রুবক বিভিন্ন আছে অর্থ এবং সেইজন্য আছে একটি অভিব্যক্তি গাছ বিভিন্ন উপস্থাপনা । দুটি খুব আলাদা জিনিসের জন্য একই উপস্থাপনা থাকা অত্যন্ত বিভ্রান্তিকর এবং বাগ প্রবণ।
দীর্ঘ উত্তর:
নিম্নোক্ত বিবেচনা কর:
(int s)=>(int t)=>s+t
বাইরের ল্যাম্বডা হ'ল সংযোজনকারীদের জন্য একটি কারখানা যা বাইরের ল্যাম্বদার প্যারামিটারের সাথে আবদ্ধ।
এখন, ধরুন আমরা এটিকে একটি এক্সপ্রেশন ট্রি হিসাবে উপস্থাপন করতে চাই যা পরে সংকলন এবং সম্পাদন হবে। এক্সপ্রেশন গাছের দেহটি কী হওয়া উচিত? আপনি সংকলিত রাষ্ট্রটি কোনও প্রতিনিধি বা কোনও এক্সপ্রেশন ট্রি ফিরিয়ে দিতে চান তা নির্ভর করে।
আসুন উদ্বেগজনক মামলাটি খারিজ করে শুরু করি। যদি আমরা এটির কোনও প্রতিনিধিকে ফিরিয়ে দিতে চাই তবে কোট বা কনস্ট্যান্ট ব্যবহার করবেন কিনা তা প্রশ্ন একটি মূল বিষয়:
var ps = Expression.Parameter(typeof(int), "s");
var pt = Expression.Parameter(typeof(int), "t");
var ex1 = Expression.Lambda(
Expression.Lambda(
Expression.Add(ps, pt),
pt),
ps);
var f1a = (Func<int, Func<int, int>>) ex1.Compile();
var f1b = f1a(100);
Console.WriteLine(f1b(123));
ল্যাম্বডায় একটি নেস্টেড ল্যাম্বদা রয়েছে; সংকলক বাহ্য ল্যাম্বদার জন্য উত্পন্ন ফাংশনটির রাজ্যের উপর বন্ধ হয়ে একটি ফাংশনের প্রতিনিধি হিসাবে অভ্যন্তরীণ ল্যাম্বদা উত্পন্ন করে। আমাদের আর এই মামলা বিবেচনা করা উচিত।
মনে করুন আমরা সংকলিত রাষ্ট্রটি অভ্যন্তরের কোনও এক্সপ্রেশন ট্রি ফিরিয়ে দিতে চাই wish এটি করার দুটি উপায় রয়েছে: সহজ উপায় এবং শক্ত উপায়।
কঠিন উপায় পরিবর্তে যে বলা হয়
(int s)=>(int t)=>s+t
আমরা আসলে যা বোঝাতে চাইছি তা হ'ল
(int s)=>Expression.Lambda(Expression.Add(...
এবং তারপর জন্য অভিব্যক্তি গাছ উৎপন্ন যে , উত্পাদক এই জগাখিচুড়ি :
Expression.Lambda(
Expression.Call(typeof(Expression).GetMethod("Lambda", ...
ব্লা ব্লা ব্লা, লাম্বদা তৈরি করতে কয়েক ডজন লাইনের প্রতিচ্ছবি কোড। উদ্ধৃতি অপারেটরের উদ্দেশ্যটি হ'ল এক্সপ্রেশন ট্রি সংকলককে জানিয়ে দিন যে আমরা চাই যে প্রদত্ত ল্যাম্বদা স্পষ্টভাবে এক্সপ্রেশন ট্রি জেনারেশন কোড উত্পন্ন না করে কোনও ফাংশন হিসাবে নয়, একটি এক্সপ্রেশন ট্রি হিসাবে বিবেচিত হবে ।
সহজ উপায়:
var ex2 = Expression.Lambda(
Expression.Quote(
Expression.Lambda(
Expression.Add(ps, pt),
pt)),
ps);
var f2a = (Func<int, Expression<Func<int, int>>>)ex2.Compile();
var f2b = f2a(200).Compile();
Console.WriteLine(f2b(123));
এবং প্রকৃতপক্ষে, আপনি যদি এই কোডটি সংকলন করেন এবং চালনা করেন তবে সঠিক উত্তর পাবেন।
লক্ষ্য করুন যে উদ্ধৃতি অপারেটর হ'ল অপারেটর যা অভ্যন্তরীণ ল্যাম্বডায় ক্লোজার শব্দার্থকে প্ররোচিত করে যা একটি বাহ্যিক ভেরিয়েবল ব্যবহার করে, বহিরাগত ল্যাম্বদার একটি আনুষ্ঠানিক প্যারামিটার।
প্রশ্নটি হ'ল: কেন উক্তিটি মুছে ফেলা হচ্ছে না এবং এটিকে একই জিনিস করতে হবে না?
var ex3 = Expression.Lambda(
Expression.Constant(
Expression.Lambda(
Expression.Add(ps, pt),
pt)),
ps);
var f3a = (Func<int, Expression<Func<int, int>>>)ex3.Compile();
var f3b = f3a(300).Compile();
Console.WriteLine(f3b(123));
ধ্রুবক ক্লোজার শব্দার্থবিজ্ঞান প্ররোচিত করে না। এটা কেন করা উচিত? আপনি বলেছিলেন যে এটি একটি ধ্রুবক ছিল । এটি কেবল একটি মান। এটি সংকলকের হাতে যেমন নিখুঁত হওয়া উচিত; সংকলকটি যেখানে প্রয়োজন সেখানে স্ট্যাকের জন্য সেই মানটির একটি ডাম্প তৈরি করতে সক্ষম হবে।
যেহেতু কোনও বন্ধ হওয়ার প্ররোচিত নেই, আপনি যদি এটি করেন তবে আপনি "সিস্টেমের মতো একটি ভেরিয়েবল 'এর' পাবেন nt
(একদিকে: আমি উদ্ধৃত অভিব্যক্তি গাছগুলি থেকে ডেলিগেট তৈরির জন্য কোড জেনারেটরটি কেবল পর্যালোচনা করেছি এবং দুর্ভাগ্যক্রমে 2006 এ কোডটি আমি কোডটিতে রেখেছিলাম এমন একটি মন্তব্য এখনও রয়েছে F FYI, উদ্ধৃত বাইরের প্যারামিটারটি একটি ধ্রুবক হিসাবে স্ন্যাপশট করা হয় যখন উদ্ধৃত হয়েছে) রানটাইম সংকলক দ্বারা এক্সপ্রেশন ট্রি একটি প্রতিনিধি হিসাবে পুনরায় সংশোধন করা হয়েছে I আমি কোডটি কেন লিখলাম তার সঠিক কারণ ছিল যা আমি এই মুহুর্তে স্মরণ করি না, তবে এটির বাইরের পরামিতিগুলির মানগুলি বন্ধ করার প্রকারের বাজে পার্শ্ব প্রতিক্রিয়া রয়েছে পরিবর্তে ভেরিয়েবল ওভার বন্ধ। স্পষ্টতই যে দলটি কোডটি উত্তরাধিকারসূত্রে পেয়েছে তারা সেই ত্রুটিটি স্থির করার সিদ্ধান্ত নিয়েছে, সুতরাং আপনি যদি একটি সংকলিত উদ্ধৃত অভ্যন্তরীণ ল্যাম্বডায় কোনও ক্লোজড ওভার বাইরের প্যারামিটারের পরিবর্তনের উপর নির্ভর করছেন তবে আপনি হতাশ হবেন। তবে, যেহেতু এটি উভয়ের কাছেই খুব খারাপ প্রোগ্রামিং অনুশীলন (1) একটি ফর্মাল প্যারামিটারটি পরিবর্তন করে এবং (2) বাইরের ভেরিয়েবলের পরিবর্তনের উপর নির্ভর করে, তাই আমি আপনাকে সুপারিশ করব যে আপনি আপনার প্রোগ্রামটি এই দুটি খারাপ প্রোগ্রামিং অনুশীলনটি ব্যবহার না করে পরিবর্তিত করুন একটি স্থির জন্য অপেক্ষা করা যা আগত বলে মনে হচ্ছে না। ত্রুটির জন্য দুঃখিত।)
সুতরাং, প্রশ্নের পুনরাবৃত্তি:
সি # সংকলকটি এক্সপ্রেশন.কোট () এর পরিবর্তে এক্সপ্রেশন.কনস্ট্যান্ট () এবং কোনও লিনকিউ ক্যোয়ারী সরবরাহকারী যা অন্য কোনও ক্যোয়ারী ভাষায় (যেমন এসকিউএল হিসাবে এক্সপ্রেশন ট্রি প্রক্রিয়াকরণ করতে চায়) জড়িত একটি এক্সপ্রেশন ট্রিতে নেস্টেড ল্যাম্বডা এক্সপ্রেশনগুলি সংকলন করতে পারত ( ) বিশেষ কোট নোড প্রকারের সাথে একটি UnaryExpression এর পরিবর্তে এক্সপ্রেসনের ধরণের কনস্ট্যান্টএক্সপ্রেসনের সন্ধান করতে পারে এবং অন্য সমস্ত কিছুই একই রকম হবে।
আপনি সঠিক. পতাকা হিসাবে ধ্রুবক অভিব্যক্তির ধরণটি ব্যবহার করে আমরা শব্দার্থক তথ্যগুলি এনকোড করতে পারি যার অর্থ "এই মানটির উপর ক্লোজার শব্দার্থকে প্ররোচিত করুন" ।
"ধ্রুবক" এর অর্থ তখন "এই ধ্রুবক মানটি ব্যবহার করুন, যদি না টাইপটি একটি এক্সপ্রেশন গাছের ধরণের হয়ে থাকে এবং মানটি একটি বৈধ এক্সপ্রেশন ট্রি হয়, সেক্ষেত্রে পরিবর্তিত পুনরায় লেখার ফলে অভিব্যক্তি গাছের মানটি ব্যবহার করুন প্রদত্ত অভিব্যক্তি গাছের অভ্যন্তরটি কোনও বহিরাগত ল্যাম্বডাসের প্রসঙ্গে যে ক্লোজার শব্দার্থকে প্ররোচিত করতে পারে যা আমরা এখনই থাকতে পারি।
কিন্তু কেন হবে আমরা যে পাগল জিনিস কি? উদ্ধৃতি অপারেটর একটি অত্যন্ত জটিল অপারেটর এবং আপনি যদি এটি ব্যবহার করতে যাচ্ছেন তবে স্পষ্টভাবে এটি ব্যবহার করা উচিত। আপনি পরামর্শ দিচ্ছেন যে ইতিমধ্যে সেখানে উপস্থিত কয়েক ডজনের মধ্যে একটি অতিরিক্ত কারখানা পদ্ধতি এবং নোড টাইপ না করার বিষয়ে পার্সোনমোনস হওয়ার জন্য, আমরা কনস্ট্যান্টগুলিতে একটি উদ্ভট কোণটির সংযোজন করি, যাতে ধ্রুবকগুলি কখনও কখনও যুক্তিযুক্তভাবে ধ্রুবক হয় এবং কখনও কখনও সেগুলি আবার লেখা হয় are বন্ধ শব্দার্থক সঙ্গে ল্যাম্বডাস।
এটি কিছুটা বিজোড় প্রভাব ফেলবে যা ধ্রুবকটির অর্থ "এই মানটি ব্যবহার করুন" না। ধরুন কিছু উদ্ভট কারণে আপনি উপরের তৃতীয় কেসটি একটি ডেলিগেটের মধ্যে একটি এক্সপ্রেশন ট্রি সংকলন করতে চেয়েছিলেন যা একটি বহিরাগত ভেরিয়েবলের কাছে পুনর্লিখনের উল্লেখ নেই এমন একটি এক্সপ্রেশন ট্রি রাখে? কেন? সম্ভবত আপনি নিজের সংকলকটি পরীক্ষা করছেন এবং কেবলমাত্র ধ্রুবকটি পেরিয়ে যেতে চান যাতে আপনি এটির পরে আরও কিছু বিশ্লেষণ করতে পারেন। আপনার প্রস্তাব যে অসম্ভব করে তোলে; অভিব্যক্তি গাছের ধরণের হতে পারে এমন যে কোনও ধ্রুবক নির্বিশেষে আবার লিখিত হবে। একটির কাছে যুক্তিযুক্ত প্রত্যাশা থাকে যে "ধ্রুবক" অর্থ "এই মানটি ব্যবহার করুন"। "কনস্ট্যান্ট" হ'ল "আমি যা বলি তা করুন" নোড। ধ্রুবক প্রসেসর ' টাইপ উপর ভিত্তি করে বলতে।
এবং অবশ্যই যে এখন আপনি বুঝতে বোঝা নির্বাণ করছে নোট (যে ধ্রুব বুঝতে শব্দার্থবিদ্যা মানে এক ক্ষেত্রে "ধ্রুবক" এবং একটি পতাকা উপর ভিত্তি "অবসান শব্দার্থবিদ্যা রাজি করানো" জটিল হয়েছে যে টাইপ সিস্টেমের মধ্যে উপর) যে সরবরাহকারী যা কেবলমাত্র মাইক্রোসফ্ট সরবরাহকারীদের উপর নয়, একটি অভিব্যক্তি গাছের অর্থ বিশ্লেষণ করে। এই তৃতীয় পক্ষের সরবরাহকারীদের মধ্যে কতজন এটি ভুল হয়ে যাবে?
"উদ্ধৃতি" একটি বড় লাল পতাকা বয়ে যাচ্ছে যা বলে যে "আরে বন্ধু, এখানে দেখুন, আমি একটি নেস্টেড ল্যাম্বডা এক্সপ্রেশন এবং যদি আমি কোনও বাইরের ভেরিয়েবলের উপর বন্ধ হয়ে থাকি তবে আমার গায়ে বেমানান শব্দার্থ থাকে!" যদিও "কনস্ট্যান্ট" বলছে "আমি মান ব্যতীত আর কিছুই না; তুমি যেমন উপযুক্ত ঠিক তেমন ব্যবহার কর" যখন কোনও কিছু জটিল এবং বিপজ্জনক হয় তখন আমরা এটিকে লাল পতাকা বানাতে চাই, ব্যবহারকারীটি এই মানটি বিশেষ কিনা তা সন্ধান করার জন্য টাইপ সিস্টেমের মাধ্যমে খোঁড়াখুঁটি করে না fact
তদুপরি, অপ্রয়োজনীয়তা এড়ানো এমনকি একটি লক্ষ্যও ধারণা ভুল। অবশ্যই, অপ্রয়োজনীয়, বিভ্রান্তিকর অপ্রয়োজনীয়তা এড়ানো একটি লক্ষ্য, তবে সর্বাধিক অপ্রয়োজনীয়তা একটি ভাল জিনিস; অপ্রয়োজনীয়তা স্পষ্টতা তৈরি করে। নতুন কারখানা পদ্ধতি এবং নোড প্রকারঃ সস্তা । আমরা আমাদের যতটুকু প্রয়োজন তৈরি করতে পারি যাতে প্রত্যেকে একটি করে পরিষ্কারভাবে একটি অপারেশন উপস্থাপন করে। আমাদের "এই ক্ষেত্রটি যদি এই জিনিসটিতে সেট না করা হয় তবে এই ক্ষেত্রে এটির অর্থ অন্য কোনও জিনিস like"