Как вызвать функцию только один раз, и только один раз ...?

голоса
6

Я часто хочу, чтобы вызвать определенную функцию только один раз, но мне нужно, чтобы вызвать его из другой функции, которая получает повторно вызывается. Например, принимая снимок чего-то для дальнейшего использования. Я обычно делаю это путем установки глобального логического значения.

Я задаюсь вопросом, является ли способ я могу сделать это на самом деле лучший способ?

Кажется, я припоминаю читал, что глобальные переменные плохо, и глобальные логические переменные еще хуже!

Во всяком случае, это то, как я обычно выполнить запуск определенного метода только один раз:

В моем исходном наборе переменных ...

private var myStatus:Boolean = false;

Тогда, в функции, которая вызывается часто ...

if (!myStatus) {
    doMyFunction();
    myStatus = true;
}

Это кажется довольно логичным для меня, но это правильно ?

UPDATE : Ну, основываясь на том, что я узнал от ваших ответов, вместо проверки глобального логические переменного, теперь я сначала проверить , существует ли узел XML (я храню изображения в пределах структуры XML , прежде чем какая - либо письменная форма происходит диск), и, если это не так, то я добавить новый узел с base64 кодированные данные изображения. Я до сих пор установить булев флаг так , чтобы потом можно перезаписать пустое изображение с данными изображений отредактировано пользователем в случае необходимости. Он отлично работает. Спасибо за вашу помощь!

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

Задан 09/12/2008 в 23:59
источник пользователем
На других языках...                            


7 ответов

голоса
7

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

Это, вероятно, лучше, чтобы переместить этот вызов, когда зависимость от логики, которая вызывает ваши функции много раз. Если вам нужно только вызвать функцию один раз, то вызывать только один раз. С другой стороны, передавать различные аргументы функции, чтобы указать, что вы делаете что-то другое.

Ответил 10/12/2008 в 00:17
источник пользователем

голоса
5

Это действительно зависит от того, что именно вы имеете в виду. Если ваш код будет вызываться из нескольких потоков, то у вас есть условие, которое может означать , что doMyFunctionможно было бы назвать много раз. Это происходит потому , что более чем один поток может проверить myStatus, убедиться , что оно ложно, то вызвать doMyFunction. Вы можете улучшить ситуацию немного, установив переменную первым:

if (!myStatus) {
    myStatus = true;
    doMyFunction();
}

но это только сужает окно проблем, не устраняет ее.

Для устранения состояния гонки, вам нужен замок.

Ответил 10/12/2008 в 00:06
источник пользователем

голоса
4

В C / C ++ вы можете обычно держать тот факт, что doMyFunction () вызывается только один раз инкапсулируется с помощью статической переменной следующим образом:

void doMyFunction() {
     // gets called only once.
     // side effects go here.
}

void functionThatGetsCalledALot() {
    static bool called = false;
    if (!called) {
        doMyFunction();
        called = true;
    }
    // do more stuff
}

Это позволяет избежать использования глобалов, но имеет тот же эффект, и статический вар объявлен именно там, где это уместно, так что понятно, что происходит. Обратите внимание, что это не поточно-, так что вам нужен замок, если у вас есть темы.

Ответил 10/12/2008 в 00:09
источник пользователем

голоса
2

Это не потокобезопасно. Это не вопрос к вам, но ты сказал «язык-агностик»: Вы, вероятно, не хотел бы использовать эту модель в библиотеке общего назначения для Java.

Это сложный вопрос, на языке-агностик способом, так как имеющиеся альтернативы в значительной степени зависят от языка. Например, на POSIX вы получили pthread_once, если вам нужна безопасность потоков. В C вы получили статические локальные переменные, чтобы получить, что логическое из глобальной области видимости. В любом ОО-языке, если вы принимаете снимок «что-то» для дальнейшего использования, то может быть подходящим объект, соответствующий «что-то» (или на снимке), который может хранить флаг.

Ответил 10/12/2008 в 00:09
источник пользователем

голоса
0

В Perl 5.10 или более поздней версии, вы должны использовать stateпеременную.

use 5.010;

sub test{
  state $once = 1;

  if( $once ){
    $once = undef;
    say 'first';
  } else {
    say 'not first';
  }
}

test for 1..5;

выходы

первый
не первый
не первый
не первый
не первый
Ответил 10/12/2008 в 21:01
источник пользователем

голоса
0

Я не вижу никакого другого пути. Единственное, что приходит на ум, о том, как улучшить это - безопасность потока. Но это необходимо, только если у вас есть несколько потоков вызова функции.

Ответил 10/12/2008 в 00:06
источник пользователем

голоса
0

Я не вижу ничего плохого с вашим подходом здесь. Имейте в виду, что не всегда «правильный» вещь ... есть определенно неправильные вещи, но то, что это право может быть субъективным, и может также зависеть драматически на основе требований системы.

Ответил 10/12/2008 в 00:02
источник пользователем

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more