Р: Где формальные формы для функции, хранящейся в памяти?

Если функция была определена, но еще не была вызвана, существуют ли формальные формы, не имеющие значений по умолчанию? Если да, то существуют ли они в среде выполнения, в среде, где находится определение функции, или где-то еще?

Если функция была определена, но еще не вызвана, а функции присвоено значение по умолчанию, существует ли это значение? Если да, то в какой среде он существует? Если выражение по умолчанию оценивается как константа, было ли присвоено этому значению формальное значение, которое должно быть перезаписано при вызове функции, если значение предоставлено? Если нет, то в какой среде это (фиксированное) значение по умолчанию находится между моментом определения и временем вызова функции?

После того, как функция была вызвана и фактические значения или значения по умолчанию были присвоены формальным формам, переданы в тело и, при необходимости, определены и / или оценены, продолжают ли формальные формы существовать? Если да, то в какой среде они тогда существуют?

Я понятия не имею, о чем вы спрашиваете

Hong Ooi 29.04.2018 14:23

Мне кажется ясным, о чем идет речь. По сути: если у вас есть что-то вроде fun <- function(x=2), существует ли x в какой-то среде? И вопрос в таких вариациях.

Karolis Koncevičius 29.04.2018 14:29

AFAIK, его не существует.

Roman Luštrik 29.04.2018 14:36

@HongOoi - вопрос Эндрю имеет смысл в контексте цитаты Джона Чемберса: «Чтобы понять вычисления в R, полезны два слогана: 1) Все, что существует, является объектом, и 2) Все, что происходит, - это вызов функции». Если все в R является объектом, формальные элементы функции также должны быть объектами. Поэтому разумно задавать вопросы об окружающей среде (ах), в которой они существуют.

Len Greski 29.04.2018 19:59
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
4
4
156
1

Ответы 1

Формы для функции существуют как объекты в среде функции после того, как экземпляр функции загружается в память при вызове. В Продвинутый R Хэдли Уикхэм называет эту среду среда исполнения. Доступ к ячейкам памяти объектов можно получить через pryr::address().

В качестве примера я буду использовать модифицированную версию кода, которую я ранее написал, чтобы проиллюстрировать ячейки памяти в функции makeVector() из второго задания по программированию для курса Джонса Хопкинса R программирование по coursera.org.

makeVector <- function(x = 200) {
     library(pryr)
     message(paste("Address of x argument is:",address(x)))
     message(paste("Number of references to x is:",refs(x)))
     m <- NULL
     set <- function(y) {
          x <<- y
          message(paste("set() address of x is:",address(x)))
          message(paste("Number of references to x is:",refs(x)))
          m <<- NULL
     }
     get <- function() x
     setmean <- function(mean) m <<- mean
     getmean <- function() m
     list(set = set, get = get,
          setmean = setmean,
          getmean = getmean)
}

Как указано выше, makeVector() - это объект S3, что означает, что мы можем получить доступ к объектам в его среде через геттеры и сеттеры, также известные как методы мутатора.

Мы можем загрузить экземпляр объекта makeVector() в память и запросить адрес и значение x с помощью следующего кода.

makeVector()$get()

... и результат:

> makeVector()$get()
Address of x argument is: 0x1103df4e0
Number of references to x is: 0
[1] 200
> 

Как видно из выходных данных, x имеет место в памяти, но нет других объектов, которые содержат ссылки на него. Кроме того, для x было установлено значение по умолчанию вектора длины 1 со значением 200.

Я предоставляю подробный обзор объектов в среде makeVector() в своем ответе на Кэширование среднего значения вектора в R.

Что касается вопроса о том, как долго формальные элементы существуют в памяти, они существуют до тех пор, пока среда, созданная для хранения вызываемого экземпляра функции, находится в памяти. Поскольку сборщик мусора работает с объектами, у которых нет внешних ссылок, если экземпляр функции не сохраняется в объекте, он имеет право на сборку мусора, как только вызов функции возвращает результат в родительскую среду.

