Jump to content

Get lost in subroutines


ReFran
 Share

Recommended Posts

Hi,

in a bigger script with many subroutines and batches I get lost in all the nested subroutines, also if I use - at least mostly - return 0/1 (sucess/no ..).

I would like to use a command like "restart", which will clear the subroutine stack and let me simple recall the main while loop.

Did I overlook a statement like that?

best regards, Reinhard

Link to comment
Share on other sites

Hi,

in a bigger script with many subroutines and batches I get lost in all the nested subroutines, also if I use - at least mostly - return 0/1 (sucess/no ..).

I would like to use a command like "restart", which will clear the subroutine stack and let me simple recall the main while loop.

Did I overlook a statement like that?

best regards, Reinhard

AutoIt doesn't have stacks or subroutines as such. GOTO has been demolished since early versions too.

Put your main loop in a function and then when you need to restart, just re-call the function.

Link to comment
Share on other sites

  • Moderators

ReFran,

Be very careful recalling the main function like that without unwinding all the function calls. It is known as recursion and can lead you into big trouble extremely quickly with stack overflows if you continually call a function again before it has ended. :(

The only real solution to your problem is to write your code such that you do unwind all the function calls and get back to the idle loop before you restart you main function again. :D

One way to do this is to use the return values you tell us you have used. Every time you call a new function, test for the return value and exit the current function if the wrong value is returned. This script should give you the idea:

Func_1()

ConsoleWrite("Back Here!" & @CRLF)

Func Func_1()

    If Func_2() Then
        ConsoleWrite("Continuing with Func_1" & @CRLF)
        Return 1
    Else
        Return 0
    EndIf

EndFunc

Func Func_2()

    If Func_3() Then
        ConsoleWrite("Continuing with Func_2" & @CRLF)
        Return 1
    Else
        Return 0
    EndIf

EndFunc

Func Func_3()

    If Func_4() Then
        ConsoleWrite("Continuing with Func_3" & @CRLF)
        Return 1
    Else
        Return 0
    EndIf

EndFunc

Func Func_4()

    If Func_5() Then
        ConsoleWrite("Continuing with Func_4" & @CRLF)
        Return 1
    Else
        Return 0
    EndIf

EndFunc

Func Func_5()

    If Random() > 0.5 Then
        ConsoleWrite(1 & @CRLF)
        Return 1
    Else
        ConsoleWrite(0 & @CRLF)
        Return 0
    EndIf

EndFunc

If the random number in the final function is > .5, all the functions run their payload code - if not they all return and you unwind right back to the beginning with no code executed other than the instant returns from each function.

Does that help? :graduated:

M23

Public_Domain.png.2d871819fcb9957cf44f4514551a2935.png Any of my own code posted anywhere on the forum is available for use by others without any restriction of any kind

Open spoiler to see my UDFs:

Spoiler

ArrayMultiColSort ---- Sort arrays on multiple columns
ChooseFileFolder ---- Single and multiple selections from specified path treeview listing
Date_Time_Convert -- Easily convert date/time formats, including the language used
ExtMsgBox --------- A highly customisable replacement for MsgBox
GUIExtender -------- Extend and retract multiple sections within a GUI
GUIFrame ---------- Subdivide GUIs into many adjustable frames
GUIListViewEx ------- Insert, delete, move, drag, sort, edit and colour ListView items
GUITreeViewEx ------ Check/clear parent and child checkboxes in a TreeView
Marquee ----------- Scrolling tickertape GUIs
NoFocusLines ------- Remove the dotted focus lines from buttons, sliders, radios and checkboxes
Notify ------------- Small notifications on the edge of the display
Scrollbars ----------Automatically sized scrollbars with a single command
StringSize ---------- Automatically size controls to fit text
Toast -------------- Small GUIs which pop out of the notification area

 

Link to comment
Share on other sites

Hello ReFran

Sometimes I run accross a section of script that I want a goto point made and I use a While Loop. In this example you will see that if a certain condition is present, it will continue the loop, kinda like a goto. A cleaner way without Recursion. Or ExitLoop if a condition is met and you don't want the rest of that section of script to run. Then setting the Loops condition to false if I need the rest of the section to run, but end aftwards.

$running = 1
While $running
    ;do something
    If $check_Condition = False Then ContinueLoop
    ;do something
    If $check_Other_Condition = True Then ExitLoop
    ;do something
    If $check_Another_Condition = True Then $running = 0
    ;do something
WEnd

Just adding my 2 cents :graduated:

Realm

Edit: Fixed typos

Edited by Realm

My Contributions: Unix Timestamp: Calculate Unix time, or seconds since Epoch, accounting for your local timezone and daylight savings time. RegEdit Jumper: A Small & Simple interface based on Yashied's Reg Jumper Function, for searching Hives in your registry. 

Link to comment
Share on other sites

Hi,

that is the answer I was afraid of.

Means I have to check my script/subs for all the cases I was not consequent enough with the return codes.

The script controls a java-app on a citrix server.

So in a simple task functions I have to call many check functions and finally I set up a batch function, which operates different task function, perhaps in connection with some helper/tool functions (e.g. getPeriods from 01-10).

And that grows from year to year. Because I write/insert the batch function may be some month later it's hard to remember where the used functions end.

"... Does that help?"

Yes, also if I would prefer the answer from James.

Thanks, Reinhard

Link to comment
Share on other sites

Thanks Realm (I'm not so quick with writing - especially on work),

with all the batches and checks I can't avoid Recursion complete.

However it seems,

I've to check the script, revising some loops, flatten the structure, ...which sounds like real work

or wait on the rerecusion / reunwind statement.

Best regards, Reinhard

Link to comment
Share on other sites

Just looking quickly at this thread, I've the feeling that this is to land in a production professional context (Citrix and such). I may be mis-interpreting things, but if in such context, the very least is to use a professional approach and structure the code clearly/cleanly enough so that you and your successors will have no issue maintaining the baby. Any single hour spent on making things as they should be in the first place is 10 or 50 hours or even more saved in the future.

This wonderful site allows debugging and testing regular expressions (many flavors available). An absolute must have in your bookmarks.
Another excellent RegExp tutorial. Don't forget downloading your copy of up-to-date pcretest.exe and pcregrep.exe here
RegExp tutorial: enough to get started
PCRE v8.33 regexp documentation latest available release and currently implemented in AutoIt beta.

SQLitespeed is another feature-rich premier SQLite manager (includes import/export). Well worth a try.
SQLite Expert (freeware Personal Edition or payware Pro version) is a very useful SQLite database manager.
An excellent eBook covering almost every aspect of SQLite3: a must-read for anyone doing serious work.
SQL tutorial (covers "generic" SQL, but most of it applies to SQLite as well)
A work-in-progress SQLite3 tutorial. Don't miss other LxyzTHW pages!
SQLite official website with full documentation (may be newer than the SQLite library that comes standard with AutoIt)

Link to comment
Share on other sites

My $0.02 as well: it may sound hard to believe when you are up to your waist in old code... But even though it might seem like a total no-go, it is Almost Always worth the trouble to (don't faint! :graduated:) .... *cough* start all over again *cough*. This has multiple advantages:

1) You know beforehand what you want to accomplish and how all parts of the script should work together so you will be able to think ahead

2) You will almost definitely discover bugs or buggy approaches in your old script and think *HOW COULD I HAVE BEEN SO STUPID, this can be done so much more efficiently* while hitting your forehead :(

3) You will learn a lot and avoid thinking errors or shortsightedness that lead to these inconsistent approaches

4) You will, with almost 100% certainty, have a way better script, that is way more extendable, reusable, readable, maintainable, commented etc.

