К сожалению, если я правильно понимаю ошибки компилятора, я не могу использовать этот же синтаксис в F #.Итак, поскольку она не поддерживается изначально, как я могу реализовать команду goto в F #?
Как сказал Даниэль, метка и следующий блок инструкций могут быть преобразованы в функцию иего тело.Тогда каждый goto
становится вызовом функции.Вы должны передать все локальные переменные в качестве аргументов, потому что отдельные функции имеют разные области видимости, и вы должны добавить сквозные вызовы из одного блока инструкций в следующий при необходимости.Однако хвостовые вызовы являются более общей концепцией.
Ваш пример цикла start
становится следующим:
let rec start () = // .start
start() // goto start
Обратите внимание, что приличный компилятор фактически скомпилирует этот эквивалентный высокоуровневый код обратно вjump
/ branch
между блоками команд в ассемблере.Основное отличие состоит в том, что стековые фреймы должны быть реорганизованы, потому что вы можете выполнять вызов между совершенно разными средами.
Кроме того, я считаю, что F #, как один из языков в парадигме функционального программирования, должен бытьспособен поддерживать gotos более высокого уровня: где вы можете передавать gotos gotos.
Да, действительно.Вы не можете передавать метки на других языках, но вы можете передавать функции в F # как в качестве аргументов в вызовах функций, так и в качестве возвращаемых значений из функций.Другие языки, такие как Fortran, предлагают вычисленные goto
как промежуточный дом.
Обратите внимание, что асинхронное программирование является важным практическим применением этой техники.Когда вы вызываете асинхронную функцию, вы сообщаете ей, где она должна перейти, когда она завершится.Например, когда вы звоните, чтобы начать асинхронную загрузку веб-страницы, вы передаете ей функцию, которую она будет вызывать, как только станут доступны данные (по сути, аппаратное прерывание, полученное, когда поступает последняя из ваших данных, в конечном итоге срабатывает с вашего максимума).-уровень управляемого кода для работы со свежими данными, что довольно круто).Современные языки дают вам инструменты для написания высокоуровневого асинхронного кода многократного использования, комбинируя эти goto
-подобные методы с дополнительной генерацией кода во время компиляции.В других языках, таких как C #, вы облажались, потому что хотите обернуть несколько асинхронных вызовов в один try..catch
, но не можете, потому что они фактически распределены по множеству различных функций.