অন্যান্য স্ক্রিপ্টগুলিতে কীভাবে (উত্স) আর স্ক্রিপ্ট অন্তর্ভুক্ত করা যায়


108

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

আমি requireফাংশনটির অনুরূপ কিছু সন্ধান করছি , এটি প্যাকেজটি লোড করে যদি এটি এখনও লোড না করা হয়। আমি কল করতে চাই না source("util.R")কারণ এটি যখনই ডাকা হবে তখন স্ক্রিপ্টটি লোড করবে।

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


37
আমি সার্বক্ষণিক স্বতন্ত্র প্রকল্পগুলির জন্য প্যাকেজ তৈরি করি। এটি খুব বেশি কাজ নয়, এবং সুবিধাগুলি বিশাল। যাও, আপনি জানেন যে আপনি এটি করতে চান ...
অ্যান্ড্রি

উত্তর:


93

এখানে একটি সম্ভাব্য উপায়। existsআপনার util.Rকোডে অনন্য কিছু পরীক্ষা করার জন্য ফাংশনটি ব্যবহার করুন ।

উদাহরণ স্বরূপ:

if(!exists("foo", mode="function")) source("util.R")

( mode="function"গ্যাভিন সিম্পসন নির্দেশিত হিসাবে অন্তর্ভুক্ত সম্পাদিত )


4
এর দুর্দান্ত ব্যবহার exists()- mode = "function"এটি বোকা প্রমাণ হিসাবে যুক্ত করার প্রয়োজন
গ্যাভিন সিম্পসন

1
exists()আর.০.০.২ এ ফিরে আসার ব্যতীত একটি ত্রুটি ছুঁড়েছে বলে মনে হচ্ছে।
মাইকেল শুবার্ট

