I've made an IDL procedure which is very simple and I'd like to use in my other codes. I've put the path in my directory and I can't see a name conflict anywhere.
When I try to run the procedure from another it tells me
!PATH=!PATH+':'+Expand_Path('+~/example/')
But when I try to find the procedure using "Findpro" I get
Procedure CHLOADCT found in directory /data/clh93/colortables/CH/
So my paths are right. I don't understand why it won't find my procedure, does anyone know what's going on?
Thanks!
Christina
Things to check in situations like this:
you are consistent about whether the routine is a function or procedure, i.e., routine is procedure and you are calling it as a procedure
routine you are calling is either compiled already or the last routine in a file named the same as it with a .pro extension; the case of the filename and routine call must match or the filename must be all lowercase (just use all lowercase in filenames!)
quick check to see if my_routine.pro is in your !path:
IDL> print, file_which('my_routine.pro')
It will return an empty string if it can't find it.
make sure the file is not in your !path twice and you are getting someone else's or an old version
Related
While learning about OpenEdge Progress-4GL, I stumbled upon running external procedures, and I just read following line of code, describing how to do this:
RUN p-exprc2.p.
For a person with programming experience in C/C++, Java and Delphi, this makes absolutely no sense: in those languages there is a bunch of procedures (functions), present in external files, which need to be imported, something like:
filename "file_with_external_functions.<extension>"
===================================================
int f1 (...){
return ...;
}
int f2 (...){
return ...;
}
filename "general_file_using_the_mentioned_functions.<extension>"
=================================================================
#import file_with_external_functions.<extension>;
...
int calculate_f1_result = f1(...);
int calculate_f2_result = f2(...);
So, in other words: external procedures (functions) mean that you make a list of procedures (functions), you put all of them and in case needed, you import that file and launch the procedure (function) when you need it.
In Progress 4GL, it seems you are launching the entire file!
Although this makes no sense at all in C/C++, Java, Delphi, I believe this means that Progress procedure files (extension "*.p") only should contain one procedure, and the name of the file is then the name of that procedure.
Is that correct and in that case, what's the sense of the PERSISTENT keyword?
Thanks in advance
Dominique
There are a lot of options to the RUN statement: https://documentation.progress.com/output/ua/OpenEdge_latest/index.html#page/dvref%2Frun-statement.html%23
But, in the simple case, if you just:
RUN name.p.
You are invoking a procedure. It might be internal, "super", "persistent" or external. It could also be an OS DLL.
The interpreter will first search for an internal procedure with that name. Thus:
procedure test.p.
message "yuck".
end.
run test.p.
Will run the internal procedure "test.p". A "local" internal procedure is defined inside the same compilation unit as the RUN statement. (Naming an internal procedure with ".p" is an abomination, don't do it. I'm just showing it to clarify how RUN resolves names.)
If a local internal procedure is not found then the 4gl interpreter will look for a SESSION SUPER procedure with that name. These are instantiated by first running a PERSISTENT procedure.
If no matching internal procedure or SUPER procedure is found the 4gl will search the PROPATH looking for a matching procedure (it will first look for a compiled version ending with .r) and, if found, will RUN that.
There are more complex ways to run procedures using handles and the IN keyword. You can also pass parameters and "compile on the fly" arguments. The documentation above gets into all of that. My answer is just covering a simple RUN name.p.
Progress was originally implemented as a procedural language which did it's thing by running programs. That's what you're seeing with the "run" statement.
If one was to implement this in OO, it'd look something like this:
NEW ProgramName(Constructor,Parameter,List).
Progress added support for OO development which does things in a way you seem more familiar with.
I have written a Fortran code for being compiled as a '*.DLL' file.
The program which reads that file is a Finite Elements Method software named Plaxis, I already achieved to generate the '*.DLL' file in Visual Studio and Plaxis recognizes my model but the model does not work fine.
I would like to evaluate all the variables involved in my code and the procedure that Plaxis is using to read them, but when I use commands like "write(*,*) 'variable'" Plaxis does not show me what I asked in the source code.
Probably you want to open a file and write to that for debug logging, because presumably Plaxis doesn't run with standard output connected to anything useful. Or maybe it would if you just ran Plaxis from a command line window?
It's not going to create a dialog box for you.
But anyway, another option would might be attach to Plaxis with a debugger, and set a breakpoint in a function in your DLL. Then you can single-step your code as called by Plaxis.
Or you can write your own test callers and write unit tests for your functions, making them easy to debug. This could work well if your function just gets an array + size as args.
If instead it passes some wrapped object that you need to call special functions to deal with, then maybe make another version of your function that does just take an array so you can call it from a simple test caller.
I have a problem. When the program reads a text file, it always get out of the line and crashed.
var f:text;
i,j,cs:byte;
a:array[0..10,0..10] of int64
begin
assign(f,'anything.txt');
reset(f);
cs:=0;
while eoln(f)=false do
begin
read(f,a[0,cs]);
inc(cs);
end;
close(f);
end.
Here is the content of anything.txt:
2 4 8 16
exitcode=201
You have not told us which compiler you are using.
In Delphi and Turbo Pascal which preceded it, run-time error 201 means "range check error". I don not still have Turbo Pascal installed but your program compiles and runs as a "console application" correctly in Delphi with only one minor change, namely to insert a semi-colon (';') after int64. It runs correctly whether the compiler has range-checking turned on or not.
It also runs correctly in FreePascal + Lazarus.
So, unless you are using a different compiler which also happens to have a run-time error code 201, your problem seems to be caused by something you have not included in your question. In any case you should learn to debug this kind of problem yourself. So:
Look up how to use use the debugger in your Pascal compiler. Place a breakpoint on the line inc(cs) e.g. by pressing F5and run the program. When it stops at the BP, place debug watches (using Ctrl-F5 in Delphi/TP) on the values of cs and a and observe the values carefully. Press F8 repeatedly to single step the program, and see if you can see where and why it goes wrong.
One possibility for what is causing your problem is that you are not reading the copy on anything.txt you think you are: because you don't include a path to the file in assign(f Windows will use the copy of anything.txt, if any, in whatever it thinks the current directory is. To avoid this, include the path to where the file is, as in
assign(f, 'C:\PascalData\Anything.Txt');
Also btw, you don't need to compare a boolean function (or expression) againt true or false as in
while eoln(f)=false do
Instead you can simply do
while not eoln(f) do
I've been working on a programme to solve any maximisation LPP using the Revised Simplex Method. I have a problem with it though as I'm trying to input a sequence to solve the problem of non-basic variables.
My code is as follows:
matmax:=proc(tableau,basic)
local pivot,T,nbv,n,m,b;
T:=evalm(tableau);
n:=coldim(T); m:=rowdim(T);
b:=evalm(basic);
print(evalm(T));
nbv:={seq(i,i=2..n-1)}minus{seq(b[i],i=1..m)};
pivot:=getpiv(T,nbv);
while not pivot=FAIL do
b[pivot[1]]:=pivot[2];
T:=evalm(gauss(col(T,pivot[2]),pivot[1])&*T);
print(evalm(T));
nbv:={seq(i,i=2,..n-1)}minus{seq(b[i],i=1..m)};
pivot:=getpiv(T,nbv);
od;
[evalm(T),evalm(b)];
end;
The gauss and getpiv commands are procedures written to work in this programme, these work fine. However upon executing this procedure Maple returns with the message "Error, (in matmax) unable to execute seq" If anyone can give me any help on how to fix this problem it would be greatly appreciated.
If you have not loaded the linalg package before calling your matxmax then commands like coldim will simplify not work and not produce the integer results for n and m that are expected when using those in the bound of the seq calls. I believe that is why your seq error occurs, because n and m are not being assigned integer intermediate results like you expect.
You could try to remedy this by either loading the package before calling matmax, with with(linalg). But that is not so robust, and there are scenarios where it might not work. The with command won't work within a procedure body, so you can't put that inside the defn of proc matmax.
You could insert a line into matmax above, say, the local declaration line, like,
uses linalg;
That would make coldim and friends from the linalg package work. Unfortunately you've used the name pivot as a local variable, and that clashes with the pivot export from linalg package. So that simple fix via uses is not quite enough. You could use some name other than pivot, and that simple uses line, sure.
My own preference would be to make everything fully explicit, so that later on you or anyone else reading the code can understand it more clearly, even if it's longer. So I would use linalg[coldim] instead of coldim, and so on for the other exports uses from the linalg package within matmax.
Having said all the above, you should know that the linalg package is deprecated in modern Maple and that LinearAlgebra is the new package that offers the functionality you seem to be using. The command names are longer, but using the newer package means that you don't need all those evalm calls (or anything like it).
The problem could lie in your gauss and getpiv commands as they may not work with your procedure, could you expand on what they do?
I have a clojure program that at some point executes a function called db-rebuild-files-table.
This function takes a directory filename as a single string argument and calls a recursive function that descends into the directory file tree, extracts certain data from the files there and logs each file in a mysql database. The end result of this command is a "files" table populated by all files in the tree under the given directory.
What I need is to be able to run this command periodically from the shell.
So, I added the :gen-class directive in the file containing my -main function that actually calls (db-rebuild-files-table *dirname*). I run lein uberjar and generate a jar which I can then execute with:
java -jar my-project-SNAPSHOT-1.0.0-standalone.jar namespace.containing.main
Sure enough, the function runs, but in the database there only exists a single entry, for the directory *dirname*. When I execute the exact same sexp in the clojure REPL I get the right behaviour: all the file tree under *dirname* get processed.
What am I doing wrong? Why does the call (db-rebuild-files-table *dirname*) behave inconsistently when called from the REPL and when executed from the command line?
[EDIT] Whats even weirder is that I get no error anywhere. All function calls seem to work as they should. I can even run the -main function in the REPL and it updates the table correctly.
If this works in the REPL, but not when executed stand-alone, then I would guess that you may be bitten by the laziness of Clojure.
Does your code perhaps need a doseq in order to get the benefits of a side-effect (e.g. writing to your database)?
Nailed it. It was a very insidious bug in my program. I got bitten by clojure's laziness.
My file-tree function used map internally, and so produced just the first value, the root directory. For some reason I still can't figure out, when executed at the REPL, evaluation was actually forced and the whole tree seq was produced. I just added a doall in my function and it solved it.
Still trying to figure why executing something at the REPL forces evaluation though. Any thoughts?