OS.FileSys.mkDir that does not raise exception when the directory already exists - sml

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

How to define custom exception printers using Janestreet Core?

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)

No local SparkleFormation files detected

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

How to unit test an Erlang function?

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.

Syntax error using "with fields" in OCaml

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";;

SML uncaught exception "Use failed: Io: openIn failed on..."

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?