I am using Julia 1.1.1 and discovered something interesting yesterday.
Minimal example below
Consider the following code:
julia> if ((true)) true else false end
true
Works as intended
However, when attempting to do the following:
julia> function foo()
true
end
foo (generic function with 1 method)
julia> if ((foo())) (true,false) else (false,true) end
ERROR: syntax: space before "(" not allowed in "foo() ("
julia>
However, when writing the expression in the standard way it seems to work
julia> if ((foo()))
(true, false)
else
false
end
(true, false)
julia>
From my understanding from the following post Does Julia have a ternary conditional operator? I should be allowed to write if expressions in much the same way as ternaries and I usually can. However, for this case the ternary operator seems to be working as intended but not the if expression
julia> ((foo())) ? (true,false) : (false,true)
(true, false)
Does it exists a subtile difference between the two?
As noted in the comments by crstnbr the following syntax is allowed:
if ((foo())) true,false else false,true end
This does not seem to have anything to do with the if block per se. It is simply a syntax error.
Effectively, julia prohibits the syntax myfun (args) when calling a function (i.e. no space is allowed between the function name and the parentheses).
Since the output of a function, e.g., in this case foo(), may be another function, the same rule must apply to returned arguments. You wrapping your foo() function in infinite parentheses does nothing to resolve this, since the output of that expression is still asked to be evaluated via wrong syntax.
For example, note that:
julia> foo()()
ERROR: MethodError: objects of type Bool are not callable
Stacktrace:
[1] top-level scope at none:0
whereas
julia> foo() ()
ERROR: syntax: space before "(" not allowed in "foo() ("
Furthermore, as I mentioned in my comment above, regardless of the above, I personally would consider such terse if blocks very bad style, as well as a bad idea, as you have yourself just figured out. If you don't want to split into lines, it's is still a good idea, and much more readable, to use a semicolon at the end of the appropriate statements to show clear separation (both to yourself reading the code, and to the interpreter).
i.e.
if true; true, false; else; false, true; end
if foo(); true, false; else; false, true; end
From the finally section here: http://docs.julialang.org/en/release-0.4/manual/control-flow/#finally-clauses, they are using this example:
f = open("file")
try
# operate on file f
finally
close(f)
end
When I run similar code in REPL, this happens:
julia> f = open("myfile.txt")
IOStream(<file myfile.txt>)
julia> try
sqrt(-10)
finally
close(f)
end
ERROR: DomainError:
[inlined code] from none:2
in anonymous at no file:0
Any idea what's the difference?
finally does not catch exceptions. It's for guaranteeing that cleanup steps happen regardless of whether an exception occurred or not. Note the difference between:
try
sqrt(-10)
catch
println("Exception swallowed!")
end
and
try
sqrt(-10)
finally
println("This cleanup happened regardless of whether an exception was thrown.")
end
Often one combines catch and finally:
try
sqrt(-10)
catch
println("Swallowed exception.")
finally
println("...but finally ran regardless.")
end
finally has still done it's job here in the sense that the close() operation has been carried out. You can check this in your code by adding isopen(f) which returns false. You get the error though because you tried to do something that produced it.
try block is always followed by the catch block. in your program you forget to put catch block before finally block.
Is it possible to try using a package?
try
using A
catch e
showerror(STDOUT, e)
end
unsupported or misplaced expression using
I am expecting to see error message like
using A
LoadError: ArgumentError: A not found in path
using is only allowed at the top level scope. A workaround can be to use eval(:(using A)) instead of using A and then the try-catch works as expected.
The difference comes from using eval which evaluates its expression argument in the top level scope.
julia> try
eval(:(using A))
catch e
showerror(STDOUT, e)
end
ArgumentError: A not found in path
I'm new to Erlang and this is a question I didn't get a proper answer surfing through the internet for several days.
I want to code something as shown in following code segment (consider it as pseudo code) :
Check =false;
lists:foreach(fun(Row) ->
if somecondition ->
Check = true;
true -> ok
end
end, RowList)
At the end I need to get the value of variable Check. As in Erlang we can't re-"assign" a value to a variable, how can I get the value of Check at the end of the code block shown above ?
I think you can use this lists:any/2.
http://www.erlang.org/doc/man/lists.html#any-2
lists:any(fun(Row) -> somecondition end, RowList).
The generic way to go through a list and modify a value for each element is to use lists:foldl/3 http://www.erlang.org/doc/man/lists.html#foldl-3. For your specific example it is easier and shorter to use lists:any/2 as above.
What is good practice for error handling in math-related functions? I'm building up a library (module) of specialized functions and my main purpose is to make debugging easier for the code calling these functions -- not to make a shiny user-friendly error handling facility.
Below is a simple example in VBA, but I'm interested in hearing from other languages as well. I'm not quite sure where I should be returning an error message/status/flag. As an extra argument?
Function AddArrays(arr1, arr2)
Dim i As Long
Dim result As Variant
' Some error trapping code here, e.g.
' - Are input arrays of same size?
' - Are input arrays numeric? (can't add strings, objects...)
' - Etc.
' If no errors found, do the actual work...
ReDim result(LBound(arr1) To UBound(arr1))
For i = LBound(arr1) To UBound(arr1)
result(i) = arr1(i) + arr2(i)
Next i
AddArrays = result
End Function
or something like the following. The function returns a boolean "success" flag (as in the example below, which would return False if the input arrays weren't numeric etc.), or an error number/message of some other type.
Function AddArrays(arr1, arr2, result) As Boolean
' same code as above
AddArrays = booSuccess
End Function
However I'm not too crazy about this, since it ruins the nice and readable calling syntax, i.e. can't say c = AddArrays(a,b) anymore.
I'm open to suggestions!
Obviously error handling in general is a big topic, and what the best practice is depends a lot on the capabilities of the language you're working with and how the routine you're coding fits in with other routines. So I'll constrain my answer to VBA (used within Excel) and library-type routines of the sort you're describing.
Exceptions vs. Error Codes in Library Routines
In this case, I would not use a return code. VBA supports a form of exception handling that, while not as powerful as the more standard form found in C++/Java/??.NET, is pretty similar. So the advice from those languages generally applies. You use exceptions to tell calling routines that the called routine can't do it's job for whatever reason. You handle exceptions at the lowest level where you can do something meaningful about that failue.
Bjarne Stroustrup gives a very good explanation of why exceptions are better than error codes for this kind of situation in this book. (The book is about C++, but the principles behind C++ exception handling and VBA error handling are the same.)
http://www2.research.att.com/~bs/3rd.html
Here is a nice excerpt from Section 8.3:
When a program is composed of separate
modules, and especially when those
modules come from separately developed
libraries, error handling needs to be
separated into two distinct parts: [1]
The reporting of error conditions that
cannot be resolved locally [2] The
handling of errors detected elsewhere
The author of a library can detect
runtime errors but does not in general
have any idea what to do about them.
The user of a library may know how to
cope with such errors but cannot
detect them – or else they would be
handled in the user’s code and not
left for the library to find.
Sections 14.1 and 14.9 also address exceptions vs. error codes in a library context. (There is a copy of the book online at archive.org.)
There is probably lots more about this on stackoverflow. I just found this, for example:
Exception vs. error-code vs. assert
(There can be pitfalls involving proper management of resources that must be cleaned up when using exceptions, but they don't really apply here.)
Exceptions in VBA
Here is how raising an exception looks in VBA (although the VBA terminology is "raising an error"):
Function AddArrays(arr1, arr2)
Dim i As Long
Dim result As Variant
' Some error finding code here, e.g.
' - Are input arrays of same size?
' - Are input arrays numeric? (can't add strings, objects...)
' - Etc.
'Assume errorsFound is a variable you populated above...
If errorsFound Then
Call Err.Raise(SOME_BAD_INPUT_CONSTANT) 'See help about the VBA Err object. (SOME_BAD_INPUT_CONSTANT is something you would have defined.)
End If
' If no errors found, do the actual work...
ReDim result(LBound(arr1) To UBound(arr1))
For i = LBound(arr1) To UBound(arr1)
result(i) = arr1(i) + arr2(i)
Next i
AddArrays = result
End Function
If this routine doesn't catch the error, VBA will give other routines above it in the call stack a chance to (See this: VBA Error "Bubble Up"). Here is how a caller might do so:
Public Function addExcelArrays(a1, a2)
On Error Goto EH
addExcelArrays = AddArrays(a1, a2)
Exit Function
EH:
'ERR_VBA_TYPE_MISMATCH isn't defined by VBA, but it's value is 13...
If Err.Number = SOME_BAD_INPUT_CONSTANT Or Err.Number = ERR_VBA_TYPE_MISMATCH Then
'We expected this might happen every so often...
addExcelArrays = CVErr(xlErrValue)
Else
'We don't know what happened...
Call debugAlertUnexpectedError() 'This is something you would have defined
End If
End Function
What "do something meaningful" means depends on the context of your application. In the case of my caller example above, it decides that some errors should be handled by returning an error value that Excel can put in a worksheet cell, while others require a nasty alert. (Here's where the case of VBA within Excel is actually not a bad specific example, because lots of applications make a distinction between internal and external routines, and between exceptions you expect to be able to handle and error conditions that you just want to know about but for which you have no response.)
Don't Forget Assertions
Because you mentioned debugging, it's also worth noting the role of assertions. If you expect AddArrays to only ever be called by routines that have actually created their own arrays or otherwise verified they are using arrays, you might do this:
Function AddArrays(arr1, arr2)
Dim i As Long
Dim result As Variant
Debug.Assert IsArray(arr1)
Debug.Assert IsArray(arr2)
'rest of code...
End Function
A fantastic discussion of the difference between assertions and exceptions is here:
Debug.Assert vs Exception Throwing
I gave an example here:
Is assert evil?
Some VBA Advice About General Array Handling Routines
Finally, as a VBA-specific note, there are VBA variants and arrays come with a number of pitfalls that must be avoided when you're trying to write general library routines. Arrays might have more than one dimension, their elements might be objects or other arrays, their start and end indices might be anything, etc. Here is an example (untested and not trying to be exhaustive) that accounts for some of that:
'NOTE: This has not been tested and isn't necessarily exhaustive! It's just
'an example!
Function addArrays(arr1, arr2)
'Note use of some other library functions you might have...
'* isVect(v) returns True only if v is an array of one and only one
' dimension
'* lengthOfArr(v) returns the size of an array in the first dimension
'* check(condition, errNum) raises an error with Err.Number = errNum if
' condition is False
'Assert stuff that you assume your caller (which is part of your
'application) has already done - i.e. you assume the caller created
'the inputs, or has already dealt with grossly-malformed inputs
Debug.Assert isVect(arr1)
Debug.Assert isVect(arr2)
Debug.Assert lengthOfArr(arr1) = lengthOfArr(arr2)
Debug.Assert lengthOfArr(arr1) > 0
'Account for VBA array index flexibility hell...
ReDim result(1 To lengthOfArr(arr1)) As Double
Dim indResult As Long
Dim ind1 As Long
ind1 = LBound(arr1)
Dim ind2 As Long
ind2 = LBound(arr2)
Dim v1
Dim v2
For indResult = 1 To lengthOfArr(arr1)
'Note implicit coercion of ranges to values. Note that VBA will raise
'an error if an object with no default property is assigned to a
'variant.
v1 = arr1(ind1)
v2 = arr2(ind2)
'Raise errors if we have any non-numbers. (Don't count a string
'with numeric text as a number).
Call check(IsNumeric(v1) And VarType(v1) <> vbString, xlErrValue)
Call check(IsNumeric(v2) And VarType(v2) <> vbString, xlErrValue)
'Now we don't expect this to raise errors.
result(indResult) = v1 + v2
ind1 = ind1 + 1
ind2 = ind2 + 1
Next indResult
addArrays = result
End Function
There's lots of ways to trap errors, some better than others. Alot of it depends on on the nature of the error and how you want to handle it.
1st: In your examples, you aren't handling the basic compiling & runtime errors (see code below).
Function Foobar (Arg1, Arg2)
On Error goto EH
Do stuff
Exit Function
EH:
msgbox "Error" & Err.Description
End Function
2nd: Using the framework example above, you can add all the if-then logical error trapping statements you want & feed it to the EH step. You can even add multiple EH steps if your function is complex enough. Setting things up this way allows you to find the particular function where your logic error occurred.
3rd: In your last example, ending that function as a boolean is not the best method. If you were able to add the 2 arrays, then that function should return the resultant array. If not, it should throw up a msgbox-style error.
4th: I recently started doing a little trick that can be very helpful in some situations. In your VBA Editor, go to Tools->Options->General->Break on ALL errors. This is very helpful when you already have your error handling code in place, but you want to go the exact line where the error occurred and you don't feel like deleting perfectly good code.
Example: Let's say you want to catch an error that wouldn't be caught normally by VBA, i.e. an integer variable should always have a value >2. Somewhere in your code, say If intvar<=2 then goto EH. Then in your EH step, add If intvar<=2 then msgbox "Intvar=" & Intvar.
First, PowerUser gave you a good answer already--this is an expansion on that one.
A trick that I just learned is the "double resume", thus:
Function Foobar (Arg1, Arg2)
On Error goto EH
Do stuff
FuncExit:
Exit Function
EH:
msgbox "Error" & Err.Description
Resume FuncExit
Resume
End Function
What happens here is that in the execution of finished code, your code throws up a MsgBox when an error is encountered, then runs the Exit Function statement & goes on its way (just the same as dropping out the bottom with End Function). However, when you're debugging and you get that MsgBox you instead do a manual Ctrl-Break, then set next statement (Ctrl-F9) to the unadorned Resume and press F8 to step--it goes right back to the line that threw the error. You don't even have to take the extra Resume statements out, since they will never execute without manual intervention.
The other point on which I want to argue (gently) with PowerUser is in the final example. I think it's best to avoid unneeded GoTo statements. A better approach is If intvar<=2 then err.raise SomeCustomNumber. Make sure you use a number that isn't already in use--search 'VB custom error' for more information.