BASIC functions to save/restore all variables
Thomas Milius (7848) 116 posts |
Nothing urgent and there are really more important things to do but in my opinion it would be nice to This would offer the ability to write simple programs with the possibility to interrupt nearly at an arbitrary place and continue after a while without worrying to save and restore relevant variables in detail. |
Theo Markettos (89) 919 posts |
Wouldn’t you need to save the stack too, to allow you to restart in the middle of a function/procedure? Also any interactions with the OS might need to be redone (eg if you open a file or allocate a block in RMA, next time the file/block won’t be open/allocated and you’d need to redo it, getting a different handle back). If there’s any memory pointers involved, you’d need to make sure they weren’t disturbed too. eg if you save when END is at a particular place, your variables will have addresses in the range END to HIMEM. If you reload with a larger program size, now END has moved upwards – so now all the pointers you reloaded are wrong. You can fix up the base of the memory block (ie DIM blk% 100 – just change blk%), but anything that has already stored the old value of blk% is going to be in trouble (eg blk%!42 = blk%+20) |
David J. Ruck (33) 1636 posts |
Isn’t it just a case of writing out a file containing lines of the form variable=valuethen reading back and feeding the line to EVAL . You would only do this for the variables you are interested in, to avoid the pitfalls for trying to restore everything that Theo mentions.
|
Chris Hall (132) 3558 posts |
Isn’t it just a case of saving and loading the variable storage area? For example
|
David J. Ruck (33) 1636 posts |
It will end in tears. |
Alan Adams (2486) 1149 posts |
I can see a use for that when debugging. I’m a lot less sure about trying to restore them. It does however occur to me that there might well be local and global variables with the same names. So it might require scope:variable=name, where scope is the name of the function/procedure where the local value applies. |
Chris Hall (132) 3558 posts |
LOCAL variables will only exist during the relevant function (and any functions it calls) the value held in the global variable will be on the stack until the function returns when it will overwrite whatever value the ‘local version’ of the variable was holding. So there is only ever one value in the variable concerned. |
Clive Semmens (2335) 3276 posts |
Exactly! This is something I remember causing pupils problems way back in the days when I was teaching. People often think that a local variable ought to be still there the next time a function is called – no it won’t. Then if the function calls another function that has another local variable of the same name, they get confused about the fact that the global variable and the first local variable will be on the stack, and that you get the first local variable back when the second function returns, and the global one back when the first function returns. Nested as deep as you like (within obvious rather generous limits…) |
Rick Murray (539) 13850 posts |
Yup, there’s that eccentricity that local isn’t really local as it applies to the current function and any it calls. So it’s more like “from this point on, until we’re done here”.
That gets people in C as well, to be fair. Usually local variables are stuck into the stack, so they are no longer viable once the function exits (but if you grab it immediately it’s still there, so you can return a local variable but you must copy it right away as the next app function you call will blat the stack). If you want a local variable that is persistent, it must be declared with
Useful for local loop counters, as long as you’re only using your own local loop variable, you can safely call ’em Aside: Bloody hell, a hornet that was buzzing around the roof just discovered the main powered bug zapper. It lost, but it put up a hell of a fight. I think the thing crackled for a good fifteen to twenty seconds as the hornet tried to fight back. Okay, where were we? Oh, yes, the local being “from here on”. Is there any other language that behaves like this? C usefully has multiple degrees of visibility. There are globals (that have to be specifically declared as not static and elsewhere as extern). Sweet. ;) Why am I talking about C? Well, because BASIC’s locals are kinda weird so it’s a comparison with a language that’s also decades old (so has grown a beard too), rather than some Trendy Toddler like Mojo. |
Rick Murray (539) 13850 posts |
It’s a shame one can’t do something like LVAR#file% to output the contents of LVAR to a file. |
Chris Hall (132) 3558 posts |
Yup, there’s that eccentricity that local isn’t really local as it applies to the current function and any it calls. If you write a function which is rather long and want to call other functions you don’t want it to forget local variables. So if you have a function DEFFNcomplex(a%,b%,c%) with LOCAL variables d% and e% you might want to use PROCstrip to replace repeated chunks of code and which uses d% and e% as parameters for some calcs without worrying about the senility of the language. ABCBasic fails miserably here! |
Steve Fryatt (216) 2105 posts |
Are you saying that ABC can’t do
I’m assuming that you’re not just treating |
Thomas Milius (7848) 116 posts |
As the discussion shows there are several aspects/levels to take into account. For my web server programs I am always ENDing at top level and I am starting always from beginning. An exact continuing immediately after the save is not necassary in !!! my !!! case, so there is no LOCAL problem for me. Of course saving and restoring variables of interest by program is possible but it will take quite high programming efforts to save and load all the variables. Also usage of a database would be a possibility. But we don’t have such a database at RISC OS in the moment and it will be always a perhaps oversized component more. Inbuild functions could be a bit more complex as my own concept in the moment. So perhaps it is worth to think about what could be achieved by parameters. I am not thinking about a 100% solution. E.g. it doesn’t make sense to keep file access open whilst the program belonging to it ends but it might be useful to note the related file names and positions. Parking of some data e.g. inside a dynamic area may be useful under certain circumstances. Of course this must not be saved and restored but the reference must be noted. |
Chris Hall (132) 3558 posts |
I’m assuming that you’re not just treating d% and e% as globals and relying on their LOCAL values from FNcomplex() remaining in scope inside nested calls to PROCstrip…? Wrong assumption. The problem with ABCBasic is that it is not compatible with BBC BASIC. It is poorly and carelessly written. |
Clive Semmens (2335) 3276 posts |
Nested as deep as you like And so many other purposes… Personally, I find it perfectly logical, the way BASIC works in this, and am surprised every time people react against it. The called functions have no reason to know or care whether variables in the calling function were global or local. When you enter a deeper level function, you don’t want to lose any of your variables; and why would the called function stack anything not declared local in the called function? There’s no reason it even needs to know it was called from a function rather than from the top level – indeed the same function might be called either way equally well. |
Rick Murray (539) 13850 posts |
Likewise, apart from a few special cases there should be no reason that a function needs to know about a variable that it wasn’t explicitly passed…
On the other hand, having a global variable replaced by a local variable in a function and then worrying which will be used in another function is the very definition of mindscrewy programming. I’d place it over there with GOSUB spaghetti. |
Clive Semmens (2335) 3276 posts |
But you don’t have to worry about anything. It’ll always be the one current in the calling function. The idea that you have to pass every variable that a function (or procedure) will use could end up with horribly long calls with loads of variables. The point of having specifically passed variables is that you’re not passing the variable: you’re passing the current value of the variable into a local variable. I wouldn’t place it with GOTO spaghetti, which really is HORRIBLE. I don’t even know what GOSUB spaghetti is, never come across GOSUB. It’s just a different way of looking at things, I think. |
Rick Murray (539) 13850 posts |
Read this PDF and cry. It’s the Adventure Game book from here: https://usborne.com/gb/books/computer-and-coding-books |
Chris Hall (132) 3558 posts |
there should be no reason that a function needs to know about a variable that it wasn’t explicitly passed… What a bizarre thought! It would obviously need to be able to use, read and write any variables used in the function – many of them may be constants (there’s no distinction in BASIC) and may have LOCAL values. One programme uses a function or procedure to convert latitude and longitude to and from grid reference and the set of constants it uses changes in different parts of Ireland. They are therefore initialised to different values at various points in the programme. |
GavinWraith (26) 1563 posts |
These discussions about BASIC remind me of the doctrinal wars about the semantics of LISP sixty years ago. Both arose from pragmatic implementations (i.e. bodges) that were insufficiently analysed from a theoretical point of view beforehand. It was not until fifty years ago, with the introduction of Scheme, that the virtues of lexical scoping began to be universally appreciated, and adopted. Perhaps I am missing the point and not properly appreciating the smoke and thunder of these re-enactments of long gone battles. |
Rick Murray (539) 13850 posts |
You’re reading too much into what I said. Constants are one thing, but generally globals should be minimised where possible. Of course a function can make use of its own variables, anything else would be crazy. But it should never ever have to depend upon a variable defined local in an ancestor.
If it was only two or three different types of reference, I’d pass a flag to the function to select which, and keep the conversion entirely within the function and not be adjusting things at various other points.
Everybody has their own preferred coding style. Some of which are clearly wrong. 😜 At least, in BASIC, we don’t get to argue about where the braces should be placed, because that’s a whole different battlefield. |
Clive Semmens (2335) 3276 posts |
I don’t know of an argument to support that assertion in general. Depending on how a particular language works, it might make sense, but in general? I don’t see it. |
Paolo Fabio Zaino (28) 1882 posts |
I’ll admit that the BBC BASIC’s concept of LOCAL is one of the most confusing I have ever seen (and I code in many, many programming languages)… First, it’s not actually “local” to the function, it’s local to the call-stack!!! In other words a LOCAL variable exists from the point of creation down to the rest of the call stack, aka function A defines varX as local and then calls function B (well function B can see varX!) (Note: this creates the same spaghetti effect that GOTO instruction creates, completely invalidating the concept of PROC/FN, because why would we have explicit parameters declaration if then a child function would also use a LCOAL variable to a parent, which may NOT be defined if another function would call that child???) Second, BBC BASIC doesn’t have a STATIC concept, which is probably what a true BASIC LOCAL variable should be (there is plenty of letterature on how BASIC was concieved to understand this, one of the best source is “Back to BASIC” from John G. Kemeny and Thomas E. Kurtz) TLDR: The reason for this, is that BASIC was designed to mimic certain natural behaviours (mostly of math students) and because of this original paradigm, a BASIC local variable should actually be the equivalent of a C static variable (local to the function, but also remembered when calling the function back). The reason why a BBC BASIC local variable is instead a “temporary variable local to the call stack” is just for memory contraints on the original BBC Micro and to improve performance when people were doing bad coding practices. |
Paolo Fabio Zaino (28) 1882 posts |
And this is absolutely true :) Most of the reasons for the “semantic bizzardries” of BBC BASIC are down to Acorn trying to give “the best possible language given the extremely limited resources of the BBC Micro”. Aka, every thing was meant to be so for practical reasons. IIRC, Sophie mentioned this many times (included her hate for how certain things had to be developed). |
Paolo Fabio Zaino (28) 1882 posts |
Quick reminder that the GOTO war, was something that Dijikstra unvolutarly started. However he mentioned only “global goto” (to be clear, NOT local goto, aka the goto used in C). Global gotos creates tightly coupled blob of logic which is indeed a nightmare to maintain. GOSUB (or Go Subroutine), is foundamentaly the precursor of PROC, but still having only a global contex and so, while it’s sligthely better than a goto spaghetti, it still causes the same issues (plus involving the stack too! lol) To stay on BBC BASIC world, a local GOTO would help reducing the form of:
By having something more like:
Apollogies for the way too much simplified example, but having a clear exit point means if you need to free resources, you’ll be able to do so in your done_computing section and ensure that you’ll always be able to clean resources without having to write complex exit code every time you need to exit and, most of all, without having side effects from having more complex exit procedures. Obviously, someone may argue that this form is confusing for them, so there probably will never be one form fit them all solution. |