В R я использую source()
для загрузки некоторых функций:
source("functions.R")
Можно ли получить список всех функций, определенных в этом файле? Как имена функций. (Может быть, source()
сам может это как-то вернуть?).
PS: в крайнем случае можно было бы вызвать source()
второй раз, как, local({ source(); })
а затем выполнить ls()
внутри и фильтровать функции, но это слишком сложно - есть ли более простое и менее неуклюжее решение?
source()
, но эта старая тема может быть интересна для вас.envir <- new.env() source("functions.R", local=envir) lsf.str(envir)
Ответы:
Я думаю, что лучшим способом было бы поместить файл во временную среду. Запросите эту среду для всех функций, затем скопируйте эти значения в родительскую среду.
источник
new.env()
вместо элегантного,local({ })
который я не уверен, будет ли он работать сassign
родительским фреймом.local()
? И кстати, 2) что вы делаете в цикле for: не существует ли какой-либо функции для объединения сред?attach
можно привыкнуть к тому, чтобы присоединить одну среду к другой. Хотя вы должны использоватьpos
аргумент, а не указыватьparent.frame
. И это будет хорошо работать только для копирования всей среды,for
цикл MrFlick позволяет копировать только функции поверх.Это немного неуклюже, но вы можете посмотреть на изменения в объектах до и после
source
вызова следующим образом.источник
Я думаю, что это регулярное выражение улавливает почти все допустимые типы функций (бинарный оператор, функции присваивания) и каждый действительный символ в имени функции, но, возможно, я пропустил крайний случай.
источник
.
и функцией присваивания (`foo<-`<- function(x, value)
существует.=
для назначения, это не поймает ни одну из моих функций ...` d d` <- function(x)
которые в данный момент не пойманы. Я не хочу, чтобы регулярное выражение стало слишком глупым, хотя я мог бы вернуться к нему.assign
,<<-
и->
. И будет очень трудно сделать так, чтобы этот подход учитывал функции, которые определены внутри функций, но на самом деле не находятся в исходной среде. Ваш ответ должен работать очень хорошо для стандартных случаев, но на самом деле вы не хотите писать R-парсер без регулярных выражений.Если это ваш собственный сценарий, и вы можете контролировать его форматирование, достаточно простого соглашения. Просто убедитесь, что каждое имя функции начинается с первого символа в строке и что слово
function
также появляется в этой строке. Любое другое использование словаfunction
должно появляться в строке, которая начинается с пробела или табуляции. Тогда однострочное решение:Преимущества этого подхода в том, что
это очень просто . Правила просто изложены, и есть только одна простая строка кода R, необходимая для извлечения имен функций. Regex также прост, и для существующего файла это очень легко проверить - просто наберите слово
function
и проверьте, соответствует ли каждое отображаемое вхождение правилу.нет необходимости запускать источник. Это полностью статично .
во многих случаях вам вообще не нужно менять исходный файл, а в других случаях изменения будут минимальными. Если вы пишете сценарий с нуля с учетом этого, его еще проще организовать.
Есть много других альтернатив вдоль идеи конвенций. у вас может быть более сложное регулярное выражение или вы можете добавить
# FUNCTION
в конце первой строки определения любой функции, если вы пишете скрипт с нуля, а затем извлекаете эту фразу и извлекаете первое слово в строке, но основное предложение здесь кажется особенно привлекателен благодаря своей простоте и другим перечисленным преимуществам.Тестовое задание
источник
lapply(x, function(y) dostuff(y))
сломал бы это# TODO
в свой код, чтобы я мог, например, выполнить свои задачи. Другая возможность в том же духе будет записана# FUNCTION
в конце первой строки любого определения функции.Это адаптирует код, использованный в посте из моего комментария, для поиска последовательности токенов (символ, оператор присваивания, затем функция), и он должен захватывать любые определенные функции. Я не уверен, что он надежен как ответ MrFlick, но это еще один вариант:
источник