Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   Альтернатива return с меткой (https://javascript.ru/forum/misc/7319-alternativa-return-s-metkojj.html)

Niar 26.01.2010 16:08

Альтернатива return с меткой
 
Чтобы выйти из цикла можно использовать break
for(){
break;
}

В функции можно использовать return без выражения справа.
function func(){
return;
}

Чтобы во вложенном цикле выйти из внешнего можно использовать break с меткой
firstfor:
for(){
for(){
break firstfor;
}
}

Вопрос как из вложенной функции завершить внешнюю
function func1(){
functiob func2(){
//Что-то завершающие func1
}
}

PeaceCoder 26.01.2010 16:38

function func1(){
  try{
    function func2(){
      //Что-то завершающие
      throw 'exit';
      }
    продолжение func1;
    }catch(e){if e!=='exit' throw e}
  }


Но оно гораздо медленее ретурнов. Легче сделать ретурн с опред значением и его на выходе проверять.
try catch vs. returns кто быстрее ?

Niar 26.01.2010 16:40

Спасибо
Поставил +

x-yuri 28.01.2010 09:58

Цитата:

Сообщение от Niar
Вопрос как из вложенной функции завершить внешнюю

не надо этого хотеть (c)

Dmitry A. Soshnikov 28.01.2010 12:40

Цитата:

Сообщение от x-yuri
не надо этого хотеть (c)

Ну, почему? Возможны варианты, когда из фунарга удобно завершить и саму функцию (например, в Ruby для таких случаев предусмотрены две конструкции): http://javascript.ru/blog/Dmitry-A.-...unarg-i-return

x-yuri 28.01.2010 13:17

хорошо, а можно практический пример?

Dmitry A. Soshnikov 28.01.2010 13:50

Цитата:

Сообщение от x-yuri
хорошо, а можно практический пример?

Там же в статье был:


function getElement() {
  [1, 2, 3].forEach(function (element) {
    if (element % 2 == 0) {
      // возврат в функционал - .forEach,
      // но не выход из getElement
      alert('found: ' + element); // found: 2
      return element;
    }
  });
  return null;
}
alert(getElement()); // null, а не 2

x-yuri 29.01.2010 09:58

ну так здесь нету никакого завершения внешней функции из вложенной.

Kolyaj 29.01.2010 10:21

Dmitry A. Soshnikov,
че-та я тоже пример не понял.

Цитата:

Сообщение от Dmitry A. Soshnikov
null, а не 2

А почему должен быть 2?

Dmitry A. Soshnikov 29.01.2010 13:03

Цитата:

Сообщение от x-yuri
ну так здесь нету никакого завершения внешней функции из вложенной.

Зависит от реализаций, в данном случае читай - завершение функции getElement из двойного вложения: метода .forEach и функции-аргумента. В ES такое невозможно. В других языка (например, Smalltak) - возможно.

Цитата:

Сообщение от Kolyaj
Dmitry A. Soshnikov,
че-та я тоже пример не понял.
А почему должен быть 2?

Нет, не должен, конечно. Для ES должен быть, правильно, null. Но вопрос в том, что иногда это может быть удобно, и, что в других языках предусмотрены для этого конструкции.

Вот этот раздел: http://en.wikipedia.org/wiki/Closure...in_sema ntics (там пониже как раз примеры на Ruby с разными вариациями return-a приводится)

Но речь идёт только о возможном завершении стека вызова (когда контексты существуют); и в Ruby можно сделать ошибку return-a, когда он не сможет определить, в какой контекст возвращать.

x-yuri 29.01.2010 16:10

а можно увидеть, как эта функция на Ruby выглядела бы?

Dmitry A. Soshnikov 29.01.2010 17:28

Цитата:

Сообщение от x-yuri
а можно увидеть, как эта функция на Ruby выглядела бы?

Ну, для начала общий пример (из Википедии):

# ruby
def foo
  f = Proc.new { return "return from foo from inside proc" }
  f.call # control leaves foo here
  return "return from foo"
end

def bar
  f = lambda { return "return from lambda" }
  f.call # control does not leave bar here
  return "return from bar"
end

puts foo # prints "return from foo from inside proc"
puts bar # prints "return from bar"


Замыкания, порождаемые Proc.new - при return-e могут завершать контекст, в котором были порождены.

Замыкания, порождаемые функцией lambda - не могут.

Касаемо массива, метода .each и фунарга - я проверил, в версии 1.8.6 - и lambda, почему-то, завершает порождаемый контекст. В версии 1.9.1. это исправлено:

def test1
  fn = lambda {|x| return x}
  [1, 2, 3].each(&fn) # процедура передаётся с амперсандом
  return nil
end

def test2
  fn = Proc.new {|x| return x}
  [1, 2, 3].each &fn # скобки вызова - опциональны
  return nil
end

puts test1 # 1 - в 1.8.6, nil (правильно) - в 1.9.1
puts test2 # 1 - правильно


Есть ещё третий способ создать замыкание в Ruby - это блок кода (который можно преобразовать в процедуру). Различные методы (типа .each) как раз и используются с этими блоками кода.

def test3
  [1, 2, 3].each {|x| return x} # сразу описываем блок кода
  nil # слово return - тоже опциональное
end

puts test3 # 1 - при использовании блока, тоже выход из порождающего контекста

x-yuri 29.01.2010 20:20

интересно... По поводу js я бы сделал так (поиск первого элемента, удовлетворяющего условию)
function getElement() {
    return [1, 2, 3].findFirst(function( element ) {
        return element % 2 == 0;
    });
}

alert(getElement());

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

Как я понял, return в замыкании, созданном с помощью Proc.new завершает функцию, в которой было создано замыкание. И использовать его, за пределами этой функции смысла не имеет

может еще какие-нибудь примеры использования Proc.new есть? Т.е. на данный момент я вижу, что это можно использовать для поиска первого элемента

Цитата:

Сообщение от Dmitry A. Soshnikov
Ну, для начала общий пример (из Википедии):

не додумался в статью про замыкания заглянуть

Dmitry A. Soshnikov 30.01.2010 01:28

Цитата:

Сообщение от x-yuri
Хотя это уже, конечно, "предварительное" мнение

Ага, привычка к конкретной технологии, анализ через её призму. В Ruby же это описывается в доках, так что, для тех, кто изначально изучал Ruby - это не будет казаться чем-то странным.

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

Цитата:

Сообщение от x-yuri
Как я понял, return в замыкании, созданном с помощью Proc.new завершает функцию, в которой было создано замыкание. И использовать его, за пределами этой функции смысла не имеет

Да, но это касается только ключевого слова return. Proc.new выходит из метода. Если вызвать Proc.new с "return" вне метода, будет ошибка - "неожиданный return".

fn = Proc.new {|x| return x}
fn.call 10 # ошибка

fn1 = Proc.new {|x| x}
fn1.call 10 # 10

def foo
  fn = Proc.new do |x| # альтернативная запись блока {...} == do...end
    return x
  end
  fn.call 10
  return 'сюда не дошли'
end

foo # 10


Есть ещё несколько случаев, когда return из Proc.new завершится с ошибкой (когда контекст уже мёртв, когда вызывается в другом треде, др.)

Вообще, можно выделить даже не 3, а целых 7 способов создать замыкания в Ruby (но они будут сводиться к 3-ём; остальные 4 - вариации/комбинации предыдущих).

Цитата:

Сообщение от x-yuri
может еще какие-нибудь примеры использования Proc.new есть? Т.е. на данный момент я вижу, что это можно использовать для поиска первого элемента

Ну, не первого, а любого/группы (и не обязательно поиска). Придумай другие примеры ;)

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

