I've written a function which contains a list of sub functions to evaluate. I have a try-catch statement around this block of sub functions so that if one of them throws an error the catch statement will ensure that the variables the subfunctions return will just be set to text messages.
Example Subfunction (working as expected)
function f(x)
SQRT = sqrt(x)
return SQRT
end
f(9) #returns the square root of a positive number
> 3.0
f(-9) #error when you try to take the square root of a negative number
> LoadError: DomainError: while loading In[80], in expression
starting on line 1 in f at In[76]:2
Example Main Function with try-catch statement (not working as expected)
function g(y)
a=[]
b=[]
try
a=f(y)
b="works"
catch
a="no"
b="no"
end
return a,b
end
g(9)
> (3.0,"works")
g(-9)
> LoadError: DomainError: while loading In[96], in expression
starting on line 1 in f at In[76]:2
I understand that the error is correct when I use f(x) since I haven't used a try-catch statement. However I'm expecting that the try-catch statement would catch this error when f(y) is evaluated inside of g(y) and would return a = "no" and b = "no". Why is the try-catch statement not picking this error up and working as expected?
Is there a way to get this statement to work? I need it to work this way to avoid putting try-catch statements into all of the many subfunctions I have written. In this example it would be easy to just insert the try-catch into f(x) and the problem would be solved as per below, but I don't want to do this in my real code because the subfunctions could fail in a number of places and I'd have to significantly alter my code to take account of all of the potential failures.
Example Subfunction with try-catch statement (working as expected)
function h(x)
SQRT = []
try
SQRT = sqrt(x)
catch
SQRT = "no"
end
return SQRT
end
h(9)
> 3.0
h(-9)
> "no"
Example Main Function (working as expected)
function i(y)
a=h(y)
b="works"
return a,b
end
i(9)
> (3.0,"works")
i(-9)
> ("no","works")
In other words, I don't want to have to use the method in my second example, is there a way to get what I want using something similar to my first example?
I'm using Julia version 0.4.6
Thanks StefanKarpinski for suggesting a restart of the repl session, that worked.
"I've tried this on Julia 0.3, 0.4 and 0.5-dev and it works in all of them. Please do try in a clean session and see if you can reproduce. Otherwise, please give details of what version of Julia you're using.
– StefanKarpinski Jul 6 at 4:55"
Related
I have a datastage routine transform function, that does something a bit more complicated than the following(Takes in Arg1 which can be null):
Ans = Len(Arg1)
In certain situations I am calling this transform function in a transform stage and for certain rows where I'm passing in a null-able Timestamp column and I believe several null values are getting passed through to my function, when I run my job through datastage director, I see "Finished (See Log)" for my transform stage and a number of warning messages are shown, they basically say this(repeated a bunch of times):
Program "ABC": Line 2, Variable "Arg1" previously undefined. Empty string used.
I've attempted to catch this condition by using the "ISNULL" function to detect it, but unfortunately my efforts have been unsuccessful, I tried the following:
If ISNULL(Arg1) THEN
Ans = 0
END
ELSE IF Arg1 = $Null THEN
Ans = 0
END
ELSE
Ans = Len(Arg1)
END
Same issue, just a different line number on the warning message.
I don't understand why this is occurring, the "ISNULL" function seems to be straight forward, and I believe the error message is referring to the fact that Arg1 is null. I found some posts related to that but I don't have the direct link, is that accurate, does undefined = null in datastage basic, or can I catch this condition some other way?
I've searched extensively, most of what is written on this application is archaic and ancient and doesn't really provide any relevant information on the warning message itself. Is there a better resource for looking up relevant information on datastage warning messages, I feel as though I'm not understanding a core tenant of datastage. How do I catch this condition inside of the function and suppress the warning message using only datastage basic code(Without changing my input or column type)?
You need to catch this condition with the IsAssigned() function, rather than the IsNull() function.
#RayWurlod was close, it's actually the "Assigned" function that accomplished this, so my final solution looks like:
If NOT(ASSIGNED(Arg1)) THEN
Ans = 0
END
ELSE
Ans = Len(Arg1)
END
How can I avoid getting an error when passing as argument to the function do-http-request an invalid host.
Is there any way that I can catch the error like the Java's exception-handling mechanism ?
Sure, CL has a very nice condition system. One easy option would be wrapping the call to do-http-request in ignore-errors, which returns nil (and the condition as a second value) if an error condition was signalled in the wrapped code. You could then check for nil afterwards.
If you want something more like exception handling in Java, just use handler-case and add an appropriate error clause (I don't have AllegroServe installed, but I suppose you get a socket-error for providing a wrong URL – just change that part if I misread):
(handler-case
(do-http-request …)
(socket-error ()
…))
If you need finally-like functionality, use unwind-protect:
(unwind-protect
(handler-case
(do-http-request …)
(socket-error (condition) ; bind the signalled condition
…) ; code to run when a socket-error was signalled
(:no-error (value) ; bind the returned value
…)) ; code to run when no condition was signalled
…) ; cleanup code (finally)
You can even get more fancy, and e.g. use handler-bind to handle the condition stack upwards by invoking a restart somewhere down the stack, without unwinding it. For example, if do-http-request provided a restart to try again with another URL, you could handle your error condition by invoking that restart with a new URL to retry. I just mention this for the sake of completeness – it would be overkill for your use case, but being able to resume (possibly expensive) computations easily can be a rather convenient feature.
Please see #7755661 first. I am using ECL and basically want to execute some code, trap any kind of condition that may occur and then continue execution, without prompting or entering the debugger. This is easy to achieve with the following handler-case macro:
(handler-case
(load "code.lisp") ; this may raise a condition
(error (condition)
(print condition))) ; this prints sth like #<a UNBOUND-VARIABLE>
My only problem is that I cannot find a generic way to print a more meaningful error for the user. Indeed my application is an HTTP server and the output goes to a web page. code.lisp is written by the user and it can raise any kind of condition, I do now want to list them all in my code. I would just like to print the same error message I see on the REPL when I do not use handler-case, but in the HTML page, e.g. for an "unbound variable" error, a string like "The variable VAR is unbound".
By inspecting a condition object of type UNBOUND-VARIABLE I see it has two slots: SI:REPORT-FUNCTION, which is a compiled function and SI:NAME, set to the name of the variable in this case. I guess SI:REPORT-FUNCTION could be what I need to invoke but how can I call it? If I try:
(handler-case foo (error (condition) (SI::REPORT-FUNCTION condition)))
it tells me that SI:REPORT-FUNCTION is undefined. SI or SYS in ECL is a package for functions and variables internal to the implementation, but I don't worry if my code is not portable, as long as it works.
BTW in other kinds of condition objects there are also other apparently useful slots for my purpose, named SI:FORMAT-CONTROL and SI:FORMAT-ARGUMENT, but I cannot access any of them from my code too.
I was looking for somethink alike to the getMessage() method of Java exception objects in Lisp, but none of my sources ever mentions something like that.
Moreover, is there any hope to be able to get the line number in code.lisp where the error occurred too? Without that it would be difficult for the user to locate the problem in his code.lisp source file. I would really want to provide this information and stopping at the first error is acceptable for me.
In Common Lisp when print escaping is disabled, the error message is printed.
CL-USER > (handler-case
a
(error (condition)
(write condition :escape nil)))
The variable A is unbound.
#<UNBOUND-VARIABLE 4020059743>
Note that PRINT binds *print-escape* to T.
Using PRINC works - it binds *print-escape* to NIL.
CL-USER > (handler-case
a
(error (condition)
(princ condition)))
The variable A is unbound.
#<UNBOUND-VARIABLE 4020175C0B>
This is described in CLHS 9.1.3 Printing Conditions.
Also note, when you have an object, which has a slot and the value of this slot is a function, then you need to get the slot value using the function SLOT-VALUE and then use FUNCALL or APPLY and call the function with the correct arguments.
If you have a condition of type simple-condition then it has a format-control and a format-argument information. This is described with an example how to use it for FORMAT in CLHS Function SIMPLE-CONDITION-FORMAT-CONTROL, SIMPLE-CONDITION-FORMAT-ARGUMENTS
My answer below is based on one I already gave at the ECL mailing list. Actually I would claim that this is not an embedding problem, but a Lisp one. You want to get some information at the file position of the form which caused the error. This is not attached to a condition because conditions happen independently of whether the form evaluated was interpreted, compiled or part of a function that is already installed in the Lisp image. In other words, it is up to you to know the position of the file which is being read and do some wrapping that adds the information.
The following is nonstandard and prone to change: ECL helps you by defining a variable ext::source-location when LOAD is used on a source file. This variable contains a CONS that should NEVER be changed or stored by the user, but you can get the file as (CAR EXT:*SOURCE-LOCATION*) and the file position as (CDR EXT:*SOURCE-LOCATION*). The plan is then to embed your LOAD form inside a HANDLER-BIND
(defparameter *error-message* nil)
(defparameter *error-tag* (cons))
(defun capture-error (condition)
(setf *error*
(format nil "At character ~S in file ~S an error was found:~%~A"
(cdr ext:*source-location*)
(car ext:*source-location*)
condition)))
(throw *error-tag* *error-message*))
(defun safely-load (file)
(handler-bind ((serious-condition #'capture-error))
(catch *error-tag*
(load file)
nil)))
(SAFELY-LOAD "myfile.lisp") will return either NIL or the formatted error.
In any case I strongly believe that relying on LOAD for this is doomed to fail. You should create your own version of LOAD, starting from this
(defun my-load (userfile)
(with-open-file (stream userfile :direction :input :external-format ....whateverformat...)
(loop for form = (read stream nil nil nil)
while form
do (eval-form-with-error-catching form))))
where EVAL-FORM-.... implements something like the code above. This function can be made more sophisticated and you may keep track of file positions, line numbers, etc. Your code will also be more portable this way.
So please, read the ANSI Spec and learn the language. The fact that you did not know how to print readably a condition and instead tried to play with ECL internals shows that you might face further problems in the future, trying to go with non-portable solutions (hidden slot names, report functions, etc) instead of first trying the standard way.
I am writing program in Octave and I encountered a problem, I implemented Gauss-Legandre Quadrature and I pass to my Gauss-Legandre function few arguments, and I pass the function to be intergrated in a cell cube, so I can pass few function at a time. I have this piece of code:
for weight=1:length(w)
temp=1;
for fun=1:length(c)
%liczenie iloczynu f(x_i)g(x_i), x_i - pieriwastki wielomianu Legandra
f=c{fun};
nargin(func2str(c{fun}))
if (nargin (func2str(c{fun})) == 1)
disp('a');
temp*=c{fun}((b-a)/2 * x(weight) + (a+b)/2);
else
(b-a)/2 * x(weight) + (a+b)/2;
temp*=f((b-a)/2 * x(weight) + (a+b)/2,I,points);
end
end
%mnozenie wyniku przez odpowiedni wspolczynnik - wage
temp*=w(weight);
result+=temp;
end
In cell array there are function handlers to functions which I want to integrate. Depending on number of arguments that function takes i want to use two different calls for function. If in cell array there is handler to a function that is written in .m file in the same directory as my Octave working directory everything works fine, but when i define function in Octave running time, for example:
function result=a(x)
result=x*x
end
Type
c{1}=#a
and pass this cell array to my function Kwadratury there is an error of nargin
error: nargin: invalid function
error: called from:
Why is that and how can I solve it, so I can define function not only in .m files but also in Octave.
I suspect I have a solution, but as this is Octave-specific and I'm mostly used to MATLAB, your mileage may vary.
You call the nargin function by supplying a string argument, this means that nargin will have to resolve that function and check the number of arguments. When you declare a function in-line, that function is defined within that scope (i.e. your base scope), so resolving the function name will not work from within any function (or it might resolve to a built-in function, which is even worse behavior).
The best solution is to use nargin(c{fun}) instead of nargin(func2str(c{fun})). That way you pass the actual function handle along, and there is no need to resolve the function name to the actual function, and hence no possible ambiguity.
In general I recommend against using strings to pass functions: that why function handles are included in MATLAB, so anyone reading your code (or a static code analysis tool) will be able to understand you are working with functions. When using strings, everything becomes ambiguous: does a string 'a' refer to the function a or to the first letter in the alphabet?
With regard to using inline functions, I don't know whether Octave supports this, but if you function is quite simple, it's easier to define an anonymous function, such as your example, by a = #(x)(x*x);. That is a construct that is supported by MATLAB, so that makes your code more portable to other environments (well, you'd still need to replace X *= A with X = X * A; to be MATLAB compatible).
edit:
Another possibility could be to just try out whether a form with multiple parameters works and fall back to the one parameter form when necessary:
try
(b-a)/2 * x(weight) + (a+b)/2;
temp*=f((b-a)/2 * x(weight) + (a+b)/2,I,points);
catch ME
try
disp('a');
temp*=c{fun}((b-a)/2 * x(weight) + (a+b)/2);
catch ME
end
end
You might want to check whether the returned error ME really states that a wrong number of arguments is used to allow other errors through. I do admit this is an ugly work-around, but since Octave apparently doesn't support function handles for nargin, it might be the only way you'd get what you want for inline functions.
Ok, I am new in Matlab and I am currently working on some econometric script. Before I move to real econometrics I have to create a function that selects the data that I'm interested in. Although I managed to get that script to work by writing at a very structural level, I would like this script to be as universal as possible and therefore would like to divide it into specific functions. However, when I converted all this to one function, I keep getting the error "Function definitions are not permitted in this context".
Thanks in advance for your help.
function [probingArray] = extractData (data, startValue, numberOfPeriods)
arrayHeight=size(data,1);
for i=1:arrayHeight
if Date(i)==startValue
datePosition=i;
end
end
n=1;
for i=(datePosition-numberOfPeriods):datePosition
probingArray(n,1)=n;
probingArray(n,2)=UK(i);
n=n+1;
end
clear n i;
make sure you respect matlab conventions
function [out1, out2, ...] = myfun(in1, in2, ...) declares the function myfun, and its inputs and outputs. The function declaration must be the first executable line of any MATLAB function.
from http://www.mathworks.com/help/techdoc/ref/function.html