I have a function in Julia I want to call for a set of arguments. It might throw an exeption and i want to convert it to a string with bactrace and log it for further examination.
for i in 1:100
try
myfun(i)
catch ex
println(ex)
println(bactrace(ex)) # does not work
end
end
How can one do this in Julia?
I know it's a bit old question, but here's what I found:
Base.show_backtrace(io, bt)
shows just the backtrace, and
sprint(io->Base.show_backtrace(io, bt))
prints it into a string in case you want to log it.
Edit: error_show in the previous answer is showerror now; it seems
str = showerror(STDOUT, ex, catch_backtrace())
Source: https://groups.google.com/forum/#!topic/julia-users/S485_5jG2Nw
Update 2: In v0.5 you can just do stacktrace() and catch_stacktrace()
Although you'd have to loop through the array of stacktraces to print it AFAIK.
Source: https://docs.julialang.org/en/stable/manual/stacktraces/
A litle more searching in the code found that this kind of works. It uses a function not exported in the API so it might break in the future, but for now it prints me a stack trace.
try
function()
catch ex
Base.error_show(STDERR, ex, catch_backtrace())
end
Related
I have an asynchronous method I'm writing which is supposed to asynchronously query for a port until it finds one, or time out at 5 minutes;
member this.GetPort(): Async<Port> = this._GetPort(DateTime.Now)
member this._GetPort(startTime: DateTime): Async<Port> = async {
match this._TryGetOpenPort() with
| Some(port) -> port
| None -> do
if (DateTime.Now - startTime).TotalMinutes >= 5 then
raise (Exception "Unable to open a port")
else
do! Async.Sleep(100)
let! result = this._GetPort(startTime)
result}
member this._TryGetOpenPort(): Option<Port> =
// etc.
However, I'm getting some strange type inconsistencies in _GetPort; the function says I'm returning a type of Async<unit> instead of Async<Port>.
It's a little unintuitive, but way to make your code work would be this:
member private this.GetPort(startTime: DateTime) =
async {
match this.TryGetOpenPort() with
| Some port ->
return port
| None ->
if (DateTime.Now - startTime).TotalMinutes >= 5 then
raise (Exception "Unable to open a port")
do! Async.Sleep(100)
let! result = this.GetPort(startTime)
return result
}
member private this.TryGetOpenPort() = failwith "yeet" // TODO
I took the liberty to clean up a few things and make the member private, since that seems to be what you're largely going after here with a more detailed internal way to get the port.
The reason why your code wasn't compiling was because you were inconsistent in what you were returning from the computation:
In the case of Some(port) you were missing a return keyword - which is required to lift the value back into an Async<port>
Your if expression where you raise an exception had an else branch but you weren't returning from both. In this case, since you clearly don't wish to return anything and just raise an exception, you can omit the else and make it an imperative program flow just like in non-async code.
The other thing you may wish to consider down the road is if throwing an exception is what you want, or if just returning a Result<T,Err> or an option is the right call. Exceptions aren't inherently bad, but often a lot of F# programming leads to avoiding their use if there's a good way to ascribe meaning to a type that wraps your return value.
What is the best method for handling a Void type when it is returned by a function? The suggestions in http://docs.julialang.org/en/release-0.5/manual/faq/#how-does-null-or-nothingness-work-in-julia don't work.
A MWE (must be run from the REPL so Base.source_dir() returns Void):
julia> isempty(Base.source_dir())
ERROR: MethodError: no method matching start(::Void)
Closest candidates are:
start(::SimpleVector) at essentials.jl:170
start(::Base.MethodList) at reflection.jl:258
start(::IntSet) at intset.jl:184
...
in isempty(::Void) at ./iterator.jl:3
in isempty(::Void) at /Applications/Julia-0.5.app/Contents/Resources/julia/lib/julia/sys.dylib:?
julia> isdefined(Base.source_dir())
ERROR: TypeError: isdefined: expected Symbol, got Void
julia> typeof(Base.source_dir()) == Void
true
This is on Julia 0.5. The latter option works, but it's a bit ugly.
Void is a singleton -- a type with exactly one instance.
That one instance is Void() also called nothing.
Be aware that nothing === Void()
You can treat it just like any other value.
It is returned by a bunch of functions, like println.
You can check if something has returned nothing -- ie and instance of type Void.
By
julia> println()===nothing
true
For the sake of type-stability,
a method should not return nothing some of the time, and something some of the time.
in those case it should instead return a Nullable,
generally.
I'm trying to make a constructor for a custom type in Julia:
type Cell
Base::Dict{String, String}
zLayers::Array{Dict{String, String},2}
X::Int
Y::Int
Cell() = new(Dict{String,String}(),[Dict{String, String}(),Dict{String, String}()],0,0)
end
try
gamestate = Cell()
catch err
print("connection ended with error $err\n")
end
Throws error:
connection ended with error MethodError(convert,(Array{Dict{String,String},2},[Dict{String,String}(),Dict{String,String}()]))
So how do we do proper initialization for Arrays of Dictionaries?
This question was double posted and answered on the mailiglist.
https://groups.google.com/forum/m/#!topic/julia-users/zE8Ri8rbfHQ
I think you’re confusing the 2 in an Array parameter set with the number of items, when it’s the number of dimensions. I’m pretty sure you’re creating a Vector, not a Matrix.
After shamelessly pilfering a code snippet from Tomas Petricek's Blog:
http://tomasp.net/blog/csharp-fsharp-async-intro.aspx
Specifically, this one (and making a few alterations to it):
let downloadPage(url:string) (postData:string) = async {
let request = HttpWebRequest.Create(url)
// Asynchronously get response and dispose it when we're done
use! response = request.AsyncGetResponse()
use stream = response.GetResponseStream()
let temp = new MemoryStream()
let buffer = Array.zeroCreate 4096
// Loop that downloads page into a buffer (could use 'while'
// but recursion is more typical for functional language)
let rec download() = async {
let! count = stream.AsyncRead(buffer, 0, buffer.Length)
do! temp.AsyncWrite(buffer, 0, count)
if count > 0 then return! download() }
// Start the download asynchronously and handle results
do! download()
temp.Seek(0L, SeekOrigin.Begin) |> ignore
let html = (new StreamReader(temp)).ReadToEnd()
return html };;
I tried to do the following with it, and got the error on the last line:
The type was expected to have type Async<'a> but has string -> Asnyc<'a> instead
I googled the error but couldn't find anything that revealed my particular issue.
let postData = "userid=" + userId + "&password=" + password + "&source=" + sourceId + "&version=" + version
let url = postUrlBase + "100/LogIn?" + postData
Async.RunSynchronously (downloadPage(url, postData));;
Also, how would I modify the code so that it downloads a non-ending byte stream (but with occasional pauses between each burst of bytes) asynchronously instead of a string? How would I integrate reading this byte stream as it comes through? I realize this is more than one question, but since they are are all closely related I figured one question would save some time.
Thanks in advance,
Bob
P.S. As I am still new to F# please feel free to make any alterations/suggestions to my code which shows how its done in a more functional style. I'm really trying to get out of my C# mindset, so I appreciate any pointers anyone may wish to share.
Edit: I accidentally pasted in the wrong snippet I was using. I did make an alteration to Tomas' snippet and forgot about it.
When I attempt to run your code downloadPage(url, postData) doesn't work as downloadPage expects two seperate strings. downloadPage url postData is what is expected.
If you changed the let binding to tuple form, or let downloadPage(url:string, postData:string) your call would have worked as well.
To explain why you got the error you got is more complicated. Curried form creates a function that returns a function or string -> string -> Async<string> in your case. The compiler therefore saw you passing a single parameter (tuples are single items after all) and saw that the result would have to be a string -> Async<string> which is not compatible with Async<string>. Another error it could have found (and did in my case) is that string * string is not compatible with string. The exact error being Expected string but found 'a * 'b.
This is what I had:
Async.RunSynchronously (downloadPage(url, postData));;
this is what worked after continued random guessing:
Async.RunSynchronously (downloadPage url postData);;
Although, I'm not sure why this change fixed the problem. Thoughts?
I have a function that pulls articles records from an MSSQL database. Some are URLs to PDFs, and other are actual articles stored in the SQL. The articles that are stored do not have a URL (DBNull) in the record, so I want to be able to parse that. I tried a simple test:
If Row.Item("url").GetType Is GetType(DBNull) Then
//' do something here....
End If
However, I get the "Conversion from type 'DBNull' to type 'String' is not valid." exception. The funny part is, when I do a watch on the above conditional, it returns True or False.
Anyone know why this is happening and/or a way to fix this? Thanks!
I always just use this test on the record:
If IsDBNull(strSQLTiggRes("url")) Then
'Do something .
Else
'do something else
end if
Why not just use:
If Row.IsNull("url") Then
//' do something here....
End If
I like
if (DBNull.Value.Equals(Row.Item("url")))
Try
If Row.Item("url") = DBNull.Value
The error is telling you that Row.Item("url") is a System.String so the value at this point will not by DbNull.
Try something like this:
If Row.Item("url") Is Nothing Then
//' do something here....
End If
Can't you just do
If Row.Item("url") = DBNull.Value Then
End If
My preference is:
If Not Object.Equals(DBNull.Value, Row.Item("url")) Then
'Hooray!
End If
In VB, you can also use the IsDBNull function (Microsoft.VisualBasic disclaimer) directly :
If Not IsDBNull(Row.Item("url")) Then
'Hooray!
End It
Use this.
if row("ColumnName") is DBNull.value Then
'do something
end if
You will find that you must use is in this case and you nee dto compare the values not just the types. You may also want to put it into a reusable function that you can use to return nothing instead of dbnull
function checkvalue(item as object)
if item is dbnul.value then
return nothing
else
return item
end if
end function