Нравится тебе это или нет, хочешь ли ты от этого отгородиться или нет, решил ли ты для себя, что это нужно/не нужно: это есть (в некоторых языках) и разработано с конкретной целью ;)

x-yuri 30.01.2010 01:57

Цитата:

Сообщение от Dmitry A. Soshnikov
Иногда это удобно, но в ES такой возможности нет.

ключевое слово иногда. Причем тем, кому оно надо, спрашивать вряд ли будут, потому что и так знают. В общем, в таких случаях вариантов ответа не много, имхо ;)

Dmitry A. Soshnikov 30.01.2010 11:58

Цитата:

Сообщение от x-yuri
ключевое слово иногда

Нет, это моё слово было (в моём предложении). Кому-то, может, это всегда удобно.

x-yuri 30.01.2010 17:39

Цитата:

Сообщение от Dmitry A. Soshnikov
Кому-то, может, это всегда удобно.

ну может и есть такие люди, но мы же не будем брать пример с кого попало ;)

Dmitry A. Soshnikov 30.01.2010 19:17

Ну, здесь я уже не смогу помочь. Я рассказал и объяснил, как есть: что с этим делать тебе и как тебе к этому относиться - решать только тебе ;)

А то, что есть такой механизм и, что он существует независимо от того, понимаешь ли/принимаешь ли ты его, и что фраза в данном случае "не надо этого хотеть" - неверна - это истина.

Цитата:

Сообщение от x-yuri
но мы же не будем брать пример с кого попало

Это твоё видение и твоё мнение, меня не причисляй :no: (данная фраза для меня является демагогией).

x-yuri 30.01.2010 21:35

Цитата:

Сообщение от Dmitry A. Soshnikov
А то, что есть такой механизм и, что он существует независимо от того, понимаешь ли/принимаешь ли ты его, и что фраза в данном случае "не надо этого хотеть" - неверна - это истина.

я не говорил никогда. Я говорил, что надо учитывать реальную проблему человека, а не формально отвечать на вопрос

Цитата:

Сообщение от Dmitry A. Soshnikov
Это твоё видение и твоё мнение, меня не причисляй (данная фраза для меня является демагогией).

я говорил о тех, которые всегда используют Proc.new, и никогда lambda. Потому что это либо фанатизм, либо пофигизм

Dmitry A. Soshnikov 30.01.2010 22:37

Цитата:

Сообщение от x-yuri
я не говорил никогда. Я говорил, что надо учитывать реальную проблему человека, а не формально отвечать на вопрос

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

Кстати, однозначные призывы "есть суп ложкой" тоже можно нарушать с целью экспериментов от устоявшихся паттернов (ну, естественно, для этого должны быть обоснованные мотивации).

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

Цитата:

Сообщение от x-yuri
я говорил о тех, которые всегда используют Proc.new, и никогда lambda. Потому что это либо фанатизм, либо пофигизм

Мне показалось, говоря о "ком попало", ты говоришь о людях, которые могут вообще использовать return для выхода из вложенной функции, завершая внешнюю. Если я не так понял, извини.

Там есть ещё различия. Например, Proc.new (в отличие от lambda) не проверяет точное количество параметров (что также может быть удобно в определённых случаях).

Если интересно - вот исходник на Ruby (выполненный даже больше в виде статьи) о замыканиях - http://innig.net/software/ruby/closures-in-ruby.rb - достаточно подробно описаны различные случаи (можешь сохранить, читать в редакторе с подсветкой, скрипт полностью рабочий и запускаемый).


Часовой пояс GMT +3, время: 22:47.