How to exit a program? - ocaml

If the input argument are not as expected I want to exit the program. How should I achieve that? Below is my attempt.
let () =
if ((Array.length Sys.argv) - 1) <> 2 then
exit 0 ; ()
else
()
Thanks.

exit n is a right way to exit program, but your code has a syntax error. if ... then exit 0; () is parsed as (if ... then exit 0); (). Therefore you got a syntax error around else, since it is not correctly paired with then.
You should write:
let () =
if ((Array.length Sys.argv) - 1) <> 2 then begin
exit 0 ; ()
end else
()
or simply,
let () = if Array.length Sys.argv - 1 <> 2 then exit 0

Related

How to return value of if else statement in ocaml?

I'd like to return the value of an if else statement in ocaml.
For example, if I do
let myvalue = if my_condition != 0 then do_this else do_this_instead
But this doesn't seem to store the result of do_this or do_this_instead in myvalue. If I was doing this in C
if(my_condition)
{
return 1 + 1;
} else {
return 1 - 1;
}
I want to kind of achieve the same affect, where not only is the if-else logic executed, but there is also kind of like a return value associated with the executed statement that is caught and stored. How might I do this in ocaml?
If I do following...
# let myvalue = if 2 > 1 then 2 else 1;;
val myvalue : int = 2
# myvalue;;
- : int = 2
What else are you expecting?
if-then-else is an expression construct, and expressions produce/have values.
Or else, if you looking to call other functions for values in the corresponding then and else construct, we can try following way...
# let my_condition = 2 in
let do_this () = 1 + 1 in
let do_this_instead () = 1 - 1 in
myvalue = if my_condition != 0 then do_this () else do_this_instead ();;
- : bool = true
# myvalue;;
- : int = 2

ATS Proof: Why does this static if need greater than or equal to?

I was writing a proof of a*0=0 and I stumbled on some strangeness. Why does the sif a >= 0 on line 7 need to be a >=, and does not compile when its just sif > 0?
prfn mul_ax0_0 {a:int} () : MUL(a,0,0) =
let
prfun auxnat {a:nat} .<a>. () : MUL(a,0,0) =
sif a == 0 then MULbas()
else MULind(auxnat{a-1}())
in
sif a >= 0 then auxnat{a}() // line 7
else MULneg(auxnat{~a}())
end
implement main0 () = ()
Intuitively, the a=0 should be handled fine by either path, yet only the first path works.
Why?
MULneg is declared as follows:
| {m:pos}{n:int}{p:int}
MULneg (~(m), n, ~(p)) of MUL_prop (m, n, p)
Note that 'm' is required to be positive. In your case, 'm' is '~a'. If
you use '>' instead of '>=', then it cannot be inferred that '~a > 0' holds
when the test 'a > 0' fails.

Make Julia testsuite report all error messages at end of run

I'm playing around with the Julia testsuite functionality and I quite like it.
What i however fail to figure out is how to make the testsuite report the potential message upon completion.
Let's say I have a test suite like the one below, where each of the functions performs a bunch of tests in turn before returning
#testset "MyTestSuite" begin
#testset "Subtest1" begin #test my_test_1() end
#testset "Subtest2" begin #test my_test_2() end
#testset "Subtest3" begin #test my_test_3() end
#testset "Subtest4" begin #test my_test_4() end
end
If now say my_test_4 fails or throws an error, then the ouput would look like below
Test Summary: | Pass Error Total
MyTestSuite | 65 1 66
Subtest1 | 5 1 6
Subtest2 | 10 0 10
Subtest3 | 20 0 20
Subtest4 | 30 0 30
ERROR: LoadError: Some tests did not pass: 65 passed, 0 failed, 1 errored, 0 broken.
But there is now way (to my knowledge) for me to see what went wrong without scrolling upwards in the terminal output. If my test suites are long enough, and produce enough diagnostics, the error information could even be lost to me or at least very difficult to find.
So, does anyone know a nice way around this? Are there options that one can give to the macro #testset to make sure it prints of collects the errors for further processing?
You can define your custom AbstractTestSet. It is descirbed here in the Julia manual.
Here is an example adapted from the manual. First define:
using Test
struct CustomTestSet <: Test.AbstractTestSet
description::AbstractString
results::Vector
CustomTestSet(desc) = new(desc, [])
end
Test.record(ts::CustomTestSet, child::Test.AbstractTestSet) = push!(ts.results, child)
Test.record(ts::CustomTestSet, res::Test.Result) = push!(ts.results, res)
function Test.finish(ts::CustomTestSet)
if Test.get_testset_depth() > 0
Test.record(Test.get_testset(), ts)
end
ts
end
and now you can write:
julia> res = #testset CustomTestSet "custom testset" begin
# this testset should inherit the type, but not the argument.
#testset "custom testset inner" begin
#test 1==1
#test 1==2
#test 2==2
#test 2==3
end
end
CustomTestSet("custom testset", Any[CustomTestSet("custom testset inner", Any[Test Passed, Test Failed at REPL[10]:5
Expression: 1 == 2
Evaluated: 1 == 2, Test Passed, Test Failed at REPL[10]:7
Expression: 2 == 3
Evaluated: 2 == 3])])
julia> res.results[1].results
4-element Array{Any,1}:
Test Passed
Test Failed at REPL[10]:5
Expression: 1 == 2
Evaluated: 1 == 2
Test Passed
Test Failed at REPL[10]:7
Expression: 2 == 3
Evaluated: 2 == 3
and you have an access to a vector that tells you what passed and what failed, and on failure what was the problem.
You can also filter out passed tests:
julia> filter(x -> !(x isa Test.Pass), res.results[1].results)
2-element Array{Any,1}:
Test Failed at REPL[6]:5
Expression: 1 == 2
Evaluated: 1 == 2
Test Failed at REPL[6]:7
Expression: 2 == 3
Evaluated: 2 == 3
If your tests have a more complex nested structure you should do it recursively.
Is this something you wanted?

