Return from a subroutine - vbscript

I want to write a subroutine for working out what to do and then returning.
Before you jump on the "A subroutine that returns is a function LOL!" bandwagon, I want the return to be executed as it were in the function body calling the subroutine, as though I've got a preprocessor to do the substitution, because otherwise this codebase is going to get unwieldy really fast, and returning the return value of a function seems kludgy.
Will vb (sorry I can't be more specific about what version- I'm writing formulas for an embedded system, our API docs are "it runs vb") let me do that or fall in a heap?

I want the return to be executed as it were in the function body calling the subroutine, as though I've got a preprocessor to do the substitution, because otherwise this codebase is going to get unwieldy really fast, and returning the return value of a function seems kludgy.
It's not. Tail-calls are a common practice that work just fine.
They are much preferable than having a function that cannot ever be called unless you want to return its value.

It sounds like you are asking whether C/C++ style macros can be implemented in VB, the answer is no. You could possibly fake it though by generating vbscript, and substituting the right things in.
Lambdas and delegates in VB.Net are not really the same thing as what you are asking for - if my interpretation is correct.

Related

Refactor eval(some_variable).is_a?(Proc) to not use eval

I have some old code that looks like:
some_variable = "-> (params) { Company.search_by_params(params) }"
if eval(some_variable).is_a?(Proc)
...
Rubocop is complaining about the use of eval. Any ideas on how to remove the usage of eval?
I don't really understand Procs so any guidance on that would be appreciated.
Simple. Don't define your variable object as a string but as a lambda Proc
my_lamda = -> (params) { Company.search_by_params(params) }
if my_lambda.is_a?(Proc)
#do stuff
end
But why would you instantiate a string object which contains what appears to be a normal lambda which is a Proc, when you can define a Proc instead?
I am going to answer the question "If I want to run code at a later time, What is the difference between using a proc and a eval'd string?" (which I think is part of your question and confusion):
What eval does is take a string and parses it to code, and then runs it. This string can come from anywhere, including user input. But eval is very unsafe and problematic, especially when used with raw user input.
The problems with eval are usually:
There is almost always a better way to do it
Very dangerous and insecure
Makes debugging difficult
Slow
Using eval allows full control of the ruby process, and if you have high permissions given to the ruby process, potentially even root acmes to the machine. So the general recommendation is use 'eval' only if you absolutely have no other options, and especially not with user input.
Procs/lambdas/blocks also let you save code for later, (and solve most of the problems with eval, they are the "better way") but instead of storing arbitrary code as a string to read later, they are code already, already parsed and ready to go. In someways, they are methods you can pass around later. Making a proc/lambda gives you an object with a #call method. Then when you later want to run the proc/block/lambda, you call call([arguments...]). What you can't do with procs though is let users write arbitrary code (and generally that's good). You have to write the code for the proc in a file ruby loads (most of the time). Eval does get around that, but you really should rethink if you really want that to be possible.
Your code sample oddly combines both these methods: it evaluates a string to a lambda. So what's happening here is eval is running the code in the string right away and returning the (last) result, which in this case happens to be a lambda/proc. (Note that this would happen every time you ran eval, which would result in multiple copies of the proc, with different identities, but the same behavior). Since the code inside the string happens to make a lambda, the value returned is a Proc which can later be #call'd. So when eval is run, the code is parsed, and a new lambda is created, with the code in the lambda stored to be run at a later time. If the code inside the string did not create a lambda, the all that code would be run immediately when eval was called with the string.
This behavior might be desired, but there is probably a better way to do this, and this is definitely a foot-gun: there are at least a half dozen subtle ways this code could do unintended things if you weren't really careful with it.

Is it better to give a function an additional parameter, or to make the parameter static?