этот ответ очень ясен и восхитительно поучительно. Однако я все еще не уверен в некоторых деталях. (1) Является ли «среда выполнения функции после ее загрузки в память» тем же средой, что и среда выполнения? Или вызывающая или окружающая среда? Или что-то другое? Я воображал, что формальные значения и значения по умолчанию являются интерфейсом функции к внешнему миру и находятся в своей собственной «промежуточной» среде, но я уверен, что это неправильно. Почти уверен. (2) адрес x такой же, как у makeVector? И (продолжение)

andrewH 29.04.2018 20:32

(3) Происходит ли присвоение 200 0x1103df4e0, когда функция определена, когда она вызывается или в какое-то время между ними?

andrewH 29.04.2018 20:34

@andrewH - когда функция вызывается, R Evaluator создает новую среду для функции и инициализирует «объекты обещания» для каждого аргумента, перечисленного в формальном разделе функции. Эти объекты хранятся во вновь созданной среде для функции, которая является дочерней по отношению к среде, в которой была создана функция. Когда необходимо оценить аргументы, они будут оцениваться в среде, из которой пришел вызов. Любым аргументам, которым не присвоены значения в этом процессе, присваиваются значения по умолчанию (Программное обеспечение для анализа данных, Kindle Edition, расположение 809+).

Len Greski 29.04.2018 21:02

@andrewH - (2) адрес (т.е. расположение в физической памяти) x отличается от адреса makeVector(). Это можно проверить, сохранив результат makeVector() в объекте, запустив на нем pryr::address() и сравнив этот адрес с адресом, возвращаемым $get(). (3) как указано выше, присвоение 200 происходит при вызове функции. Если я ответил на ваш вопрос, примите ответ.

Len Greski 29.04.2018 21:08

повторю ваш первый ответ: так это среда, которую они называют средой исполнения, да? Извини, если я вбиваю это в землю. Я просто хочу быть уверенным, что могу связать то, что я узнаю от вас, с тем, что, как мне казалось, я узнал из «Advanced R» Хэдли. re ваш второй ответ: подойдет. Я прочитал ваш пост Caching the Mean. Очень красивая штука.

andrewH 30.04.2018 01:13

@andrewH - Да, это среда, которую Уикхэм называет средой выполнения в Глава окружения из Продвинутый R. Спасибо, что сообщили мне, что читаете это, чтобы я мог получить для вас правильную перекрестную ссылку. Кроме того, никаких извинений не требуется. Пожалуйста, задавайте столько дополнительных вопросов, сколько вам нужно, чтобы полностью понять концепции. Также спасибо за отзыв о моей исходной статье.

Len Greski 30.04.2018 01:29

@LenGreski, стилистический вопрос: использование require в начале мало что даст: если он вернет FALSE, ваша функция будет продолжать работать без изменений (и не удастся с первым object not found). Есть ли причина (1) не проверять возвращаемое значение или (2) не использовать library? Или цель - более явный и самодокументированный код?

r2evans 30.04.2018 18:08

@ r2evans - Мое намерение было (2), но я обновлю код, включив проверку ошибок require() и вызов library().

Len Greski 01.05.2018 03:36

Я не понимаю, чем ваш новый код лучше, чем просто library(pryr). Если require(pryr) возвращает F, ваш вызов library обязательно завершится неудачей; если он возвращает T, то library никогда не может быть вызван, но конечный результат тот же: пространство имен загружается и присоединяется к пути поиска и т. д.

r2evans 01.05.2018 03:44

@ r2evans - тут мозговая судорога немного, должна работать stop(), если require() дает сбой.

Len Greski 01.05.2018 04:04

@ r2evans - прочитав Сообщение блога Yihui Xie о library() vs. require(), я согласен с тем, что library() более подходит, чем require(), хотя в документации R указано, что require() предназначен для использования в функциях R. Спасибо за то, что вы спрашивали меня об этом.

Len Greski 02.05.2018 13:17

Не то чтобы я часами размышлял над этой темой, но ... я думаю, что единственное практическое использование require - это когда у вас есть два пути кода: один, когда доступен пакет, другой в противном случае, возможно, из-за скорости / эффективности, возможно, из-за дополнительных возможностей . В library второй путь жестко запрограммирован как stop. (И if (!require(...)) install.packages(), как правило, не следует использовать в продакшене, возможно, только в учебных / демонстрационных материалах.) Я уже цитировал этот пост, кстати, он хорошо написан.

r2evans 02.05.2018 17:08

Другие вопросы по теме