Is it possible to define an exception inside a function

One way to implement "early returns" in OCaml is via exceptions:
exception Exit
let myfunc () =
try
for i = 0 to .... do
if .. then raise Exit
done; false
with Exit -> true
However, is there a way to declare this Exit exception in the body of the function, so its name is not visible to other functions in the module?
(* I would like to do this, but it gives a syntax error *)
let myfunc () =
exception Exit
try
for i = 0 to .... do
if .. then raise Exit
done; false
with Exit -> true
Yes, what you want is possible by using a local module:
let myfunc () =
let module M = struct exception Exit end in
try
for i = 0 to 3 do
if true then raise M.Exit
done; false
with M.Exit -> true
That style is not particularly pleasant to read, though, so I wouldn't recommend it. It is enough to omit showing Exit at the next module interface if you want to hide it from most of the rest of the program.

Fortran fibonacci woes

I am working my way through "Modern Fortran explained" by Metcalf, Reid, and Cohen and in chapter four it assigns a Fibonacci program as a homework problem. My code below doesn't compile. How can I correct it?
! Fibonacci here we go
integer :: lim, i
lim=0
read *, lim
integer, dimension(lim) :: fib
if( lim >= 1 )
fib(1) = 0
end if
if( lim >= 2 )
fib(2) = 1
end if
if( lim >= 3 )
fib(3) = 1
end if
do i=4, lim
fib(i) = fib(i-2) + fib(i-1)
end do
do i=1, size(fib)
print *, fib(i)
end do
end
Also, here are the errors I am getting. I would attempt to shorten this to what is needed but I am not sure what one needs when looking at Fortran error logs.
Compiling the source code....
$/usr/bin/gfortran /tmp/135997827718658.f95 -o /tmp/135997827718658 2>&1
In file /tmp/135997827718658.f95:7
integer, dimension(lim) :: fib
1
Error: Unexpected data declaration statement at (1)
In file /tmp/135997827718658.f95:9
if( lim >= 1 )
1
Error: Unclassifiable statement in IF-clause at (1)
In file /tmp/135997827718658.f95:10
fib(1) = 0
1
Error: Unclassifiable statement at (1)
In file /tmp/135997827718658.f95:11
end if
1
Error: Expecting END PROGRAM statement at (1)
In file /tmp/135997827718658.f95:13
if( lim >= 2 )
1
Error: Unclassifiable statement in IF-clause at (1)
In file /tmp/135997827718658.f95:14
fib(2) = 1
1
Error: Unclassifiable statement at (1)
In file /tmp/135997827718658.f95:15
end if
1
Error: Expecting END PROGRAM statement at (1)
In file /tmp/135997827718658.f95:17
if( lim >= 3 )
1
Error: Unclassifiable statement in IF-clause at (1)
In file /tmp/135997827718658.f95:18
fib(3) = 1
1
Error: Unclassifiable statement at (1)
In file /tmp/135997827718658.f95:19
end if
1
Error: Expecting END PROGRAM statement at (1)
In file /tmp/135997827718658.f95:22
fib(i) = fib(i-2) + fib(i-1)
1
Error: Statement function at (1) is recursive
Error: Unexpected end of file in '/tmp/135997827718658.f95'
random fixes....
if block should be
if (condition) then
do something
endif
cannot ommit "then".
you cannot go
read *, lim
integer, dimension(lim) :: fib
all the declaration has to come before executable codes. so instead, use allocatable array
integer, dimension(:), allocatable :: fib
read *, lim
allocate(fib(lim))