Many times I've come across a situation where I am calling a method many times with one parameter always exactly the same, and I need to add some additional parameter defined in my main method. I'm never sure what to do about the additional parameter. It seems like it might be a better idea to make the parameter static to make the code cleaner, but then, static variables are not very good. Still, adding parameters can in some cases lead to very long lists of parameters that are in a way unnecessary, and I imagine that there will be a speed disadvantage as well when your function is short, called often, and has a lot of parameters.
Here's the most recent code (kotlin) that has had me thinking about this problem, but I've ran into the problem a lot in different languages.
tailrec fun getAncestor(ind: Int, parent: IntArray): Int {
if (parent[ind] == ind) return ind else return getAncestor(parent[ind], parent);
}
Is it better to make parent a static variable and not have it as a parameter to the method? (Assume that every time that this method is called, the second parameter will be the same. I'm usually only writing short 100 line code files for competitive programming so there is no chance the method will be reused with a different second parameter)
In general if you're working on a project, you'll want to stay away from static variables because when the project starts scaling up and getting bigger, it'll be very hard to keep track of the static variables and this will make it very hard to debug.
In competitive programming, I suggest go for the quicker approach.
In my opinion, it depends on your preferred coding paradigm. For instance, if you'd like your code to conform to the functional paradigm, your code is fine how it is now (regarding the parameter), however, if you don't care about the functional programming, having that param extracted out, as a constant is alright. I see no reason why it should be bad. If you worry about the performance, you could declare it as lazy, but otherwise it'd fine, I guess.

Fortran, Meaning of Unary* operator in function calls?

I am attempting to make modifications to an old fortran code to get it to handle a slightly different binary input file format. In the process of doing this I have been encountering * used in a unary fashion. For example, this code found within a loop:
CALL EVENT1(QDRBUF(IPNTR+EVTHSZ),EVTSIZ,EVTID,
- *11000,*10000,*80000)
There are other cases as well but as far as I have seen / remember it is only in function calls. What is this doing?
I'm not a Fortran guy, but this question intrigued me, so I did some looking. It appears to be an alternate return specifier. The number after the asterisk is a label that can be used in place of a normal return, almost like catching an exception.

How to keep only one return statement in a function?

Despite the discussion here, Should a function have only one return statement?, are there some simple tips or method to keep only one return statement? Or how to refactor a multiple return statement to a only one return statement?
First of all it is not clear why you want to do this as in the thread it is already mentioned that this feature was added in modern languages due to some reasons and to allow the user to get more functionality.
The wiki says a lot on it:
Some people make sure each function has a single entry, single exit
(SESE). These people argue that The use of a return statement violates
structured programming: it is an unstructured exit from the function,
resulting in multiple exit points, rather than the single exit point
required by structured programming. It has thus been argued[5] that
one should eschew the use of the explicit return statement except at
the textual end of a subroutine, considering that, when it is used to
"return early", it may suffer from the same sort of problems that
arise for the GOTO statement. Conversely, it can be argued that using
the return statement is worthwhile when the alternative is more
convoluted code, such as deeper nesting, harming readability.
Other people say that one or more "guard clauses" -- conditional
"early exit" return statements near the beginning of a function --
often make a function easier to read than the alternative.[6][7][8][9]
The most common problem in early exit is that cleanup or final
statements are not executed – for example, allocated memory is not
unallocated, or open files are not closed, causing leaks. These must
be done at each return site, which is brittle and can easily result in
bugs. For instance, in later development, a return statement could be
overlooked by a developer, and an action which should be performed at
the end of a subroutine (e.g., a trace statement) might not be
performed in all cases. Languages without a return statement, such as
standard Pascal don't have this problem. Some languages, such as C++
and Python, employ concepts which allow actions to be performed
automatically upon return (or exception throw) which mitigates some of
these issues – these are often known as "try/finally" or similar.
Ironically, functionality like these "finally" clauses can be
implemented by a goto to the single return point of the subroutine. An
alternative solution is to use the normal stack unwinding (variable
deallocation) at function exit to unallocate resources, such as via
destructors on local variables, or similar mechanisms such as Python's
"with" statement.
But even then if you want to achieve the Single entry and Single exit functionality then the best way to do is to get invalid cases out of the way first, either simply exiting or raising exceptions as appropriate, put a blank line in there, then add the "real" body of the method.
Also check Where did the notion of “one return only” come from?

What is the most obfuscated code you've had to fix?

Most programmers will have had the experience of debugging/fixing someone else's code. Sometimes that "someone else's code" is so obfuscated it's bad enough trying to understand what it's doing.
What's the worst (most obfuscated) code you've had to debug/fix?
If you didn't throw it away and recode it from scratch, well why didn't you?
PHP OSCommerce is enough to say, it is obfuscated code...
a Java class
only static methods that manipulates DOM
8000 LOCs
long chain of methods that return null on "error": a.b().c().d().e()
very long methods (400/500 LOC each)
nested if, while, like:
if (...) {
for (...) {
if (...) {
if (...) {
while (...) {
if (...) {
cut-and-paste oriented programming
no exceptions, all exceptions are catched and "handled" using printStackTrace()
no unit tests
no documentation
I was tempted to throw away and recode... but, after 3 days of hard debugging,
I've added the magic if :-)
Spaghetti code PHP CMS system.
by default, programmers think someone else's code is obfuscated.
The worse I probably had to do was interpreting what variables i1, i2 j, k, t were in a simple method and they were not counters in 'for' loops.
In all other circumstances I guess the problem area was difficult which made the code look difficult.
I found this line in our codebase today and thought it was a nice example of sneaky obfuscation:
if (MULTICLICK_ENABLED.equals(propService.getProperty(PropertyNames.MULTICLICK_ENABLED))) {} else {
return false;
}
Just making sure I read the whole line. NO SKIMREADING.
When working on a GWT project, I would reach parts of GWT-compiled obfuscated JS code which wasn't mine.
Now good luck debugging real obfuscated code.
I can't remember the full code, but a single part of it remains burned into my memory as something I spend hours trying to understand:
do{
$tmp = shift unless shift;
$tmp;
}while($tmp);
I couldn't understand it at first, it looks so useless, then I printed out #_ for a list of arguments, a series of alternating boolean and function names, the code was used in conjunction with a library detection module that changed behaviour if a function was broken, but the code was so badly documented and made of things like that which made no sense without a complete understanding of the full code I gave up and rewrote the whole thing.
UPDATE from DVK:
And, lest someone claims this was because Perl is unreadable as opposed to coder being a golf master instead of good software developer, here's the same code in a slightly less obfuscated form (the really correct code wouldn't even HAVE alternating sub names and booleans in the first place :)
# This subroutine take a list of alternating true/false flags
# and subroutine names; and executes the named subroutines for which flag is true.
# I am also weird, otherwise I'd have simply have passed list of subroutines to execute :)
my #flags_and_sub_names_list = #_;
while ( #flags_and_sub_names_list ) {
my $flag = shift #flags_and_sub_names_list;
my $subName = shift #flags_and_sub_names_list;
next unless $flag && $subName;
&{ $subName }; # Call the named subroutine
}
I've had a case of a 300lines function performing input sanitization which missed a certain corner case. It was parsing certain situations manually using IndexOf and Substring plus a lot of inlined variables and constants (looks like the original coder didn't know anything about good practices), and no comment was provided. Throwing it away wasn't feasible due to time constraints and the fact that I didn't have the specification required so rewriting it would've meant understanding the original, but after understanding it fixing it was just quicker. I also added lots of comments, so whoever shall come after me won't feel the same pain taking a look at it...
The Perl statement:
select((select(s),$|=1)[0])
which, at the suggestion of the original author (Randal Schwartz himself, who said he disliked it but nothing else was available at the time), was replaced with something a little more understandable:
IO::Handle->autoflush
Beyond that one-liner, some of the Java JDBC libraries from IBM are obfuscated and all variables and functions are either combinations of the letter 'l' and '1' or single/double characters - very hard to track anything down until you get them all renamed. Needed to do this to track down why they worked fine in IBM's JRE but not Sun's.
If you're talking about HLL codes, once I was updating project written by a chinese and all comments were chinese (stored in ansii) and it was a horror to understand some code fragments, if you're talking about low level code there were MANY of them (obfuscated, mutated, vm-ed...).
I once had to reverse engineer a Java 1.1 framework that:
Extended event-driven SAX parser classes for every class, even those that didn't parse XML (the overridden methods were simply invoked ad hoc by other code)
Custom runtime exceptions were thrown in lieu of method invocations wherever possible. As a result, most of the business logic landed in a nested series of catch blocks.
If I had to guess, it was probably someone's "smart" idea that method invocations were expensive in Java 1.1, so throwing exceptions for non-exceptional flow control was somehow considered an optimization.
Went through about three bottles of eye drops.
I once found a time bomb that had been intentionally obfuscated.
When I had finally decoded what it was doing I mentioned it to the manager who said they knew about the time bomb but had left it in place because it was so ineffective and was interwoven with other code.
The time bomb was (presumably) supposed to go off after a certain date.
Instead, it had a bug in it so it only activated if someone was working after lunchtime on Dec 31st.
It had taken three years for that circumstance to occur since the guy who wrote the time bomb left the company.

Resources