The only downside is that is costs time, but believe me: if you plan on writing more scripts in the future (and especially if you plan on writing more extensions to this one) you will be HAPPY that you have a better script and a better understanding to work with it.

What I hear here is someone who started a script of 10 lines, which proved so incredibly useful that he got pushed by very enthousiastic colleagues/friends to write more code and extend it to 40 lines with more functionality, which in turn made even more people happy, which inspired even more added code, which finally spiralled out of control. Tell me that I'm wrong! :D Been there, done that! :D The total recall was for me often time consuming but always life saving. (Which reminds me of the following paragraph of Jon in the "History of AutoIt and Developers" (from the Helpfile):

September 1999 - May 2001

Numerous versions and number of functions increasing at a massive rate. Basically, if someone asked for a function I stuck it in there. The problems this caused is why we don't give in all the time any more.

)

Just my $0.02.

/edit: some typos.

/edit 2: just noticed your post count and forum subscription date... Occured to me that I may have come across as somewhat patronizing. Not indended!

Edited by SadBunny

Roses are FF0000, violets are 0000FF... All my base are belong to you.

Link to comment
Share on other sites

I fully agree with SadBunny.

I created an automation script to dial into our 86 branches, restart a service and then move on to the next.

At first I hard-coded every branch mnemonic and number into an array since it was only supposed to be a quicky. Within the same week I add:

  • Version comparison of the service to the latest compiled application
  • Date differencing so that the service is only restarted if it last "phone-homes" around 2 or more hours before the script is running
  • Emails the IT department
  • Remove hard-coded branch array and in place add a dynamic database-driven array creation function
  • Log file
