Тема: AHK: В чем "злость" Goto?
И так , история началась с того что мне сказали , что Goto - зло. Но никто так и не объяснил почему.
И чем же тогда пользоваться если не goto?
Вы не вошли. Пожалуйста, войдите или зарегистрируйтесь.
Страницы 1
Чтобы отправить ответ, вы должны войти или зарегистрироваться
И так , история началась с того что мне сказали , что Goto - зло. Но никто так и не объяснил почему.
И чем же тогда пользоваться если не goto?
Скажем, если заголовок правильно оформите.
Вроде правильно оформил
GoTo не зло.
Хотя использование команды Goto как правило не одобряется, ее можно применить внутри функции, чтобы перейти на другую позицию внутри той же самой функции, что может помочь упростить большие функции, имеющие много точек возврата, каждая из которых перед возвратом должна сделать некоторую зачистку.
А в общих случаях: Continue, Break.
Хотя мне иногда удобнее и нагляднее использовать GoTo, чем цикл:
YoutubeUpload:
oIE.navigate("https://www.youtube.com/upload")
While oIE.readyState != 4 || oIE.document.readyState != "complete" || oIE.busy
Sleep, 10
text := oIE.document.documentElement.InnerText
If InStr(text, "This page can’t be displayed")
GoTo, YoutubeUpload
exobangs, в goto нет никакого криминала.
Я такой же вопрос задал лет 15 назад. И отмахнулся от всех наставлений, поскольку они показались мне несколько надуманными. Своё мнение я изменил, когда написал первый код длиной более 12-15 экранов. Нет, пока я его писал все было в порядке. А вот когда нужно было ввести правку через месяц, вот тогда и я согласился, что goto - зло.
И что комментарии не стоит ленится писать тогда же понял. Потом в 5 раз больше времени уйдёт, чтобы понять что ты видишь перед собой вообще, чем на написание короткого комментария.
Так это зло не goto, а длиннющих портянок кода.
А в функции да, очень удобно бывает. Если то же делать через if/else, получается более громоздко.
Так это зло не goto, а длиннющих портянок кода.
А как вы боретесь с портянками?
Дроблением кода на функции?
Ну, если целеустремлённо этим заниматься, то разобраться с этим будет скорее всего не проще чем с портянкой. Иногда какой-то параметр так "закапывается", что пока пройдёшь все функции, из которых он возникает, забудешь что искал.
Сколько уже копий сломано по поводу этого несчастного оператора... Вот годная статья, как ни странно, в защиту goto. Комментарии тоже доставляют.
exobangs, использование goto может быть оправдано, но не два же оператора из пяти.))
Ну, если целеустремлённо этим заниматься, то разобраться с этим будет скорее всего не проще чем с портянкой.
Почему? Если имена функций говорят о том, что они делают, то логика программы будет легче пониматься (или вспоминаться).
Иногда какой-то параметр так "закапывается", что пока пройдёшь все функции, из которых он возникает, забудешь что искал.
Это как? Что за параметр, возникающий из функций?
Хотя мне иногда удобнее и нагляднее использовать GoTo, чем цикл:
YoutubeUpload: oIE.navigate("https://www.youtube.com/upload") While oIE.readyState != 4 || oIE.document.readyState != "complete" || oIE.busy Sleep, 10 text := oIE.document.documentElement.InnerText If InStr(text, "This page can’t be displayed") GoTo, YoutubeUpload
По-моему, так гораздо нагляднее:
Loop {
oIE.navigate("https://www.youtube.com/upload")
While oIE.readyState != 4 || oIE.document.readyState != "complete" || oIE.busy
Sleep, 10
text := oIE.document.documentElement.InnerText
} until !InStr(text, "This page can’t be displayed")
Единственная причина, по которой твой вариант кажется тебе более наглядным, это то, что ты пока плохо понимаешь синтаксис AHK. Код, заключённый в скобки, лучше выделяется визуально, парные скобки можно подсветить в редакторе, код между скобками можно свернуть. Всего этого не сделать с метками.
Вот годная статья, как ни странно, в защиту goto. Комментарии тоже доставляют.
А вот её опровержение.
Имхо, в AHK использование GoTo всегда можно заменить на более наглядный вариант. Внутри функций можно поступать так:
Loop 1 {
if (условие)
break
...
...
if (условие)
break
Loop { ; если есть вложенные циклы, тогда так:
...
if (условие)
break 2
}
}
; продолжение кода
Я так и не увидел самих фактов , но если же есть сторонники которые против Goto , подскажите , как реализовать без Goto?
Вот код для примера
Loop {
Start:
ComObjError(false)
HTTP := ComObjCreate("WinHTTP.WinHTTPRequest.5.1")
HTTP.Open("GET", "http://microsoft.com")
HTTP.Send()
if (HTTP.ResponseText = "")
Goto, Start
else
Fileappend, Интернет есть., CheckInternet.txt
}
ComObjError(false)
HTTP := ComObjCreate("WinHTTP.WinHTTPRequest.5.1")
HTTP.Open("GET", "http://microsoft.com")
Loop {
HTTP.Send()
if (HTTP.ResponseText = "")
continue
Fileappend, Интернет есть., CheckInternet.txt
}
А лучше так:
Loop {
if !Ping("www.microsoft.com")
continue
Fileappend, Интернет есть., CheckInternet.txt
}
Ping(strHost)
{
Return ComObjGet("winmgmts:").Get("Win32_PingStatus.address='" . strHost . "'").StatusCode = 0
}
teadrinker, ну код я приводил для примера , но суть в том что мне нужно возвращатся к началу , если интернета нету.
Но наверное до меня долго доходит (туговато) , с применением ваших примеров.
мне нужно возвращатся к началу
Оператор continue как раз и возвращает к началу цикла. Изучайте синтаксис.
Единственная причина, по которой твой вариант кажется тебе более наглядным, это то, что ты пока плохо понимаешь синтаксис AHK. Код, заключённый в скобки, лучше выделяется визуально, парные скобки можно подсветить в редакторе, код между скобками можно свернуть. Всего этого не сделать с метками.
А если там несколько возможных возвратов к метке, то без GoTo получится цикл в цикле цикла.
И этот вариант:
Loop {
oIE.navigate("https://www.youtube.com/upload")
While oIE.readyState != 4 || oIE.document.readyState != "complete" || oIE.busy
Sleep, 10
text := oIE.document.documentElement.InnerText
} until !InStr(text, "This page can’t be displayed")
мне кажется менее наглядным чем этот:
Loop
{
oIE.navigate("https://www.youtube.com/upload")
While oIE.readyState != 4 || oIE.document.readyState != "complete" || oIE.busy
Sleep, 10
text := oIE.document.documentElement.InnerText
if !InStr(text, "This page can’t be displayed")
break
}
А если там несколько возможных возвратов к метке, то без GoTo получится цикл в цикле цикла.
Лучше на примере, так неясно.
мне кажется менее наглядным чем этот
Они равнозначны, только первый короче. В плане наглядности — просто дело привычки.
Это как? Что за параметр, возникающий из функций?
Сам я так не делаю, но разок копался в чужом коде, чтобы понять как осуществляется одно, интересующее меня действие. Нашёл по оператору функцию в которой это действие производилось, потом нашёл переменные от которых оно зависело, перешёл к функциям, которые определяли эти переменные. В них то же самое, пошёл к следующей функции. И так где-то до глубины в 7-8 функций.
Когда вышел в "начало", уже совершенно потерял преставление, что на что влияет и сама "цепочка" действий из головы высыпалась.
Foma, может тут не в функциях проблема, а в беспорядочно составленном коде?
Вообще-то все циклы это условие и переход (goto). Есть безусловные переходы (JMP) и условные (JZ, JA и т д.), не знаю, AHK компилятор как-то оптимизирует их или нет.
Так что с точки зрения компилятора goto будет даже более практичным.
не знаю, AHK компилятор как-то оптимизирует их или нет
Так что с точки зрения компилятора goto будет даже более практичным.
Вижу противоречие между первым и вторым высказываниями. Если нужна скорость выполнения, то вообще AHK бессмысленно использовать.
Лучше на примере, так неясно.
PasteBin:
oIE.navigate("http://pastebin.com/index/0ivKzH0R")
loop
{
text := oIE.document.documentElement.InnerText
If InStr(text, "This page can’t be displayed")
GoTo, PasteBin
text := oIE.document.querySelector("#paste_code").outerText
If text !=
break
sleep, 100
}
RegexMatch(text, "(^.*?\R)", name)
Description := RegExReplace(text, "(^.*?\R)")
DetectHiddenWindows, On
YoutubeUpload = 1
YoutubeUpload:
if YoutubeUpload = 1
{
UploadFile := "G:\RITS\youtube\astrolog.mpg"
oIE.navigate("https://www.youtube.com/signin?feature=masthead_switcher&next=`%2Fupload&authuser=1&action_handle_signin=true&skip_identity_prompt=False")
}
if YoutubeUpload = 2
{
UploadFile := "G:\RITS\youtube\utroLTV7.mpg"
CloseProcess("iexplore.exe")
oIE := ComObjCreate("InternetExplorer.Application")
oIE.visible := True, oIEHWND := oIE.HWND
WinMaximize ahk_id %oIEHWND%
oIE.navigate("https://www.youtube.com/signin?feature=masthead_switcher&next=`%2Fupload&skip_identity_prompt=False&pageid=110507430261645574853&authuser=0&action_handle_signin=true")
}
While oIE.readyState != 4 || oIE.document.readyState != "complete" || oIE.busy
Sleep, 10
text := oIE.document.documentElement.InnerText
If InStr(text, "This page can’t be displayed")
GoTo, YoutubeUpload
FileDelete, WinWait.ahk
FileAppend,
(
#NoTrayIcon
WinWait, Choose File to Upload
loop
{
ControlSetText, Edit1, "%UploadFile%", Choose File to Upload
ControlClick, Button1, Choose File to Upload,,,, NA
WinWaitClose, Choose File to Upload,,5
if ErrorLevel != 1
ExitApp
}
), WinWait.ahk
Run, WinWait.ahk
WinWait, WinWait.ahk
oIE.document.querySelector("span[class=""init-upload-action-icon yt-sprite""]").click()
WinWaitClose, WinWait.ahk
FileDelete, WinWait.ahk
if YoutubeUpload = 2
{
oIE.document.querySelector("input[name=""title""]").value := name1
oIE.document.querySelector("textarea[name=""description""]").value := description
}
oIE.document.querySelector("button[class=""yt-uix-button yt-uix-button-size-default save-changes-button yt-uix-tooltip yt-uix-button-primary""]").click()
loop
{
text := oIE.document.documentElement.InnerText
if InStr(text, "1 of 1 uploaded") and (YoutubeUpload = 1)
{
YoutubeUpload = 2
GoTo, YoutubeUpload
}
if InStr(text, "1 of 1 uploaded") and (YoutubeUpload = 2)
break
sleep, 100
}
oIE.Quit
Malcev, адЪ!
loop
{
oIE.navigate("http://pastebin.com/index/0ivKzH0R")
text := oIE.document.documentElement.InnerText
if InStr(text, "This page can’t be displayed")
continue
text := oIE.document.querySelector("#paste_code").outerText
if (text != "")
break
sleep, 100
}
Код неверен.
Зачем каждый раз делать oIE.navigate("http://pastebin.com/index/0ivKzH0R")?
В моем коде туда идет переход только в случае:
if InStr(text, "This page can’t be displayed")
Код неверен.
Ну, так это и говорит о том, что в постоянных прыжках туда-сюда без поллитра не разберёшься.
oIE.navigate("http://pastebin.com/index/0ivKzH0R")
loop
{
text := oIE.document.documentElement.InnerText
If InStr(text, "This page can’t be displayed") {
oIE.navigate("http://pastebin.com/index/0ivKzH0R")
continue
}
text := oIE.document.querySelector("#paste_code").outerText
If text !=
break
sleep, 100
}
_gruz пишет:не знаю, AHK компилятор как-то оптимизирует их или нет
_gruz пишет:Так что с точки зрения компилятора goto будет даже более практичным.
Вижу противоречие между первым и вторым высказываниями. Если нужна скорость выполнения, то вообще AHK бессмысленно использовать.
Первое - про конкретно AHK компилятор, второе - обобщенное понятие.
АНК как раз и должна быть оптимизирована для скорости и малого объема, т.к. в реальном времени должна обрабатывать и реагировать на события. Конечно я понимаю, что мат. вычисления это не к AHK но тем не менее, что есть то есть.
Имхо, главное, чтоб сам автор кода разбирался.
И я лично по метке сразу вижу, что речь идет о Pastebin.
А как ты бы изменил код под меткой YoutubeUpload из 23 поста?
Имхо, главное, чтоб сам автор кода разбирался.
Это если публиковать не собирается.
И я лично по метке сразу вижу, что речь идет о Pastebin.
Есть комментарии.
А как ты бы изменил код под меткой Youtube из 23 поста?
Примерно так:
global oIE
DetectHiddenWindows, On
YoutubeUpload = 1
Upload(YoutubeUpload)
Loop
{
While oIE.readyState != 4 || oIE.document.readyState != "complete" || oIE.busy
Sleep, 10
text := oIE.document.documentElement.InnerText
If InStr(text, "This page can’t be displayed") {
Upload(YoutubeUpload)
continue
}
CreateScript(YoutubeUpload)
if YoutubeUpload = 2
{
oIE.document.querySelector("input[name=""title""]").value := name1
oIE.document.querySelector("textarea[name=""description""]").value := description
}
oIE.document.querySelector("button[class=""yt-uix-button yt-uix-button-size-default save-changes-button yt-uix-tooltip yt-uix-button-primary""]").click()
loop
{
text := oIE.document.documentElement.InnerText
if InStr(text, "1 of 1 uploaded") {
if (YoutubeUpload = 1 && YoutubeUpload := 2)
break
else
break 2
}
sleep, 100
}
}
oIE.Quit
Upload(var)
{
if (var = 1)
oIE.navigate("https://www.youtube.com/signin?feature=masthead_switcher&next=`%2Fupload&authuser=1&action_handle_signin=true&skip_identity_prompt=False")
else if (var = 2) {
CloseProcess("iexplore.exe")
oIE := ComObjCreate("InternetExplorer.Application")
oIE.visible := True, oIEHWND := oIE.HWND
WinMaximize ahk_id %oIEHWND%
oIE.navigate("https://www.youtube.com/signin?feature=masthead_switcher&next=`%2Fupload&skip_identity_prompt=False&pageid=110507430261645574853&authuser=0&action_handle_signin=true")
}
}
CreateScript(var)
{
UploadFile := (var = 1 ? "G:\RITS\youtube\astrolog.mpg" : "G:\RITS\youtube\utroLTV7.mpg")
FileDelete, WinWait.ahk
FileAppend,
(
#NoTrayIcon
WinWait, Choose File to Upload
loop
{
ControlSetText, Edit1, "%UploadFile%", Choose File to Upload
ControlClick, Button1, Choose File to Upload,,,, NA
WinWaitClose, Choose File to Upload,,5
if ErrorLevel != 1
ExitApp
}
), WinWait.ahk
Run, WinWait.ahk
WinWait, WinWait.ahk
oIE.document.querySelector("span[class=""init-upload-action-icon yt-sprite""]").click()
WinWaitClose, WinWait.ahk
FileDelete, WinWait.ahk
}
Возможно, где-то есть ошибки, но главный принцип — последовательность — сохранён.
Foma, может тут не в функциях проблема, а в беспорядочно составленном коде?
Тогда дело именно в порядке? Как в "портянке", так и в наборе функций разобраться одинаково просто, если код не "беспорядочно составлен".
На самом деле, GOTO — это единственный оператор, который используется для управления выполнением кода этими вашими центральными процессорами. Для всякого ЦП есть в сущности два способа управлять кодом: условный оператор (если да, то выполнить следующую команду, иначе выполнить послеследующую) и перейти на другой участок кода (GOTO). Всё. И все эти ваши процедурное программирование, функциональное программирование, ООП, ААП, замыкания, циклы и прочая синтаксическая ересь — после компиляции превращается в сотни, тысячи, миллионы GOTO (а точнее, в JMP, JE, JLE, JGE, JNE, etc.), я гарантирую это! Несогласные goto 30.
(GoTo, http://lurkmore.to/GOTO)
Тогда дело именно в порядке? Как в "портянке", так и в наборе функций разобраться одинаково просто, если код не "беспорядочно составлен".
В общем да. Но ведь мы как раз и говорим, что GoTo нарушает порядок, прыгая в самые непредсказуемые места. Что касается портянки — всё же понимание кода повышается, если он разделён на логические блоки, такие, как функции и подпрограммы, и эти блоки не превышают размера одного экрана.
всё же понимание кода повышается, если он разделён на логические блоки, такие, как функции и подпрограммы, и эти блоки не превышают размера одного экрана.
Ну, блоки и подпрограммы, тут спора нет, а вот про "размер одного экрана" для них, как-то не задумывался. Посмотрел - абсолютное большинство в один-два укладывается. Надо будет подумать над тем, чтобы дробить мельче, но не в ущерб наглядности. Так как я её понимаю.
Ну, так это и говорит о том, что в постоянных прыжках туда-сюда без поллитра не разберёшься.
В моем случае прыжек идет только в начало кода посвященного конкретному действию.
Это если публиковать не собирается.
Александр_, помню опубликовал:
http://forum.script-coding.com/viewtopi … 302#p56302
Есть комментарии.
В них отпадает нужда в моем случае с меткой.
Примерно так:
Мне твой вариант более награможденным кажется.
И все эти ваши процедурное программирование, функциональное программирование, ООП, ААП, замыкания, циклы и прочая синтаксическая ересь — после компиляции превращается в сотни, тысячи, миллионы GOTO (а точнее, в JMP, JE, JLE, JGE, JNE, etc.), я гарантирую это!
А call и ret куда делись? А loop?
Александр_, помню опубликовал:
Так там у него Goto только вниз (последовательность не нарушается), нет выпрыгиваний из циклов. В данном случае это Goto, Clear равнозначно использованию Return в функции или break в цикле.
Мне твой вариант более награможденным кажется.
Ну, тут ничего не поделаешь. Показаться что угодно может.
Моё первое знакомство с подробным описанием "GoTo" впервые произошло на страницах учебника "Visual C# 2008. Базовый курс", где этому оператору как и всем остальным технологиям был посвящён ознакомительный раздел. Там, это столкновение субъективных версий выражено менее экспрессивно, нежели любые иные источники в интернетах включая эту беседу, не отбирая у процесса познания его конструктивной нити. Главная особенность этого оператора позволяющая "нырять" в теле сценария в любом направлении, плохо понимающему задачу поставленную перед собой даёт иллюзорное ощущение контроля над своим "детищем", всё более превращая его труд в бессмысленный набор символов с увеличением количества переходов. "GoTo" - это путь наименьшего сопротивления приводящий в эквивалентный тупик, как и любое другое описание кода в неумелых руках, уводящее кодера от вожделенной развязки. Разница правда в том, что пользование остальных технологий формирует рамки, в пределах которых существует их "зона ответственности", а "GoTo" не только их не имеет, но и нарушает. И напротив, в "GoTo" нет никакой опасности, как нет опасности в скальпеле в руках хирурга, или резце скульптора, если конечная форма его применения видна заблаговременно. "GoTo" - это запятая в "Казнить нельзя помиловать", ставить которую неправильный поступок, если не представляешь последствий. Лучше использовать другие сочетания слов, чаще окажущиеся не менее обоснованными. А новичкам он "мешает думать". Лишает возможности чувствовать тонкости экспериментов к которым направленно их стремление, потому что - "...метка перехода в конкретный момент течения мысли обеспечивает выполнение следующего необходимого действия, описание которого уже произошло некоторыми строками ранее/позднее..." Код может и будет живуч, будет выполнять требуемые операции, но это будет как раз тот самый показательный опыт жизни, к которому будет апеллировать подсознание только лишь потому, что он оказался удачным, а не закономерным, не рассматривая при этом разницы последнего.
После прочтения той статьи я перестал пользоваться "GoTo". Без него стало труднее, но только потому лишь, что приходилось думать головой, в попытке понять - "как устроен велосипед". Не могу похвастаться богатством опыта, но сейчас просто не представляю для чего он вообще нужен. Наверняка есть какие-то случаи, когда переход к метке будет оправдан, или даже необходим, но мне они пока не встречались. Более того, прерывание циклов в AHK может происходить в одном месте до любого уровня вложенности указанием через запятую после "break" необходимого значения(например: break, 3), что по своей сути ставит свою красивую, лаконичную точку в очень весомом принципе, на который часто ссылаются оппозиционеры движения "Против GoTo".
Но право применения тех или иных технологий, конечно же остаётся за Вами, уважаемый читатель. Если у Вас хватило терпения дочитать этот текст до сего момента, то, вероятно, Ваше любопытство ищет наиболее верное решение, а не просто свет в конце тоннеля.
Страницы 1
Чтобы отправить ответ, вы должны войти или зарегистрироваться