আরপিএলে ক্লোজার ফাইলটি কীভাবে পুনরায় লোড করবেন


170

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

  • সম্পাদন করা src/foo/bar.clj
  • REPL বন্ধ করুন
  • REPL খুলুন
  • (load-file "src/foo/bar.clj")
  • (use 'foo.bar)

এছাড়াও, (use 'foo.bar :reload-all)প্রয়োজনীয় প্রভাবের ফলশ্রুতি দেয় না যা উত্স হিসাবে পরিবর্তন করার পরিবর্তে ফাংশনগুলির পরিবর্তিত সংস্থাগুলির মূল্যায়ন এবং নতুন মানগুলি ফিরিয়ে দিচ্ছে।

ডকুমেন্টেশন:


20
(use 'foo.bar :reload-all)সবসময় আমার জন্য ভাল কাজ করেছে। এছাড়াও, (load-file)আপনার ক্লাসপথটি সঠিকভাবে স্থাপন করা থাকলে কখনই প্রয়োজন হবে না। আপনি "প্রয়োজনীয় প্রভাব" কী পাচ্ছেন না?
ডেভ রায়

হ্যাঁ, "প্রয়োজনীয় প্রভাব" কী? bar.clj"প্রয়োজনীয় প্রভাব" সম্পর্কে বিশদ বিবরণ সহ একটি নমুনা পোস্ট করুন।
শ্রীধর রত্নাকুমার

1
প্রয়োজনীয় প্রভাব দ্বারা আমি বোঝাতে চেয়েছিলাম যে যদি আমার কোনও ফাংশন থাকে (defn f [] 1)এবং আমি এর সংজ্ঞাটি পরিবর্তিত করি তবে আমার কাছে (defn f [] 2)মনে হয়েছিল যে আমি ফাংশনটি ইস্যু করার পরে (use 'foo.bar :reload-all)এবং কল করার পরে fএটি 2 ফিরে আসবে, 1 নয়। দুর্ভাগ্যক্রমে এটি আমার এবং প্রত্যেকের পক্ষে সেভাবে কাজ করে না সময় আমি ফাংশনটির বডি পরিবর্তন করি আমাকে আরপিএল পুনরায় চালু করতে হবে।
pkaleta

আপনার সেটআপে আপনার অবশ্যই অন্য একটি সমস্যা থাকতে হবে ... :reloadবা :reload-allউভয়েরই কাজ করা উচিত।
জেসন

উত্তর:


196

অথবা (use 'your.namespace :reload)


3
:reload-allকাজ করা উচিত। ওপি বিশেষত এটি বলে না, তবে আমি মনে করি ওপি-র পরিবেশ পরিবেশে অন্যরকম কিছু ভুল ছিল কারণ একটি ফাইলের জন্য দুটি ( :reloadএবং :reload-all) একই প্রভাব থাকতে হবে should এর জন্য সম্পূর্ণ কমান্ড এখানে :reload-all: (use 'your.namespace :reload-all) এটি সমস্ত নির্ভরতাও পুনরায় লোড করে।
জেসন

77

সরঞ্জাম.নামস্পেস ব্যবহার করার মতো বিকল্পও রয়েছে , এটি বেশ কার্যকর:

user=> (use '[clojure.tools.namespace.repl :only (refresh)])

user=> (refresh)

:reloading (namespace.app)

:ok

3
এই উত্তরটি আরও সঠিক
বাহাদির ক্যামবেল

12
ক্যাভ্যাট: (refresh)দৌড়াদৌড়িটিও আপনার প্রয়োজনীয় রেফিলিটি ভুলে যাওয়ার কারণ হতে পারে clojure.tools.namespace.repl। পরবর্তী কলগুলি (refresh)আপনাকে একটি রানটাইম এক্সেক্সপশন দেবে, "প্রতীক সমাধান করতে অক্ষম: এই প্রসঙ্গে রিফ্রেশ করুন।" সম্ভবত সবচেয়ে ভাল কাজটি হ'ল হয় (require 'your.namespace :reload-all), বা, যদি আপনি জানেন যে আপনি একটি প্রদত্ত প্রকল্পের জন্য আপনার আরপিএলকে অনেক রিফ্রেশ করতে চান, একটি :devপ্রোফাইল তৈরি করুন এবং এতে যুক্ত [clojure.tools.namespace.repl :refer (refresh refresh-all)]হনdev/user.clj
ডেভ ইয়ারউড

1
টুলস.নেমস্পেসের লেখক দ্বারা ক্লোজার ওয়ার্কফ্লোতে ব্লগপোস্ট: চিন্তাভাবনা
ডেভিড টনহফার

61

ব্যবহার Clojure কোড পুনরায় লোড করা (require … :reload)এবং :reload-allহয় খুব সমস্যাযুক্ত :

  • যদি আপনি দুটি নেমস্পেসগুলি একে অপরের উপর নির্ভর করে পরিবর্তন করেন তবে সংকলন ত্রুটিগুলি এড়াতে আপনাকে অবশ্যই সঠিক ক্রমে পুনরায় লোড করতে হবে remember

  • আপনি যদি কোনও উত্স ফাইল থেকে সংজ্ঞাগুলি সরিয়ে থাকেন এবং তারপরে এটিকে পুনরায় লোড করেন তবে সেই সংজ্ঞাগুলি এখনও মেমরিতে উপলব্ধ। যদি অন্য কোডগুলি সেই সংজ্ঞাগুলির উপর নির্ভর করে তবে এটি কাজ চালিয়ে যাবে তবে পরের বার আপনি JVM পুনরায় চালু করবেন break

  • যদি পুনরায় লোড হওয়া নেমস্পেস থাকে তবে defmultiআপনাকে অবশ্যই সম্পর্কিত সমস্ত defmethodঅভিব্যক্তি পুনরায় লোড করতে হবে ।

  • যদি পুনরায় লোড করা নেমস্পেস থাকে তবে defprotocolআপনাকে অবশ্যই সেই রেকর্ড বা প্রোটোকলটি প্রয়োগকারী প্রকারগুলি পুনরায় লোড করতে হবে এবং সেই রেকর্ড / প্রকারের বিদ্যমান উপস্থিতিগুলিকে নতুন উদাহরণ সহ প্রতিস্থাপন করতে হবে।

  • যদি পুনরায় লোড হওয়া নেমস্পেসে ম্যাক্রোগুলি থাকে তবে আপনাকে অবশ্যই সেই জাতীয় ম্যাক্রোগুলি যে কোনও নেমস্পেসগুলি পুনরায় লোড করতে হবে।

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

Clojure.tools.namespace গ্রন্থাগার পরিস্থিতি উল্লেখযোগ্যভাবে উন্নত করে। এটি একটি সহজ রিফ্রেশ ফাংশন সরবরাহ করে যা নামের স্থানগুলির নির্ভরতা গ্রাফের উপর ভিত্তি করে স্মার্ট পুনরায় লোড করে does

myapp.web=> (require '[clojure.tools.namespace.repl :refer [refresh]])
nil
myapp.web=> (refresh)
:reloading (myapp.web)
:ok

দুর্ভাগ্যক্রমে দ্বিতীয় বার পুনরায় লোড করা যদি আপনি refreshফাংশনটি উল্লেখ করেছেন সেই নেমস্পেসটি পরিবর্তন হয়ে যায়। এটি নতুন কোড লোড করার আগে সরঞ্জাম.নামস্পেস নামের জায়গার বর্তমান সংস্করণটিকে ধ্বংস করে দেয় এই কারণে এটি ঘটে।

myapp.web=> (refresh)

CompilerException java.lang.RuntimeException: Unable to resolve symbol: refresh in this context, compiling:(/private/var/folders/ks/d6qbfg2s6l1bcg6ws_6bq4600000gn/T/form-init819543191440017519.clj:1:1)

আপনি এই সমস্যার জন্য সম্পূর্ণরূপে যোগ্যতাসম্পন্ন বর্ণ নামটি ব্যবহার করতে পারেন তবে ব্যক্তিগতভাবে আমি প্রতিটি রিফ্রেশে টাইপ না করা পছন্দ করি। উপরের সাথে আর একটি সমস্যা হ'ল মূল নামস্থানটি পুনরায় লোড করার পরে মানক আরপিএল সহায়ক ফাংশনগুলি (যেমন docএবং source) আর রেফারেন্স করা হয় না।

এই সমস্যাগুলি সমাধান করার জন্য আমি ব্যবহারকারীর নেমস্পেসের জন্য একটি আসল উত্স ফাইল তৈরি করতে পছন্দ করি যাতে এটি নির্ভরযোগ্যভাবে পুনরায় লোড করা যায়। আমি উত্স ফাইলটি রেখেছি ~/.lein/src/user.cljতবে আপনি যে কোনও জায়গায় রাখতে পারেন। এই ফাইলটির জন্য শীর্ষ এনএস ঘোষণায় রিফ্রেশ ফাংশন প্রয়োজন:

(ns user
  (:require [clojure.tools.namespace.repl :refer [refresh]]))

আপনি সেটআপ একটি leiningen ব্যবহারকারী প্রোফাইল মধ্যে ~/.lein/profiles.cljযাতে অবস্থান আপনি বর্গ পথ যোগ করা হয় ফাইল করা। প্রোফাইলটি দেখতে এমন কিছু দেখতে পাওয়া উচিত:

{:user {:dependencies [[org.clojure/tools.namespace "0.2.7"]]
        :repl-options { :init-ns user }
        :source-paths ["/Users/me/.lein/src"]}}

নোট করুন যে আমি আরপিএল চালু করার সময় ব্যবহারকারীর নাম স্থানটি এন্ট্রি পয়েন্ট হিসাবে সেট করেছি। এটি নিশ্চিত করে যে আরপিএল সহায়ক ফাংশনগুলি আপনার অ্যাপ্লিকেশনটির প্রধান নাম স্থানের পরিবর্তে ব্যবহারকারীর নামস্থানে রেফারেন্স পেতে পারে। আপনি সবে তৈরি করা উত্স ফাইলটি পরিবর্তন না করা পর্যন্ত সেগুলি হারাবে না।

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


ভাল পরামর্শ। একটি প্রশ্ন: উপরে "উত্স-পাথ" এন্ট্রি কেন?
অ্যালান থম্পসন

2
@ ডার্ক জিয়ারস, :source-pathsআমার সাথে পেয়েছি #<FileNotFoundException java.io.FileNotFoundException: Could not locate user__init.class or user.clj on classpath: >, যখন :resource-pathsসমস্ত কিছু ঠিক আছে।
fl00r

1
@ fl00r এবং এটি এখনও ত্রুটি ছুড়ে ফেলেছে? আপনি যে ফোল্ডারটি থেকে আরপিএল চালু করছেন তাতে কোনও বৈধ প্রজেক্ট.সিএলজে রয়েছে? এটি আপনার সমস্যার সমাধান করতে পারে।
ডার্ক জিয়ার্স

1
হ্যাঁ, এটি বেশ স্ট্যান্ডার্ড, এবং সবগুলি দিয়ে ভাল কাজ করে :resource-paths, আমি repl এর ভিতরে আমার ব্যবহারকারীর নেমস্পেসে আছি।
fl00r

1
এই reloadসমস্যাটির কারণেই আমার কাছে মিথ্যা কথা বলার মতো একটি আরএপিএল নিয়ে কাজ করার জন্য আমার খুব সময় ছিল । তারপরে এটি প্রমাণিত হয়েছিল যে আমি যা ভাবছিলাম তা আর ছিল না। কারও কি এই পরিস্থিতি ঠিক করা উচিত?
আল্পার

41

সর্বোত্তম উত্তরটি হ'ল:

(require 'my.namespace :reload-all)

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

ডকুমেন্টেশন:

প্রয়োজন


2
এটিই একমাত্র উত্তর যা দিয়ে কাজ করেছে lein repl, কালজুরে ১.7.০ এবং এনআরইপিএল ০.০.৫ যদি আপনি ক্লোজারে নতুন হন: উদাহরণস্বরূপ, নাম স্পেসটি ... এর 'my.namespaceসাথে সংজ্ঞায়িত করা (ns ...)হয়েছে । src//core.clj
অ্যারন ডিজুল্লা

1
এই উত্তরের সমস্যাটি হ'ল মূল প্রশ্নটি (লোড-ফাইল ...) ব্যবহার করছে, কোনও প্রয়োজন নেই। কীভাবে তার যুক্ত করা যাবে: লোড-ফাইলের পরে নাম স্থানটিতে পুনরায় লোড করুন?
jgomo3

কারণ নামের জায়গার কাঠামোটি proj.stuff.coreমিররগুলির মতো ডিস্কে থাকা ফাইলের কাঠামোর মতো src/proj/stuff/core.clj, REPL সঠিক ফাইলটি সনাক্ত করতে পারে এবং আপনার প্রয়োজন নেই load-file
অ্যালান থম্পসন

6

পাপাচনের উত্তরের উপর ভিত্তি করে একটি লাইনার:

(clojure.tools.namespace.repl/refresh)

5

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

(ns my.namespace)

আমি আমার নামস্থানগুলি এর মতো ঘোষণা করি:

(clojure.core/let [s 'my.namespace]
                  (clojure.core/remove-ns s)
                  (clojure.core/in-ns s)
                  (clojure.core/require '[clojure.core])
                  (clojure.core/refer 'clojure.core))

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


3

আবার লোড-ফাইল চেষ্টা করবেন?

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


1

যত তাড়াতাড়ি (use 'foo.bar)আপনার জন্য কাজ, তার মানে আপনি foo বিন্যাস / bar.clj অথবা আপনার CLASSPATH উপর foo বিন্যাস / bar_init.class আছে। বার_ইনিট.ক্লাস বারক্ললজের একটি এওটি-সংকলিত সংস্করণ হবে। আপনি যদি করেন তবে (use 'foo.bar)আমি নিশ্চিত নই যে ক্লোজিউর ক্লজকে ক্লজ বা অন্যভাবে রাস্তা পছন্দ করে কিনা। যদি এটি শ্রেণিবদ্ধ ফাইলগুলি পছন্দ করে এবং আপনার উভয় ফাইলই থাকে তবে এটি পরিষ্কার হয়ে গেছে যে clj ফাইল সম্পাদনা এবং তারপরে নাম স্থান পুনরায় লোড করার কোনও প্রভাব নেই।

বিটিডাব্লু: আপনার ক্লাসস্প্যাটটি সঠিকভাবে সেট করা থাকলে আপনার load-fileআগে প্রয়োজন নেই use

বিটিডাব্লু 2: যদি আপনার load-fileকোনও কারণে প্রয়োজন হয় তবে আপনি ফাইলটি সম্পাদনা করলে কেবল এটি আবার করতে পারেন।


14
কেন এটি সঠিক উত্তর হিসাবে চিহ্নিত হয়েছে তা নিশ্চিত নয়। এটি প্রশ্নের পরিষ্কারভাবে উত্তর দেয় না।
আনানফায়

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