কমপেজ রুটের পিছনে "বড় ধারণা" কী?


109

আমি ক্লোজুরে নতুন এবং একটি বেসিক ওয়েব অ্যাপ্লিকেশন লেখার জন্য কমপেজ ব্যবহার করছি। আমি কমপোজোর defroutesসিনট্যাক্স দিয়ে একটি প্রাচীরের উপর আঘাত করছি , যদিও আমি মনে করি এবং এর পিছনে "কীভাবে" এবং "কেন" উভয়ই বুঝতে হবে।

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

সমস্যাটি হ'ল আমি কমপোজোরের পদ্ধতিকে বুঝতে পারি না। আসুন নীচের defroutesএস-এক্সপ্রেশনটি গ্রহণ করুন:

(defroutes main-routes
  (GET "/"  [] (workbench))
  (POST "/save" {form-params :form-params} (str form-params))
  (GET "/test" [& more] (str "<pre>" more "</pre>"))
  (GET ["/:filename" :filename #".*"] [filename]
    (response/file-response filename {:root "./static"}))
  (ANY "*"  [] "<h1>Page not found.</h1>"))

আমি জানি যে কিছু ম্যাক্রো ভুডোর মধ্যে এই সমস্ত মিথ্যা বোঝার মূল চাবিকাঠি, তবে আমি ম্যাক্রোগুলি (এখনও) পুরোপুরি বুঝতে পারি না। আমি defroutesউত্সটি দীর্ঘ সময়ের জন্য তাকিয়েছি , তবে কেবল এটি পাই না! এখানে কি হচ্ছে? "বড় ধারণা" বোঝা আমাকে সম্ভবত এই নির্দিষ্ট প্রশ্নের উত্তর দিতে সহায়তা করবে:

  1. কোনও রাউটেড ফাংশন (যেমন workbenchফাংশন) এর মধ্যে থেকে আমি কীভাবে রিং পরিবেশে অ্যাক্সেস করব ? উদাহরণস্বরূপ, বলুন যে আমি HTTP_ACCEPT শিরোনাম বা অনুরোধের / মিডলওয়্যারের অন্য কোনও অংশটি অ্যাক্সেস করতে চেয়েছি?
  2. ধ্বংস ( {form-params :form-params}) এর সাথে কী চুক্তি ? ধ্বংসের সময় আমার জন্য কী কীওয়ার্ড পাওয়া যায়?

আমি সত্যিই ক্লোজুরে পছন্দ করি তবে আমি খুব স্টাম্পড!

উত্তর:


212

সংক্ষিপ্ত বিবরণ (কিছু পরিমাণে)

বিশেষ দ্রষ্টব্য। আমি কমপোজার 0.4.1 এর সাথে কাজ করছি ( এখানে গিটহাবের 0.4.1 রিলিজ কমিট)।

কেন?

একেবারে শীর্ষে compojure/core.clj, কমপোজারের উদ্দেশ্যটির এই সহায়ক সংক্ষিপ্তসারটি রয়েছে:

রিং হ্যান্ডলারগুলি উত্পাদন করার জন্য একটি সংক্ষিপ্ত বাক্য গঠন।

একটি পৃষ্ঠের স্তরে, "কেন" প্রশ্নটিই এখানে রয়েছে। কিছুটা গভীরভাবে যেতে, আসুন এক ঝলক দেখি কীভাবে একটি রিং-স্টাইল অ্যাপ্লিকেশন কাজ করে:

  1. একটি অনুরোধ উপস্থিত হয়েছে এবং রিং অনুমান অনুসারে ক্লোজার ম্যাপে রূপান্তরিত হয়েছে।

  2. এই মানচিত্রটি একটি তথাকথিত "হ্যান্ডলার ফাংশন" হিসাবে সজ্জিত হয়েছে, যা প্রত্যাশা তৈরি করবে বলে আশা করা হচ্ছে (এটি ক্লোজার ম্যাপও)।

  3. প্রতিক্রিয়া মানচিত্র একটি প্রকৃত HTTP প্রতিক্রিয়া রূপান্তরিত এবং ক্লায়েন্ট ফিরে পাঠানো হয়।

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

কিভাবে?

"রুট" ধারণার চারপাশে কমপেজ তৈরি করা হয়েছে। এগুলি আসলে ক্লাউট গ্রন্থাগার দ্বারা গভীর স্তরে প্রয়োগ করা হয়েছে (কমপোজার প্রকল্পের একটি স্পিনফ - 0.3.x -> 0.4.x স্থানান্তরে অনেকগুলি পৃথক গ্রন্থাগারে স্থানান্তরিত করা হয়েছিল)। একটি রুট (1) একটি HTTP পদ্ধতি (জিইটি, পুট, হেড ...) দ্বারা সংজ্ঞায়িত করা হয়েছে, (২) একটি ইউআরআই প্যাটার্ন (সিনট্যাক্সের সাথে নির্দিষ্ট করা হবে যা সম্ভবত ওয়েববি রুবিবাদীদের সাথে পরিচিত হবে), (3) একটি কাঠামোগত ফর্ম ব্যবহৃত অনুরোধের মানচিত্রের অংশগুলি শরীরে উপলব্ধ নামগুলিতে আবদ্ধ করা (4) এমন একটি ভাবের সংশ্লেষ যা একটি বৈধ রিং প্রতিক্রিয়া তৈরি করতে পারে (অ-তুচ্ছ ক্ষেত্রে এটি সাধারণত একটি পৃথক ফাংশনটির জন্য কেবল একটি কল)।

সাধারণ উদাহরণটি দেখার জন্য এটি ভাল পয়েন্ট হতে পারে:

(def example-route (GET "/" [] "<html>...</html>"))

আসুন এটি আরইপিএলে পরীক্ষা করুন (নীচের অনুরোধের মানচিত্রটি সর্বনিম্ন বৈধ রিংয়ের অনুরোধ মানচিত্রটি):

user> (example-route {:server-port 80
                      :server-name "127.0.0.1"
                      :remote-addr "127.0.0.1"
                      :uri "/"
                      :scheme :http
                      :headers {}
                      :request-method :get})
{:status 200,
 :headers {"Content-Type" "text/html"},
 :body "<html>...</html>"}

তাহলে :request-methodছিল :headপরিবর্তে, প্রতিক্রিয়া হবে nil। আমরা nilএক মিনিটে এখানে কী বোঝাতে চাইছি তার প্রশ্নে ফিরে আসব (তবে লক্ষ্য করুন যে এটি কোনও বৈধ রিং রিসোস নয়!)।

যেমন এই উদাহরণ থেকে স্পষ্ট, example-routeকেবল একটি ফাংশন, এবং এটি একটি খুব সহজ একটি; এটি অনুরোধটির দিকে নজর দেয়, এটি পরিচালনা করতে আগ্রহী কিনা তা নির্ধারণ করে (পরীক্ষা করে :request-methodএবং :uri) এবং যদি তাই হয় তবে একটি প্রাথমিক প্রতিক্রিয়ার মানচিত্র ফেরত দেয়।

যা স্পষ্ট তা হল যে রুটের মূল অংশটি সঠিক প্রতিক্রিয়ার মানচিত্রে মূল্যায়ন করার প্রয়োজন নেই; কমপোজার স্ট্রিংগুলির জন্য বুদ্ধিমান ডিফল্ট হ্যান্ডলিং সরবরাহ করে (উপরে দেখানো হয়েছে) এবং অন্যান্য অবজেক্টের বিভিন্ন ধরণের; দেখতে compojure.response/renderবিস্তারিত জানার জন্য multimethod (কোড সম্পূর্ণভাবে স্বয়ংসম্পূর্ণ দলিল এখানে)।

আসুন defroutesএখন ব্যবহার করার চেষ্টা করুন :

(defroutes example-routes
  (GET "/" [] "get")
  (HEAD "/" [] "head"))

উপরে প্রদর্শিত উদাহরণ অনুরোধের প্রতিক্রিয়া এবং এর বৈকল্পিকের সাথে :request-method :headপ্রত্যাশার মতো।

এর অভ্যন্তরীণ কাজগুলি example-routesএমন যে প্রতিটি রুটের পরিবর্তে চেষ্টা করা হয়; যত তাড়াতাড়ি তাদের মধ্যে একটি nilপ্রতিক্রিয়া ফিরিয়ে দেয় , সেই প্রতিক্রিয়া পুরো example-routesহ্যান্ডলারের রিটার্ন মান হয়ে যায় । একটি অতিরিক্ত সুবিধা হিসাবে, - defroutesসংজ্ঞায়িত হ্যান্ডলারগুলি মোড়ানো wrap-paramsএবং wrap-cookiesঅন্তর্নিহিতভাবে।

আরও জটিল রুটের উদাহরণ এখানে:

(def echo-typed-url-route
  (GET "*" {:keys [scheme server-name server-port uri]}
    (str (name scheme) "://" server-name ":" server-port uri)))

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

উপরের একটি পরীক্ষা:

user> (echo-typed-url-route {:server-port 80
                             :server-name "127.0.0.1"
                             :remote-addr "127.0.0.1"
                             :uri "/foo/bar"
                             :scheme :http
                             :headers {}
                             :request-method :get})
{:status 200,
 :headers {"Content-Type" "text/html"},
 :body "http://127.0.0.1:80/foo/bar"}

উপরের উজ্জ্বল ফলো-আপ ধারণাটি হ'ল আরও জটিল রুটগুলি assocমিলের পর্যায়ে অনুরোধের উপরে অতিরিক্ত তথ্য পেতে পারে:

(def echo-first-path-component-route
  (GET "/:fst/*" [fst] fst))

এই সঙ্গে প্রতিক্রিয়াশীল :bodyএর "foo"পূর্ববর্তী উদাহরণ থেকে অনুরোধ করতে পারি।

দুটি জিনিস এই সর্বশেষ উদাহরণ সম্পর্কে নতুন আছেন: "/:fst/*"এবং অ খালি বাঁধাই ভেক্টর [fst]। প্রথমটি ইউআরআই নিদর্শনগুলির জন্য উল্লিখিত রেলস এবং সিনট্রা জাতীয় সিনট্যাক্স। এটি ইউআরআই বিভাগগুলিতে রিজেক্স সীমাবদ্ধতার উপরোক্ত উদাহরণ থেকে যা দৃশ্যমান তার চেয়ে কিছুটা পরিশীলিত (উদাহরণস্বরূপ উপরের সমস্ত অংকের ["/:fst/*" :fst #"[0-9]+"]মানগুলি রুটটিকে গ্রহণ করার জন্য সরবরাহ করা যেতে পারে :fst)। দ্বিতীয়টি :paramsঅনুরোধ মানচিত্রে প্রবেশের সাথে মিলের সহজতর উপায় , যা নিজেই একটি মানচিত্র; এটি অনুরোধ, ক্যোরি স্ট্রিং প্যারামিটার এবং ফর্ম পরামিতিগুলি থেকে ইউআরআই বিভাগগুলি উত্তোলনের জন্য দরকারী। পরবর্তী দৃষ্টান্তটি বর্ণনা করার জন্য একটি উদাহরণ:

(defroutes echo-params
  (GET "/" [& more]
    (str more)))

user> (echo-params
       {:server-port 80
        :server-name "127.0.0.1"
        :remote-addr "127.0.0.1"
        :uri "/"
        :query-string "foo=1"
        :scheme :http
        :headers {}
        :request-method :get})
{:status 200,
 :headers {"Content-Type" "text/html"},
 :body "{\"foo\" \"1\"}"}

প্রশ্নের পাঠ্য থেকে উদাহরণটি দেখার জন্য এটি ভাল সময় হবে:

(defroutes main-routes
  (GET "/"  [] (workbench))
  (POST "/save" {form-params :form-params} (str form-params))
  (GET "/test" [& more] (str "<pre>" more "</pre>"))
  (GET ["/:filename" :filename #".*"] [filename]
    (response/file-response filename {:root "./static"}))
  (ANY "*"  [] "<h1>Page not found.</h1>"))

আসুন পরিবর্তে প্রতিটি রুট বিশ্লেষণ করুন:

  1. (GET "/" [] (workbench))- যখন কোনও GETঅনুরোধের সাথে ডিল করার সময় :uri "/", ফাংশনটি কল করুন workbenchএবং যা প্রতিক্রিয়া মানচিত্রে ফিরে আসে তা রেন্ডার করুন। (মনে রাখবেন যে ফেরতের মান মানচিত্র হতে পারে তবে একটি স্ট্রিং ইত্যাদিও থাকতে পারে)

  2. (POST "/save" {form-params :form-params} (str form-params))- মিডওয়্যারের :form-paramsদ্বারা সরবরাহিত অনুরোধ মানচিত্রে একটি প্রবেশিকা wrap-params(এটি প্রত্যক্ষভাবে অন্তর্ভুক্ত করা হয়েছে তা প্রত্যাহার করুন defroutes)। প্রতিক্রিয়া মান হতে হবে {:status 200 :headers {"Content-Type" "text/html"} :body ...}সঙ্গে (str form-params)প্রতিস্থাপিত ...। (কিছুটা অস্বাভাবিক POSTহ্যান্ডলার, এটি ...)

  3. (GET "/test" [& more] (str "<pre> more "</pre>"))- এটি উদাহরণস্বরূপ মানচিত্রের স্ট্রিং উপস্থাপনাটিকে প্রতিধ্বনিত করবে {"foo" "1"}যদি ব্যবহারকারী এজেন্ট জিজ্ঞাসা করে "/test?foo=1"

  4. (GET ["/:filename" :filename #".*"] [filename] ...)- :filename #".*"অংশটি কিছুই করে না (যেহেতু #".*"সবসময় মেলে)। এটি ring.util.response/file-responseতার প্রতিক্রিয়া তৈরি করতে রিং ইউটিলিটি ফাংশনটিকে কল করে ; {:root "./static"}অংশ বলা হয়েছে যে সব যেখানে ফাইলের জন্য দেখুন।

  5. (ANY "*" [] ...)- একটি ক্যাচ-অল রুট। নিয়মিতভাবে defroutesসংজ্ঞায়িত হ্যান্ডলারটি একটি বৈধ রিং প্রতিক্রিয়া মানচিত্র ফেরত দেয় তা নিশ্চিত করার জন্য (ফর্মের সাথে ব্যর্থতার ফলস্বরূপ কোনও রুট মিলে যায় nil) তা নিশ্চিত করার জন্য ফর্মের শেষে এই জাতীয় রুট অন্তর্ভুক্ত করা সর্বদা ভাল অনুশীলন অনুশীলন ।

কেন এভাবে?

রিং মিডলওয়্যারের একটি উদ্দেশ্য হল অনুরোধের মানচিত্রে তথ্য যুক্ত করা; এইভাবে কুকি-হ্যান্ডলিং মিডলওয়্যার :cookiesঅনুরোধটিতে একটি কী wrap-paramsযুক্ত করে, :query-paramsএবং যোগ করে এবং / অথবা:form-paramsযদি কোনও কোয়েরি স্ট্রিং / ফর্ম ডেটা উপস্থিত থাকে এবং ততক্ষণ। (কড়া কথায় বলতে গেলে মিডলওয়্যারের ফাংশনগুলি যুক্ত করা সমস্ত তথ্য ইতিমধ্যে অনুরোধের মানচিত্রে উপস্থিত থাকতে হবে, যেহেতু তারা এগুলি পাস হয়; তাদের কাজ হ'ল তাদের মোড়ানো হ্যান্ডলারের সাথে কাজ করা আরও সুবিধাজনক হওয়ার জন্য তাদের কাজটি এটি রূপান্তর করা)) শেষ পর্যন্ত "সমৃদ্ধ" অনুরোধটি বেস হ্যান্ডলারের কাছে প্রেরণ করা হয়েছে, যা মিডওয়্যার দ্বারা যুক্ত সমস্ত প্রিপ্রোসেসড তথ্য সহ অনুরোধের মানচিত্রটি পরীক্ষা করে এবং একটি প্রতিক্রিয়া তৈরি করে। (মিডলওয়্যার এর চেয়ে জটিল জিনিসগুলি করতে পারে - যেমন বেশ কয়েকটি "অভ্যন্তরীণ" হ্যান্ডলার মোড়ানো এবং তাদের মধ্যে বেছে নেওয়া, মোড়ক হ্যান্ডলার (গুলি) কে আদৌ কল করতে হবে কিনা তা সিদ্ধান্ত নেওয়া ইত্যাদি That এটি অবশ্য এই উত্তরের বাইরে নয় outside)

বেস হ্যান্ডলারটি ঘুরে দেখা যায় সাধারণত (অ-তুচ্ছ ঘটনাগুলিতে) এমন একটি ফাংশন যা অনুরোধ সম্পর্কে কেবল কয়েকটি মুষ্টিমেয় আইটেমের প্রয়োজন হয়। (উদাহরণস্বরূপ ring.util.response/file-responseবেশিরভাগ অনুরোধের যত্ন নেই; এটির জন্য কেবল একটি ফাইলের নাম প্রয়োজন)) সুতরাং একটি রিংয়ের অনুরোধের কেবলমাত্র প্রাসঙ্গিক অংশগুলি বের করার একটি সহজ পদ্ধতির প্রয়োজন। কমপোজোর লক্ষ্য ছিল একটি বিশেষ-উদ্দেশ্য প্যাটার্ন মেলানো ইঞ্জিন সরবরাহ করা, যেমনটি ছিল, যা কেবল এটি করে।


3
"একটি অতিরিক্ত সুবিধার্থ হিসাবে, ডিফল্ট-সংজ্ঞায়িত হ্যান্ডলারগুলি মোড়ক-প্যারাম এবং মোড়ক-কুকিগুলিতে অন্তর্ভুক্ত থাকে" " - 0.6.0 সংস্করণ হিসাবে আপনাকে এগুলি স্পষ্টভাবে যুক্ত করতে হবে। রেফ github.com/weavejester/compojure/commit/…
ড্যান মিডউড

3
খুব ভাল লাগানো। এই উত্তরটি কমপোজারের হোমপেজে থাকা উচিত।
সিদ্ধার্থ রেড্ডি

2
কমপোজায় নতুন কারও জন্য প্রয়োজনীয় পাঠ্য। আমি আশা করি বিষয়টির প্রতিটি উইকি এবং ব্লগ পোস্ট এর একটি লিঙ্ক দিয়ে শুরু করা হোক।
জেমমন

7

এ চমৎকার নিবন্ধ নেই booleanknot.com জেমস রিভস থেকে (Compojure লেখক), এবং এটি পড়া এটা আমার জন্য "ক্লিক করুন", তাই আমি এর কিছু এখানে retranscribed কাজ করলাম (সত্যিই যে সব আমি করেছি)।

একই লেখকের এখানে একটি স্লাইডেক রয়েছে , যা এই সঠিক প্রশ্নের উত্তর দেয়।

কমপোজারটি রিংয়ের উপর ভিত্তি করে তৈরি করা হয় , যা HTTP অনুরোধগুলির জন্য একটি বিমূর্ততা।

A concise syntax for generating Ring handlers.

তো, সেই রিং হ্যান্ডলারগুলি কী কী? দস্তাবেজ থেকে নিষ্কাশন:

;; Handlers are functions that define your web application.
;; They take one argument, a map representing a HTTP request,
;; and return a map representing the HTTP response.

;; Let's take a look at an example:

(defn what-is-my-ip [request]
  {:status 200
   :headers {"Content-Type" "text/plain"}
   :body (:remote-addr request)})

বেশ সহজ, তবে বেশ নিম্ন স্তরেরও। উপরের হ্যান্ডলারটি আরও সংক্ষিপ্তভাবে ring/utilগ্রন্থাগারটি ব্যবহার করে সংজ্ঞায়িত করা যেতে পারে ।

(use 'ring.util.response)

(defn handler [request]
  (response "Hello World"))

এখন আমরা অনুরোধের উপর নির্ভর করে বিভিন্ন হ্যান্ডলারদের কল করতে চাই। আমরা এর মতো কিছু স্ট্যাটিক রাউটিং করতে পারি:

(defn handler [request]
  (or
    (if (= (:uri request) "/a") (response "Alpha"))
    (if (= (:uri request) "/b") (response "Beta"))))

এবং এটির মতো রিফ্যাক্টর:

(defn a-route [request]
  (if (= (:uri request) "/a") (response "Alpha")))

(defn b-route [request]
  (if (= (:uri request) "/b") (response "Beta"))))

(defn handler [request]
  (or (a-route request)
      (b-route request)))

জেমস এরপরে আকর্ষণীয় বিষয়টি লক্ষ্য করে যে হ'ল এটি বাসা বাঁধার অনুমতি দেয়, কারণ "দুই বা ততোধিক রুটের একত্রিত হওয়ার ফলাফলটি নিজেই একটি রুট"।

(defn ab-routes [request]
  (or (a-route request)
      (b-route request)))

(defn cd-routes [request]
  (or (c-route request)
      (d-route request)))

(defn handler [request]
  (or (ab-routes request)
      (cd-routes request)))

এতক্ষণে, আমরা এমন কিছু কোড দেখতে শুরু করেছি যা দেখে মনে হচ্ছে ম্যাক্রো ব্যবহার করে এটি ফ্যাক্টরড হতে পারে। সংমিশ্রণ একটি defroutesম্যাক্রো সরবরাহ করে:

(defroutes ab-routes a-route b-route)

;; is identical to

(def ab-routes (routes a-route b-route))

সংমিশ্রণ ম্যাক্রোর মতো অন্যান্য ম্যাক্রোগুলি সরবরাহ করে GET:

(GET "/a" [] "Alpha")

;; will expand to

(fn [request#]
  (if (and (= (:request-method request#) ~http-method)
           (= (:uri request#) ~uri))
    (let [~bindings request#]
      ~@body)))

যে শেষ ফাংশনটি তৈরি হয়েছিল তা আমাদের হ্যান্ডলারের মতো দেখাচ্ছে!

চেক আউট করতে ভুলবেন না দয়া করে জেমস পোস্ট , যেমন আরো বিস্তারিত ব্যাখ্যা মধ্যে যায়।


4

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

আসলে দস্তাবেজগুলিlet পড়ার ফলে পুরো "পরিষ্কার করার জন্য যাদু মানগুলি কোথা থেকে আসে?" প্রশ্ন।

আমি নীচে সম্পর্কিত বিভাগগুলি আটকানো করছি:

ক্লোজুর অ্যাবস্ট্রাক্ট স্ট্রাকচারাল বাইন্ডিং সমর্থন করে, প্রায়শই তাকে ডান্সস্ট্রাকচার বলে, বন্ডিং তালিকাগুলি, fn প্যারামিটার তালিকাগুলি এবং যে কোনও ম্যাক্রো যা একটি লেট বা এফএনএন-এ প্রসারিত হয়। মূল ধারণাটি হ'ল একটি বাইন্ডিং-ফর্মটি এমন একটি ডেটা স্ট্রাকচার আক্ষরিক হতে পারে যা প্রতীকযুক্ত থাকে যা init-expr এর সাথে সম্পর্কিত অংশগুলিতে আবদ্ধ হয়ে যায়। এই বাইন্ডিংটি বিমূর্তরূপে যে কোনও ভেক্টর আক্ষরিক অনুক্রমিক যে কোনও কিছুকে আবদ্ধ করতে পারে, অন্যদিকে মানচিত্রের আক্ষরিকটি যেকোন কিছুকে সংযুক্তিযুক্ত করে তোলে ia

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

(let [[a b c & d :as e] [1 2 3 4 5 6 7]]
  [a b c d e])
->[1 2 3 (4 5 6 7) [1 2 3 4 5 6 7]]

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

(let [[a b c & d :as e] [1 2 3 4 5 6 7]]
  [a b c d e])
->[1 2 3 (4 5 6 7) [1 2 3 4 5 6 7]]

3

আমি ক্লোজার ওয়েব স্টাফগুলিতে এখনও শুরু করি নি তবে আমি করব, এখানে আমার বুকমার্ক করা স্টাফ রয়েছে।


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

1

ডেস্ট্রাকচারিং (the ফর্ম-প্যারাম: ফর্ম-প্যারামস) এর সাথে কী চুক্তি হয়েছে? ধ্বংসের সময় আমার জন্য কী কীওয়ার্ড পাওয়া যায়?

উপলব্ধ কীগুলি হ'ল ইনপুট মানচিত্রে। লেট এবং ডোজাক ফর্মের ভিতরে, বা পরামিতিগুলির ভিতরে এনএফএন বা ডিফএন করার জন্য বিকাশ উপলব্ধ

নিম্নলিখিত কোডটি আশাবাদী তথ্যমূলক হবে:

(let [{a :thing-a
       c :thing-c :as things} {:thing-a 0
                               :thing-b 1
                               :thing-c 2}]
  [a c (keys things)])

=> [0 2 (:thing-b :thing-a :thing-c)]

আরও উন্নত উদাহরণ, নেস্টেড ধ্বংসগুলি দেখানো:

user> (let [{thing-id :id
             {thing-color :color :as props} :properties} {:id 1
                                                          :properties {:shape
                                                                       "square"
                                                                       :color
                                                                       0xffffff}}]
            [thing-id thing-color (keys props)])
=> [1 16777215 (:color :shape)]

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

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