It's crazy and I've been through several incarnations after making each update, fine tuning the little details.

James

Link to comment
Share on other sites

I believe that the first solution James gave to you is more appealing because it would be an easy way out ... temporarily. What everyone told you here is entirely true, been writing scripts for my team for more than 3 years now and I have a good idea about what that means. Going back to re-write code, add features, improve existing ... all happens very often. And very often a very quick and simple script will evolve into a coding beast.

My advice - listen to what Melba23 told you - bad recursive calls can land your script in a mess in a matter of miliseconds. In a production environment I am pretty sure you will want to avoid that.

I know it's difficult to re-write all error handling part but you need to do it. That will teach you a lesson of planning ahead, you will start to add error control structure automatically when you write your code.

I remember a proverb: "Any kick in the back is a step forward." - not always true but it is in this case :graduated:

SNMP_UDF ... for SNMPv1 and v2c so far, GetBulk and a new example script

wannabe "Unbeatable" Tic-Tac-Toe

Paper-Scissor-Rock ... try to beat it anyway :)

Link to comment
Share on other sites

What I would try in your situation, and I havent tested this.

First open your script in scite4autoit, tools/add func trace lines.

That will put a line to consolewrite something at the begging of every function in the script.

Here comes the part I would be on the forum asking for help with.. regexp.

Make a regexp pattern to replace all those lines with something like

If $999 Then Return

All the trace lines end with ";### Function Trace" so would'nt be to hard I'd hope.

Have a hotkey to set your emergency flag $999/$911 to true/false to bring your script to heel.

If that makes any sense. It couls be a load of rubbish.

AutoIt Absolute Beginners    Require a serial    Pause Script    Video Tutorials by Morthawt   ipify 

Monkey's are, like, natures humans.

Link to comment
Share on other sites

I think JohnOne's idea is actually a creative and workable quick fix to the problem, but it does rely on all global variables to be resetted properly, otherwise you risk functions reusing values from before the "restart".

If you do implement such a non-standard construction into a program that others might have to maintain I'd make sure to document it clearly though.

Link to comment
Share on other sites

Something tells me JohnOne is on crack or alike Posted Image

haha

I thought it may have been unworkable, the idea was to just have any and all functions just return immediately, bringing it back to the first function and staying there until the global flag id reset(assuming there is a main loop)

See Tvern has got the faith, thanks pal :graduated:

Edited by JohnOne

AutoIt Absolute Beginners    Require a serial    Pause Script    Video Tutorials by Morthawt   ipify 

Monkey's are, like, natures humans.

Link to comment
Share on other sites

I thought it may have been unworkable, the idea was to just have any and all functions just return immediately, bringing it back to the first function and staying there until the global flag id reset(assuming there is a main loop)

I meant, I didn't fully understand your idea.

Firstly, why use a regular expression? They require a fair bit more thinking time (in code) which increases the speed of which the application runs at.

Also, even adding a $999 or $911 variable will require the OP to add checks around his code, alas, shouldn't he just write the correct error handling whilst he's at it?

Link to comment
Share on other sites

Firstly, why use a regular expression? They require a fair bit more thinking time (in code) which increases the speed of which the application runs at.

I believe he wanted to use a regexp on the actual script to replace trace lines with the line: "If $999 Then Return", as an easy way to get the line everywhere in the script. However I believe they should not only be put at the top of each function, but above each line in the function. (by replacing trace lines, instead of func trace lines) as otherwise you run the risk of calling functions without valid arguments.

Adding an If statement for each line might have a noticable effect on performance and will double the size of the script though.

Link to comment
Share on other sites

Hi,

Reviewing the script, I think the general structure is OK.

But I don't have in every function return codes and in the main loop I don't check some return codes (because I introduced it later). Perhaps I should use a global variable as "doneWell" switch, so I can ask every time for the state.

Also I found 2 task functions which works - more or less - already as batch-jobs. Putting batch-jobs onto batch-jobs was really not a good idea. So I've to change that.

Thanks for all the tips and hints.

Best regards, Reinhard

PS: The script is only for me and some colleagues. It automate some functions of a Java-App on a citrix-server and gather some infos from a MS-SQL-Server, which is the basic of the java-app. Unfortunately our IT-guys don't want me to influence the data on the SQL-Server directly.

My "official work task" is at time, to manage the revising of a professional written program. That is only 2 years old, discussed and planned in a big project group, but overrun from the reality. Never thought that I would have the chance (??) to learn TCL-scripting, which is used in that program.

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...