Nano Hash - криптовалюты, майнинг, программирование

Область видимости переменной с дочерними функциями

Я прочитал это сегодня

«Local может использоваться только внутри функции; это делает имя переменной видимой областью, ограниченной этой функцией и ее дочерними элементами». Автор руководства ABS считает такое поведение ошибкой.

§ Локальные переменные

и я придумал этот сценарий

begin () {
  local foo
  alpha
}
alpha () {
  foo=333 bar=444
  bravo
}
bravo () {
  printf 'foo %3s bar %s\n' "$foo" "$bar"
}
begin
bravo

Вывод

foo 333 bar 444
foo     bar 444

Итак, как вы можете видеть, поскольку я не local bar, это просочилось в глобальную область. Вопросы:

  • Является ли локальная переменная доступной для дочерней функции ошибкой или это было только его мнением?
  • Есть ли в Bash способ пометить все как локальное, аналогично тому, как set -a отмечает все для экспорта?
  • Если это не удается, есть ли в Bash способ проверить эти утечки глобальных переменных?

  • Чтобы быть ясным, динамическая область видимости почти всегда считается недостатком языкового дизайна. В случае Bash (и большинства других оболочек) это преднамеренная, а не случайная ошибка. 29.12.2014

Ответы:


1

Является ли локальная переменная доступной для дочерней функции ошибкой или это было только его мнением?

Нет, это не ошибка. Это только его мнение.

Есть ли в Bash способ пометить все как локальное, аналогично тому, как set -a отмечает все для экспорта?

No.

Если это не удается, есть ли в Bash способ проверить эти утечки глобальных переменных?

да. Просто попробуйте «установить» или «объявить», оба без каких-либо параметров.

29.12.2014

2

Если это не удается, есть ли в Bash способ проверить эти утечки глобальных переменных?

Нет. В Bash есть недокументированная концепция, называемая «скрытые переменные», которая делает невозможным проверку того, установлен ли локальный, без нарушения переменной.

Этот тест демонстрирует скрытую переменную вместе с зависящей от области видимости характером unset встроенный.

function f {
    case $1 in 1)
        typeset x=1
        f 2
        ;;
    2)
        typeset x
        unset -v x # Does nothing (demonstrates hidden local)
        f 3
        ;;
    [345])
        printf "x is %sunset\n" ${x+"not "}
        unset -v x
        f $(($1 + 1))
    esac
}

f 1

# output:
# x is unset
# x is not unset
# x is unset

Bash имеет способ принудительно установить глобальное значение с помощью declare -g, однако нет способа заставить bash разыменовать его или проверить, установлен ли он, что делает эту функцию очень ограниченной полезностью.

Надеюсь, это ясно демонстрирует проблему.

f() {
    local x="in x"      # Assign a local
    declare -g x=global # Assign a global
    declare -p x        # prints "in x"
    unset -v x          # try unsetting the local
    declare -p x        # error (x is invisible)
}
f
declare -p x # x is visible again, but there's no way to test for that before now.
29.12.2014
  • @StevenPenny Я неправильно понял? Переменные не могут просочиться таким образом, чтобы случайно установить локальный объект там, где был предназначен глобальный (кроме declare -g). Самая распространенная причина намеренного задания переменной, объявленной в родительской области, - это имитация передачи по ссылке, когда тот факт, что вы не можете проверить локализованную переменную или гарантировать, что ссылка на конкретный экземпляр является серьезной проблемой. Если намерение состоит в том, чтобы установить глобальное значение, применима та же проблема. declare -g гарантирует, что был установлен правильный экземпляр, но нет возможности напрямую ссылаться на глобальный объект после его установки. 29.12.2014
  • Правильно, unset снял все слои к тому времени, когда сценарий будет закончен. Когда последняя ветвь case попадает в первый раз, x устанавливается в первой области, но тест (с использованием ${x+word}) отображает обратное. Невозможно различить, установлен ли x или нет, пока вы не отключите его от дочерней области. Это именно та проблема, которую вы пытаетесь избежать (или обнаружить) в своем примере вопроса. 29.12.2014
  • Код / комментарии верны. Если ваш bash старше 4.2 alpha, значит, у вас нет declare -g. Это просто для демонстрации. определение global перед вызовом f дает тот же эффект. 29.12.2014
  • Итак, я попробовал это снова с Bash 4.3. Только глобальное значение x доступно вне функции, так в чем проблема? 26.04.2015
  • @StevenPenny Это ловушка с declare -g, описанная в первом комментарии (и большая проблема с динамической областью видимости в целом). Единственная функция declare -g - разрешить безусловное присвоение глобальной области, даже если локальный объект с таким же именем был установлен в любом родительском элементе текущей области. Это не делает эту переменную доступной для использования из текущей области, пока вы либо не вернетесь из первой функции, которая ее локализовала, либо не вызовете unset из любой дочерней области последней функции, которая локализовала ее, пока не будут сброшены все локальные переменные с конфликтующими именами. 06.06.2015
  • Новые материалы

    Кластеризация: более глубокий взгляд
    Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

    Как написать эффективное резюме
    Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

    Как я автоматизирую тестирование с помощью Jest
    Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

    Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
    В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..