সঠিক ব্যবহারটি `বিদ্যমান (" foo ") এবং উত্তরটি সম্পাদিত হয়েছিল।
অ্যান্ড্রি

18

আর অন্তর্নির্মিত কোনও জিনিস নেই, যেহেতু আর কল কলগুলি ট্র্যাক করে না sourceএবং কোথা থেকে লোড হয়েছিল তা নির্ধারণ করতে সক্ষম হয় না (প্যাকেজগুলি ব্যবহার করার সময় এটি হয় না)। তবুও, আপনি সি .hফাইলগুলির মতো একই ধারণা ব্যবহার করতে পারেন , অর্থাত্ পুরোটি এতে মোড়ানো:

if(!exists('util_R')){
 util_R<-T

 #Code

}

এবং তারপর কোডের source("util.R")মধ্যে কল if, ডান?
রাফালোটুফো

1
@ ইরালোটুফো আপনি যথারীতি উত্স ("Use.R") দিতেন। এমবিকিউয়ের পোস্টের কোডটি ব্যবহারের মধ্যে চলে যাবে। আপনি কেবল ব্যবহারের মধ্যে পুরো শরীরটি রেখেছেন right এখনই একটি দৈত্য যদি () বিবৃতিতে রাখে, যদি তা বোঝা যায়।
কিথ টম্বল্বি

10

বলে util.Rএকটি ফাংশন উত্পাদন foo()। আপনি এই বিশ্বস্ত পরিবেশে এই ফাংশনটি উপলব্ধ কিনা তা পরীক্ষা করতে পারেন এবং স্ক্রিপ্টটি যদি তা না হয় তবে:

if(identical(length(ls(pattern = "^foo$")), 0))
    source("util.R")

নামের সাথে এটি কিছু খুঁজে পাবে foo। আপনি যদি কোনও ফাংশন সন্ধান করতে চান তবে (@ অ্যান্ড্রি দ্বারা উল্লিখিত) exists()সহায়ক তবে সঠিক ধরণের অবজেক্টটি কীভাবে সন্ধান করতে হবে তা বলা দরকার, যেমন

if(exists("foo", mode = "function"))
    source("util.R")

এখানে exists()পদক্ষেপ নেওয়া হয়েছে:

> exists("foo", mode = "function")
[1] FALSE
> foo <- function(x) x
> exists("foo", mode = "function")
[1] TRUE
> rm(foo)
> foo <- 1:10
> exists("foo", mode = "function")
[1] FALSE

এই ক্ষেত্রে, আপনি ব্যবহার করতে চাইতে পারেন grepl(..., value=TRUE)কারণ আপনার অনুসন্ধান শব্দটি সম্ভবত কোনও রেজেক্স নয়। +1, উপায় দ্বারা।
অ্যান্ড্রি

?? grepl()কোন যুক্তি নেই value, তবে আমার সম্ভবত রেজিপেক্সটি ঠিক করা উচিত ls()...
গ্যাভিন সিম্পসন

দুঃখিত আমার ভুল. আমি বোঝাতে চেয়েছিলামfixed=TRUE
এন্ড্রি

@ এন্ড্রি - আহ, ঠিক আছে। এটি কোনওভাবেই কাজ করে নি। এটিকে ভাবতে ভাবতে টানতে পেরেছি। exists()আরও ভাল তবে আমি এখন দেখছি আপনি এর মধ্যে একটি উত্তর পোস্ট করেছেন।
গ্যাভিন সিম্পসন

5

আপনি এমন একটি ফাংশন লিখতে পারেন যা একটি ফাইলের নাম এবং একটি পরিবেশের নাম নেয়, ফাইলটি পরিবেশে লোড করা হয়েছে কিনা তা পরীক্ষা করে দেখুন এবং sys.sourceযদি না হয় তবে ফাইলটি উত্স হিসাবে ব্যবহার করে।

এখানে একটি দ্রুত এবং অনির্ধারিত ফাংশন (উন্নতিগুলি স্বাগত!):

include <- function(file, env) {
  # ensure file and env are provided
  if(missing(file) || missing(env))
    stop("'file' and 'env' must be provided")
  # ensure env is character
  if(!is.character(file) || !is.character(env))
    stop("'file' and 'env' must be a character")

  # see if env is attached to the search path
  if(env %in% search()) {
    ENV <- get(env)
    files <- get(".files",ENV)
    # if the file hasn't been loaded
    if(!(file %in% files)) {
      sys.source(file, ENV)                        # load the file
      assign(".files", c(file, files), envir=ENV)  # set the flag
    }
  } else {
    ENV <- attach(NULL, name=env)      # create/attach new environment
    sys.source(file, ENV)              # load the file
    assign(".files", file, envir=ENV)  # set the flag
  }
}

5

এখানে আমি লিখেছি একটি ফাংশন। এটি base::sourceবিশ্বব্যাপী পরিবেশের তালিকা তালিকায় উত্সযুক্ত ফাইলগুলির একটি তালিকা সঞ্চয় করার জন্য ফাংশনটি আবৃত করে sourced। যদি আপনি .force=TRUEকলটিতে উত্সটিতে কোনও যুক্তি সরবরাহ করেন তবে এটি কেবল একটি ফাইলকেই পুনরায় উত্স করবে। এর আর্গুমেন্ট স্বাক্ষরটি অন্যথায় বাস্তবের মতোই source()তাই এটি ব্যবহার করতে আপনার স্ক্রিপ্টগুলি পুনরায় লেখার দরকার নেই।

warning("overriding source with my own function FYI")
source <- function(path, .force=FALSE, ...) {
  library(tools)
  path <- tryCatch(normalizePath(path), error=function(e) path)
  m<-md5sum(path)

  go<-TRUE
  if (!is.vector(.GlobalEnv$sourced)) {
    .GlobalEnv$sourced <- list()
  }
  if(! is.null(.GlobalEnv$sourced[[path]])) {
    if(m == .GlobalEnv$sourced[[path]]) {
      message(sprintf("Not re-sourcing %s. Override with:\n  source('%s', .force=TRUE)", path, path))
      go<-FALSE
    }
    else {
      message(sprintf('re-sourcing %s as it has changed from: %s to: %s', path, .GlobalEnv$sourced[[path]], m))
      go<-TRUE
    }
  } 
  if(.force) {
    go<-TRUE
    message("  ...forcing.")
  }
  if(go) {
    message(sprintf("sourcing %s", path))
    .GlobalEnv$sourced[path] <- m
    base::source(path, ...)
  }
}

এটি বেশ চমকপ্রদ (প্রচুর কল message()) যাতে আপনি যদি যত্ন নেন তবে এই লাইনগুলি বাইরে নিতে পারেন। প্রবীণ আর ব্যবহারকারীদের কোনও পরামর্শ প্রশংসা করা হয়; আমি আর তে বেশ নতুন।


0

আমার কোড যেখানে রয়েছে সেখানে পুরো ঠিকানা ব্যবহার করে আমি আমার সমস্যার সমাধান করেছি: আগে:

if(!exists("foo", mode="function")) source("utils.r")

পরে:

if(!exists("foo", mode="function")) source("C:/tests/utils.r")
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.