I am trying to write a function that creates a directory but does not raise an error when the directory already exists. This is the function:
fun ensureDir s =
(OS.FileSys.mkDir s)
handle OS.SysErr (_, SOME Posix.Error.exist) => ()
I based the pattern OS.SysErr (_, SOME Posix.Error.exist) on the fact that OS.FileSys.mkDir fails with the following error message when the directory already exists:
Poly/ML:
Exception- SysErr ("File exists", SOME EEXIST) raised
SML/NJ:
uncaught exception SysErr [SysErr: File exists [exist]]
raised at: <mkdir.c>
However, I get this error when I try to define the function in the Poly/ML shell:
poly: : error: qualified name Posix.Error.exist illegal here
Static Errors
This is the error in SML/NJ:
Error: variable found where constructor is required: Posix.Error.exist
What mistake did I make in the function definition?
(Poly/ML 5.7.1; SML/NJ 110.79; Ubuntu 20.04)
Posix.Error.exist is a val and not a constructor (like SOME) so
you cannot use it as a pattern in a pattern matching construct. Here
is an equivalent code for what you intended to do.
fun ensureDir s =
(OS.FileSys.mkDir s)
handle e as (OS.SysErr (_, SOME err)) =>
if err = Posix.Error.exist
then ()
else raise e
;
Related
By default, a Failure exception is printed as such:
# print_endline (Printexc.to_string (Failure "uh\noh"));;
Failure("uh\noh")
For improved readability, we want to print the argument of Failure as is because we understand it should be human-readable. In the OCaml standard library, we would initialize an application with the following:
# Printexc.register_printer (function
| Failure s -> Some ("Failure: " ^ s)
| _ -> None
);;
The new behavior of Printexc.to_string would be:
# print_endline (Printexc.to_string (Failure "uh\noh"));;
Failure: uh
oh
Great. Now if we use the core_kernel library, first we can see that printing an exception is slightly different but not better to a human reader:
#require "core_kernel";;
# print_endline (Printexc.to_string (Failure "uh\noh"));;
(Failure "uh\
\noh")
Perhaps we can override this? Let's try.
# Printexc.register_printer (function
| Failure s -> Some ("Failure: " ^ s)
| _ -> None
);;
# print_endline (Printexc.to_string (Failure "uh\noh"));;
Failure: uh
oh
This works, but it's not using the printer that's part of Core_kernel. If we use it, we still get the same unreadable result:
# print_endline (Core_kernel.Exn.to_string (Failure "uh\noh"));;
(Failure "uh\
\noh")
And Core_kernel.Exn doesn't offer a register_printer function. So effectively, it looks like Core_kernel.Exn makes sure that we don't define custom exception printers. Is there another way or should we just not use Core_kernel.Exn then if we want to show human-readable error messages?
Edit: For context, our original problem is to print nested error messages nicely. For example, we would like to read something like the following:
Uncaught exception: Failure:
Uncaught exception in subprocess 1234: Failure:
something happened
trace line 1
trace line 2
trace line 1
trace line 2
trace line 3
where we use indentation for quoting and escaping, rather than double-quotes and backslash escape sequences.
Base.Exn (for which Core_kernel.Exn is an alias) prints errors as human readable s-expressions using Sexplib0 printer and converters. It is possible to add custom sexp converter for exceptions with Sexplib0.Exn_converter.add.
However, if you don't intend to print exceptions as s-expressions, I see indeed no reason to use the printer of Base.Exn.
EDIT: Since the problem seems to be the printing of S-expressions, one solution might be to use Base.Exn.sexp_of and then plug-in a custom S-expression printers that does not escape strings, nor print parenthesis:
let pp_sep ppf () = Format.fprintf ppf "# "
let pp_sexp ppf = function
| Atom s -> Format.pp_print_string ppf s
| List l ->
Format.fprintf ppf "#[<v 2> %a#]"
(Format.pp_print_list ~pp_sep pp_sexp) l
let to_string exn = Format.asprintf "%a" pp_sexp (Exn.sexp_of_t exn)
So I've been working in sparkleformation and had this issue pop up even though all my files exist:
[WARN]: No local SparkleFormation files detected
[ERROR]: Failed to locate any templates!
[FATAL]: Invalid formation file path provided:
ERROR: IOError: Failed to locate file:
I wanted to create this question for future reference. This is what happens if you create a sparkleformation template and place any code outside of the Sparkleformation.new block. For example this would cause the above failure:
yamlfile = YAML.load_file(ENV['YAMLFILE_YML_PATH'])
SparkleFormation.new(:somename, :provider => :aws).load(:base).overrides do
yamlfile.keys.each { |key| yamlfile[key.to_sym] = yamlfile.delete(key)}
dynamic!(:someother name, :test_eips, yamlfile)
end
This will work:
SparkleFormation.new(:somename, :provider => :aws).load(:base).overrides do
yamlfile = YAML.load_file(ENV['YAMLFILE_YML_PATH'])
yamlfile.keys.each { |key| yamlfile[key.to_sym] = yamlfile.delete(key)}
dynamic!(:someother name, :test_eips, yamlfile)
end
get_ue_supported_srvcc([]) ->
?SRVCC_3GPP_NONE_SUPPORT;
get_ue_supported_srvcc([#sip_contactV{extensionsP = EP} | T]) ->
case b2bLib:support_tags_to_value(EP) of
?SRVCC_3GPP_NONE_SUPPORT ->
get_ue_supported_srvcc(T);
Flag ->
Flag
end.
I want create a unit test for this function,
Here is my unit test case:
get_ue_supported_srvcc_test() ->
Contact =
[#sip_contactV{extensionsP =
[{"+sip.instance",
{quoted_string,"<urn:gsma:imei:35502406-005233-0>"}},
{"+g.3gpp.icsi-ref",
{quoted_string,"urn%3Aurn-7%3A3gpp-service.ims.icsi.mmtel"}},
"+g.3gpp.mid-call",
"+g.3gpp.srvcc-alerting",
"+g.3gpp.ps2cs-srvcc-orig-pre-alerting",
"video"]}],
?assertEqual(7, b2bAtcfLib:get_ue_supported_srvcc(Contact)).
But when I run it, I get this error:
======================== EUnit ========================
module 'b2bAtcfLib'
b2bAtcfLib_tests: get_ue_supported_srvcc_test (module 'b2bAtcfLib_tests')...*failed*
in function b2bLib:support_tags_to_value/1
called as support_tags_to_value([{"+sip.instance",{quoted_string,"<urn:gsma:imei:35502406-005233-0>"}},
{"+g.3gpp.icsi-ref",
{quoted_string,"urn%3Aurn-7%3A3gpp-service.ims.icsi.mmtel"}},
"+g.3gpp.mid-call","+g.3gpp.srvcc-alerting",
"+g.3gpp.ps2cs-srvcc-orig-pre-alerting","video"])
in call from b2bAtcfLib:get_ue_supported_srvcc/1 (src/b2bAtcfLib.erl, line 1735)
in call from b2bAtcfLib_tests:'-get_ue_supported_srvcc_test/0-fun-0-'/1 (test/unit/b2bAtcfLib_tests.erl, line 49)
in call from b2bAtcfLib_tests:get_ue_supported_srvcc_test/0
**error:undef
output:<<"">>
[done in 0.008 s]
=======================================================
The error means b2bLib:support_tags_to_value/1 is undef.
The define for this function b2bLib:support_tags_to_value:
support_tags_to_value(FieldStr) ->
lists:sum([Val || {Tag, Val} <- ?TAGLIST, lists:member(Tag, FieldStr)]).
The error is:
**error:undef
That means that the test is calling a function that's not defined. Either the module couldn't be found, or the module in question doesn't define a function with that name and arity.
The whole error message is a bit confusing. Now that we know that we got a "function undefined" error, we should be looking at this line:
in function b2bLib:support_tags_to_value/1
Even though it says that the error occurred "in" this function, this is the function that's undefined.
So either the test is run in such a way that it doesn't find the b2bLib module, or that module doesn't define a function called support_tags_to_value taking one argument. If it's the former, add -pa path/to/ebin to the Erlang command line in order to add the right directory to the code path.
I'm working through Real World OCaml and I'm getting a syntax error on the following bit of code:
`# module Logon = struct
type t =
{ session_id: string;
time: Time.t;
user: string;
credentials: string;
}
with fields
end;;
On running, Utop underlines the word "with" and throws a syntax error. I've tried similar, more simple examples on my own and get the same error. Any thoughts on what's going on?
EDIT: Omitted "}" added.
For ocaml 4.01.0 :
In utop : #require "fieldslib.syntax";; is solving the issue. (... do not forget to run opam install fieldslib).
For recent ocaml :
(got some hints here ).
opam install ppx_jane fieldslib
#require "ppx_jane";;
#require "fieldslib";;
module Logon = struct
type t =
{ session_id: string;
time: Time.t;
user: string;
credentials: string;
}
[##deriving fields]
end;;
For me I needed to add this, in utop:
#require "ppx_fields_conv";;
I am new with SML/programming/emacs/all the stuff and when I do the first homework from coursera class I have the old story regarding this error:
[opening is_older.sml]
[use failed: Io: openIn failed on "is_older.sml", Win32TextPrimIO:openRd: failed]
uncaught exception Error
raised at: ../compiler/TopLevel/interact/interact.sml:24.14-24.28
I tried all the possible things found on the forums, topics, like: path,checking any misspelled name of sml file, coding-I put several codes, savings, etc. The only thing I did not made was to custom Emacs and I didn't verify if the SML-mode is working properly since 2 days ago Emacs and SML/NJ were installed.
The last code I wrote - but anyway is not important because it doesn't matter which code is, I have the same error - is this:
fun is_older ((x1,y1,z1), (x2,y2,z2)) =
if z1 < z2
then true
else
if x1 = x1 andalso y1 = y2 andalso z1 < z2
then true
else false;
[use failed: Io: openIn failed on "is_older.sml", Win32TextPrimIO:openRd: failed]
This sounds like like it simply didn't find the file. Maybe you misspelled the name, or it's in a different directory?