একাধিক ভেরিয়েবলগুলিতে একই মান নির্ধারণ করছেন?


12

কখনও কখনও আমি একাধিক ভেরিয়েবল একই মান সেট করা প্রয়োজন।

পাইথনে, আমি করতে পারি

f_loc1 = f_loc2 = "/foo/bar"

তবে এলিস্পে, আমি লিখছি

(setq f_loc1 "/foo/bar" f_loc2 "/foo/bar")

আমি ভাবছি "/foo/bar"একবার ব্যবহার করে এটি অর্জন করার উপায় আছে কি?


1
হাই, চিল্লার, আপনি কি দয়া করে @ পার্সিয়াসের উত্তরকে গ্রহণযোগ্য হিসাবে বেছে নিতে পারেন? আমার উত্তরটি এমন সমাধান সমাধান করে যা আপনি যা চান তা আপনাকে দেয় তবে আমি যেমন বলেছিলাম এটি "অনুশীলনের ধরণের" যা এই তর্কযুক্ত কৃত্রিম চ্যালেঞ্জকে সমাধান করে তবে অনুশীলনে খুব কার্যকর নয়। তারসুইস তার উত্তরে এই সুস্পষ্ট বিবেচ্যতা প্রদর্শনে অনেক প্রচেষ্টা করেছেন, তাই আমি মনে করি তার উত্তরটি "সঠিক উত্তর" হিসাবে পাওয়ার যোগ্য, তাই সবাই আবার খুশি।
মার্ক কার্পভ

1
আমি যুক্তি দিয়েছি যে একাধিক ভেরিয়েবলগুলিতে একই মান নির্ধারণের প্রয়োজনটি এমন একটি নকশার ত্রুটি নির্দেশ করে যা cover
াকতে

1
যদি চান সেটে @lunaryorn source& targetশুরুতে একই পথে এবং আমি পরিবর্তন করতে পারে targetপরে, কিভাবে তাদের তারপর সেট করতে?
চিল্লারনান্দ

আরও কোড দেখান, তাই আপনার ব্যবহারের ক্ষেত্রে "ভেরিয়েবল" বলতে আপনার অর্থ কী তা আমরা বলতে পারি; যেমন, আপনি কী ধরণের ভেরিয়েবল সেট করার চেষ্টা করছেন। @ জর্ডন বিয়নদোর জবাবের জন্য আমার মন্তব্য দেখুন।
ড্র হয়েছে

উত্তর:


21

setq মানটি ফেরত দেয়, তাই আপনি ঠিক করতে পারেন:

(setq f-loc1 (setq f-loc2 "/foo/bar"))

আপনি যদি এর উপর নির্ভর করতে না চান তবে ব্যবহার করুন:

(setq f-loc1 "/foo/bar" f-loc2 f-loc1)

আমি ব্যক্তিগতভাবে আমি পরবর্তীগুলি এড়াতে এবং পরিবর্তে লিখতে চাই:

(setq f-loc1 "/foo/bar"
      f-loc2 f-loc1)

অথবা এমনকি

(setq f-loc1 "/foo/bar")
(setq f-loc2 f-loc1)

এবং প্রথম পদ্ধতির আমি কেবল বিশেষ পরিস্থিতিতে ব্যবহার করব যেখানে এটি প্রকৃতপক্ষে উদ্দেশ্যকে জোর দেয়, বা বিকল্পটি দ্বিতীয় পদ্ধতির ব্যবহার করতে গেলে বা অন্য কোনও উপায় হয় progn


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


অবশেষে, "যখন এটি setq-everyলস্প এবং আমরা পারি" এর মতো ম্যাক্রো লিখতে প্ররোচিত করা হচ্ছে, আমি তা করার বিরুদ্ধে দৃ strongly়ভাবে সুপারিশ করব। এটি করে আপনি খুব সামান্য লাভ করতে পারেন:

(setq-every value a b)
   vs
(setq a (setq b value))

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

প্রতিবার যখন আপনি তাকান সেই মানসিক ওভারহেডের সাথে আপনি মোকাবিলা setq-everyকরতে পারেন বা আপনি কেবল একটি অতিরিক্ত অতিরিক্ত চরিত্র নিয়ে বেঁচে থাকতে পারেন। (অন্তত সেই ক্ষেত্রে যেখানে আপনাকে কেবল দুটি ভেরিয়েবল সেট করতে হবে, তবে আমি মনে করতে পারি না যে আমাকে একবারে একই মানে দুটির বেশি ভেরিয়েবল সেট করতে হয়েছিল you যদি আপনাকে এটি করতে হয় তবে সম্ভবত অন্য কিছু ভুল আছে আপনার কোড সহ।)

