I have a function (FunctionA) that is being called by another function (FunctionB). The problem is, I'm not sure which function "FunctionB" is.
I have this snippet of code:
function FunctionA():void {
trace("This function was called by " + ???);
}
I need to figure out what to put for "???" so FunctionA's trace statement looks like this:
This function was called by FunctionB
What should I put for "???"?
An idea that comes to mind is looking at the current stack trace. The entry before the currently executing method should be the routine that called in to FunctionA.
Example
(This is for ActionScript 3.0 but I'm pretty sure it should be available in previous versions)
I don't think stack trace is available in AS2.
For each possible call site, add the line
arguments.callee.__caller="somestr";
where somestr is unique.
In function A
trace(arguments.caller.__caller);
In response to comment:
I guess theoretically, you could walk the _global object recursively looking for functions and tagging them.
I'm assuming that you aren't using the Flash IDE? This has a debugger (fairly slow and bad), but it should give you a stack trace (if memory serves me right)
Related
I want to build a class in Raku. Here's what I have so far:
unit class Vimwiki::File;
has Str:D $.path is required where *.IO.e;
method size {
return $.file.IO.s;
}
I'd like to get rid of the size method by simply making my class inherit the methods from IO::Path but I'm at a bit of a loss for how to accomplish this. Trying is IO::Path throws errors when I try to create a new object:
$vwf = Vimwiki::File.new(path => 't/test_file.md');
Must specify a non-empty string as a path
in block <unit> at t/01-basic.rakutest line 24
Must specify a non-empty string as a path
I always try a person's code when looking at someone's SO. Yours didn't work. (No declaration of $vwf.) That instantly alerts me that someone hasn't applied Minimal Reproducible Example principles.
So I did and less than 60 seconds later:
IO::Path.new
Yields the same error.
Why?
The doc for IO::Path.new shows its signature:
multi method new(Str:D $path, ...
So, IO::Path's new method expects a positional argument that's a Str. You (and my MRE) haven't passed a positional argument that's a Str. Thus the error message.
Of course, you've declared your own attribute $path, and have passed a named argument to set it, and that's unfortunately confused you because of the coincidence with the name path, but that's the fun of programming.
What next, take #1
Having a path attribute that duplicates IO::Path's strikes me as likely to lead to unnecessary complexity and/or bugs. So I think I'd nix that.
If all you're trying to do is wrap an additional check around the filename, then you could just write:
unit class Vimwiki::File is IO::Path;
method new ($path, |) { $path.IO.e ?? (callsame) !! die 'nope' }
callsame redispatches the ongoing routine call (the new method call), with the exact same arguments, to the next best fitting candidate(s) that would have been chosen if your new one containing the callsame hadn't been called. In this case, the next candidate(s) will be the existing new method(s) of IO::Path.
That seems fine to get started. Then you can add other attributes and methods as you see fit...
What next, take #2
...except for the IO::Path bug you filed, which means you can't initialize attributes in the normal way because IO::Path breaks the standard object construction protocol! :(
Liz shows one way to workaround this bug.
In an earlier version of this answer, I had not only showed but recommended another approach, namely delegation via handles instead of ordinary inheritance. I have since concluded that that was over-complicating things, and so removed it from this answer. And then I read your issue!
So I guess the delegation approach might still be appropriate as a workaround for a bug. So if later readers want to see it in action, follow #sdondley's link to their code. But I'm leaving it out of this (hopefully final! famous last words...) version of this answer in the hope that by the time you (later reader) read this, you just need to do something really simple like take #1.
Example:
data class T(val flag: Boolean) {
constructor(n: Int) : this(run {
// Some computation here...
<Boolean result>
})
}
In this example, the custom constructor needs to run some computation in order to determine which value to pass to the primary constructor, but the compiler does not accept the run, citing Cannot access 'run' before superclass constructor has been called, which, if I understand correctly, means instead of interpreting it as the non-extension run (the variant with no object reference in https://kotlinlang.org/docs/reference/scope-functions.html#function-selection), it construes it as a call to this.run (the variant with an object reference in the above table) - which is invalid as the object has not completely instantiated yet.
What can I do in order to let the compiler know I mean the run function which is not an extension method and doesn't take a scope?
Clarification: I am interested in an answer to the question as asked, not in a workaround.
I can think of several workarounds - ways to rewrite this code in a way that works as intended without calling run: extracting the code to a function; rewriting it as a (possibly highly nested) let expression; removing the run and invoking the lambda (with () after it) instead (funnily enough, IntelliJ IDEA tags that as Redundant lambda creation and suggests to Inline the body, which reinstates the non-compiling run). But the question is not how to rewrite this without using run - it's how to make run work in this context.
A good answer should do one of the following things:
Explain how to instruct the compiler to call a function rather than an extension method when a name is overloaded, in general; or
Explain how to do that specifically for run; or
Explain that (and ideally also why) it is not possible to do (ideally with supporting references); or
Explain what I got wrong, in case I got something wrong and the whole question is irrelevant (e.g. if my analysis is incorrect, and the problem is something other than the compiler construing the call to run as this.run).
If someone has a neat workaround not mentioned above they're welcome to post it in a comment - not as an answer.
In case it matters: I'm using multi-platform Kotlin 1.4.20.
Kotlin favors the receiver overload if it is in scope. The solution is to use the fully qualified name of the non-receiver function:
kotlin.run { //...
The specification is explained here.
Another option when the overloads are not in the same package is to use import renaming, but that won't work in this case since both run functions are in the same package.
I have a small question in my mind. I researched it on the Internet but no-one is providing the exact answer. My question is:
In data flow coverage criteria, say there is a method which finally returns variable x. When drawing the graph for that method, is that return statement considered to be a use of x?
Yes, a return statement uses the value that it returns. I couldn't find an authoritative reference that says so in plain English either, but here are two arguments:
A return statement passes control from one part of a program to another, just like a method call does. The value being returned is analogous to a function parameter. return therefore is a use just like being a function parameter is a use.
The other kind of use in data flow analysis is when a value leaves the program and has some effect on the outside world, for example by being printed. If we're analyzing a method, rather than an entire program, return causes the value to leave the scope which we're analyzing. So it's a use for the same reason that printing is a use.
I'm making a batch development kit in visual basic and i need to be able to call a function that sets textboxes to a saved files text. How do i do this without returning? I tried this, and it lets me run the program, but gives me a warning, not an error. How do i go about doing this? Here is my little function design. P.S. I recently switched back to VB from Java and i'm so used to doing public void. Thanks in advance!
Public Function loadProject()
End Function
You want a Sub, which is the equivalent to the Java void method.
Public Sub LoadProject()
End Sub
It's not a bad Idea to just have a function that returns a value like a success statement just in case you need it. A call to the function doesn't have to accept or use the return value from the function.
You could even build a class with two values - txtpreviousvalue and txtnewvalue
Have your function return that type and fill an instance of the type with the respective values.
One day, if you need it, you'll have it.
P.S. I'm only posting this as an answer because the good answer posted by sstan is not marked as the answer; You should probably do that.
I'm trying to get the referring method in vb.net.
e.g. I have 1 generic method (sendMail) that handle's emails, any other method can call this. I want sendMail to log an entry to the database when it sends an email. In this log i want the name of method that calls sendMail. I can do it by passing paramaters but I would like to know if sendMail can access the name of the method that calls it.
I found this article that works great in vs
Is it possible to get the referring method in VB.NET?
but unfortunately i'm working in a proprietary application and their IDE and the output I get from StackFrame is 'ExecuteAction at offset 1438 in file:line:column :0:0 '. I think it might be because the StackFrame used in example by Jon works in debug mode not release. (MSDN said something about debug mode but i'm not 100% sure here)
Is there another way of getting the calling method name?
Or am I using StackFrame incorrectly?
Cheers in advance.
dno
public string GetStackTrace()
{
StackTrace st = new StackTrace(true);
StackFrame[] frames = st.GetFrames();
return frames[1].GetMethod().Name.ToString();
}
give it a try:
this method will most likely return the name of its caller, with a few adjustment, you cant tweak it to nest back by increasing the index of the frames array.
good luck