অন্যদিকে আপনি যদি এই ম্যাক্রোটি সম্ভবত অর্ধ ডজন বারের চেয়ে বেশি বেশি ব্যবহার করতে যাচ্ছেন, তবে অতিরিক্ত দিকনির্দেশের পক্ষে এটি মূল্যবান হতে পারে। উদাহরণস্বরূপ আমি লাইব্রেরি --when-letথেকে ম্যাক্রোগুলি ব্যবহার করি dash.el। যাঁরা আমার কোডটিতে প্রথমে এটি উপস্থিত হন তাদের পক্ষে এটি আরও কঠিন হয়ে যায়, তবে বুঝতে অসুবিধাটি পরায়ন করা উপযুক্ত কারণ এটি কেবলমাত্র কয়েকবারের চেয়ে বেশি ব্যবহৃত হয় এবং কমপক্ষে আমার মতে, কোডটি আরও পঠনযোগ্য করে তোলে ।

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


1
আপনি একটি বৈচিত্র্য স্থাপনের পরে setqএটির নতুন মানটি উল্লেখ করতে পারেন, সুতরাং আপনি এই এককথায়ও ব্যবহার করতে পারেন: (setq a 10 b a c a d a e a)যা abcd এবং 10 এ সেট করে
জর্ডন বিওনডো

1
@ জর্ডন বিওনডো, হ্যাঁ, তবে আমি মনে করি ওপি'র লক্ষ্য হ'ল তার কোডে পুনরাবৃত্তি হ্রাস করা :-)
মার্ক কার্পভ

3
ম্যাক্রোর অপব্যবহারের বিরুদ্ধে সতর্কতার জন্য আমি আপনাকে একটি +10 দিতে চাই!
লুনারিওর

সবেমাত্র ম্যাক্রো সেরা অনুশীলন সম্পর্কে একটি অনুসন্ধান তৈরি করেছে। emacs.stackexchange.com / ক্র্যাশনস / 21015 । আশা করি @ টারশিউস এবং অন্যান্যরা দুর্দান্ত উত্তর দেবেন।
ইয়াসুশি শোজি

13

আপনি যা চান তা করার জন্য একটি ম্যাক্রো

বাছাইয়ের অনুশীলন হিসাবে:

(defmacro setq-every (value &rest vars)
  "Set every variable from VARS to value VALUE."
  `(progn ,@(mapcar (lambda (x) (list 'setq x value)) vars)))

এখন এটি চেষ্টা করুন:

(setq-every "/foo/bar" f-loc1 f-loc2)

এটা কিভাবে কাজ করে

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

ম্যাক্রোগুলি কাঁচা কোডে কাজ করে। ম্যাক্রো তাদের আর্গুমেন্টগুলি মূল্যায়িত করে না (কার্যগুলি ভিন্ন)। সুতরাং আমরা এখানে মূল্যহীন valueএবং সংগ্রহ করেছি vars, যা আমাদের ম্যাক্রোর জন্য কেবল প্রতীক are

prognsetqএক মধ্যে বিভিন্ন ফর্ম গ্রুপ । এই জিনিস:

(mapcar (lambda (x) (list 'setq x value)) vars)

কেবলমাত্র setqফর্মের একটি তালিকা তৈরি করে, ওপি'র উদাহরণ ব্যবহার করে এটি হবে:

((setq f-loc1 "/foo/bar") (setq f-loc2 "/foo/bar"))

আপনি দেখুন, ফর্ম ভিতরে backquote ফর্মের এবং একটি কমা দিয়ে পূর্বনির্ধারিত ,। ব্যাককোটিড ফর্মের ভিতরে সমস্ত কিছু সাধারণত হিসাবে উদ্ধৃত হয়, তবে , অস্থায়ীভাবে " টার্ন অন" মূল্যায়ন হয়, সুতরাং পুরোটি ম্যাক্রোএক্সপেনশন mapcarসময়ে মূল্যায়ন করা হয়।

অবশেষে s এর @তালিকা থেকে বাহ্যিক বন্ধনী সরিয়ে দেয় setq, তাই আমরা পাই:

(progn
  (setq f-loc1 "/foo/bar")
  (setq f-loc2 "/foo/bar"))

ম্যাক্রোস নির্বিচারে আপনার উত্স কোডটি রূপান্তর করতে পারে, এটি দুর্দান্ত না?

একটি সতর্কীকরণ

এখানে একটি ছোট সতর্কতা, প্রথম যুক্তিটি কয়েকবার মূল্যায়ন করা হবে, কারণ এই ম্যাক্রো মূলত নিম্নলিখিতটিতে প্রসারিত:

(progn
  (setq f-loc1 "/foo/bar")
  (setq f-loc2 "/foo/bar"))

আপনি দেখতে পাচ্ছেন, এখানে যদি আপনার কোনও ভেরিয়েবল বা স্ট্রিং থাকে তবে তা ঠিক আছে, তবে আপনি যদি এই জাতীয় কিছু লিখে থাকেন:

(setq-every (my-function-with-side-effects) f-loc1 f-loc2)

তারপরে আপনার ফাংশনটি একাধিকবার কল করা হবে। এটি অনাকাঙ্ক্ষিত হতে পারে। once-only( এমএমটি প্যাকেজে উপলব্ধ ) এর সাহায্যে এটি কীভাবে ঠিক করা যায় তা এখানে :

(defmacro setq-every (value &rest vars)
  "Set every variable from VARS to value VALUE.

VALUE is only evaluated once."
  (mmt-once-only (value)
    `(progn ,@(mapcar (lambda (x) (list 'setq x value)) vars))))

আর সমস্যাটা চলে গেছে।


1
এটি কীভাবে কাজ করে এবং এই কোডটি আরও বিশদে কী করছে তার কিছু ব্যাখ্যা যুক্ত করতে পারলে চমৎকার হবে, তাই পরের বারের লোকেরা নিজের মতো করে কিছু লিখতে পারে :)
ক্লেমেরা

আপনি valueম্যাক্রো-সম্প্রসারণের সময় মূল্যায়ন করতে চান না ।
তারসিয়াস

@ তারসিউস, আমি না: (macroexpand '(setq-every user-emacs-directory f-loc1 f-loc2))-> (progn (setq f-loc1 user-emacs-directory) (setq f-loc2 user-emacs-directory))। যদি valueম্যাক্রোএক্সপেনশন সময়ে মূল্যায়ন করা হয় তবে এটি প্রকৃত স্ট্রিংয়ের সাথে প্রতিস্থাপিত হবে। আপনি পার্শ্ব প্রতিক্রিয়া সহ ফাংশন কল রাখতে পারেন, স্থানে value, প্রসারিত কোড চালানো না হওয়া পর্যন্ত এটির মূল্যায়ন করা হবে না, চেষ্টা করে দেখুন। valueম্যাক্রোর যুক্তি স্বয়ংক্রিয়ভাবে মূল্যায়ন করা হয় নি। আসল বিষয়টি হ'ল এটি valueবেশ কয়েকবার মূল্যায়ন করা হবে যা অনাকাঙ্ক্ষিত once-onlyহতে পারে, এখানে সহায়তা করতে পারে।
মার্ক কার্পভ

1
পরিবর্তে mmt-once-only(যার জন্য একটি বাহ্যিক ডিপ প্রয়োজন), আপনি ব্যবহার করতে পারেন macroexp-let2
ইয়ংফ্রাগ

2
বিতৃষ্ণা। প্রশ্নটি ম্যাক্রোতে setমোড়ানোর জন্য নয়, এর সাথে পুনরাবৃত্তিটি ব্যবহার করে setq। অথবা কেবল setqবার্তাগুলির পুনরাবৃত্তি সহ একাধিক আরগস ব্যবহার করুন ।
ড্রিউ

7

যেহেতু আপনি লিস্পে চিহ্নগুলি ব্যবহার ও পরিচালনা করতে পারেন, তাই আপনি কেবলমাত্র চিহ্ন এবং ব্যবহারের তালিকাটি লুপ করতে পারেন set

(dolist (var '(foo bar baz)) (set var 10))

(mapc (lambda (var) (set var 10)) '(foo bar baz))

(loop for var in '(foo bar baz) do (set var 11))

(--each '(foo bar baz) (set it 10))


@ এনপোস্টাভস: সত্য, তবে এটি ওপি যা চায় / প্রয়োজন তা হতে পারে। যদি সে লেসিকাল ভেরিয়েবল ব্যবহার না করে তবে অবশ্যই এটি যাওয়ার উপায়। আপনি ঠিক বলেছেন, যদিও "পরিবর্তনশীল" অস্পষ্ট, সুতরাং সাধারণভাবে প্রশ্নটির অর্থ কোনও ধরণের পরিবর্তনশীল হতে পারে। প্রকৃত ব্যবহারের কেসটি ভালভাবে উপস্থাপন করা হয়নি, আইএমও।
ড্র হয়েছে
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.