-
Notifications
You must be signed in to change notification settings - Fork 41
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
file system #37
Comments
Hi! No, this is currently not possible, but it would probably be easy to add in |
Read and write! |
So the signatures would be |
Perfect! Thank you for your reply. It is absolutely appreciated So are you saying I can use these read and write functions from external.ml? is that the right one? https://github.com/ocaml/ocamlbuild/blob/master/testsuite/external.ml and I am assuming I can write
in the top of my eff file to import it? I followed these steps but it did not work, so I am not sure what I am doing wrong FYI, I have Ocamal installed on my machine |
I see that external.ml exist in eff/_build/src/runtime |
I am guessing I should do something like external ( < ) : 'a -> 'a -> bool = "<" |
No, you should take a look at |
You can also add such effects in the same way that #Print was added, in For instance, for a basic version of
| V.Call ("Read_file", v, k) ->
let filename = V.to_str v in
let channel = open_in filename in
let text = ref "" in
(
try
while true do
text := !text ^ (input_line channel) ^ "\n" (* Gather text into a single string. *)
done;
close_in channel;
top_handle (k (V.Const (Const.of_string !text))) (* This is only for typechecking. *)
with
End_of_file ->
close_in channel;
top_handle (k (V.Const (Const.of_string !text)))
) seems to work for me. You should adapt the function to your needs (as you can see this adds an Also, don't forget to |
Thanks a lot! |
That worked! Thank you so much I will work now to add write_to_file and also read_line |
This is my implementation of write_to_file I added this effect to effect Write_file : string * string -> unit
I added these two to val first : value -> value
val second : value -> value and these two let first = function
| Tuple (x::xs) -> x
| _ -> Error.runtime "first value expected."
let second = function
| Tuple (x::y::xs)-> y
| _ -> Error.runtime "second value expected." and added this case to top_handle in | V.Call ("Write_file", v , k) ->
let filename = V.to_str (V.first v) in
let text = V.to_str (V.second v) in
let channel = open_out filename in
fprintf channel "%s\n" text;
top_handle (k V.unit_value)
I can now see why read_line might be complicated because we need to keep track of the file pointer |
Yes, you'd need a separate constant for file pointers (just like for booleans, strings, …) |
I think this issue presents a very realistic and nice test case for effects: what is the Correct Way of working with files? |
Alright! First I added in_channel and out_channel as types to type t =
| In_channel of in_channel
| Out_channel of out_channel
let of_in_channel n = In_channel n
let of_out_channel n = Out_channel n
let print c ppf =
| In_channel f -> Format.fprintf ppf ""
| Out_channel f -> Format.fprintf ppf "" to type t = private
| In_channel of in_channel
| Out_channel of out_channel
val of_in_channel : in_channel -> t
val of_out_channel : out_channel -> t to let const ?loc c =
| Const.Out_channel _ -> Type.out_channel_ty
| Const.In_channel _ -> Type.in_channel_ty to ("in_channel", (OldUtils.trio_empty, Inline T.in_channel_ty));
("out_channel", (OldUtils.trio_empty, Inline T.out_channel_ty)); to let in_channel_ty = Basic "in_channel"
let out_channel_ty = Basic "out_channel" to val to_out_channel : value -> out_channel
val to_in_channel : value -> in_channel to let to_in_channel = function
| Const (Const.In_channel b) -> b
| _ -> Error.runtime "A in_channel value expected."
let to_out_channel = function
| Const (Const.Out_channel b) -> b
| _ -> Error.runtime "A out_channel value expected."
** I got a bunch of warnings because pattern matching is not complete in many functions but it compiles Now I added to (* effect Open_in : string -> in_channel *)
| V.Call ("Open_in", v , k) ->
let filename = V.to_str v in
let channel = open_in filename in
(try
top_handle (k (V.Const (Const.of_in_channel channel) ))
with e ->
close_in channel;
top_handle (k (V.Const (Const.of_in_channel channel) ))
)
(* effect effect Open_out : string -> out_channel *)
| V.Call ("Open_out", v , k) ->
let filename = V.to_str v in
let channel = open_out filename in
(try
top_handle (k (V.Const (Const.of_out_channel channel) ))
with e -> (* some unexpected exception occurs *)
close_out channel;
top_handle (k (V.Const (Const.of_out_channel channel) ))
) (* effect effect Close_in : in_channel -> unit *)
| V.Call ("Close_in", v , k) ->
let channel = V.to_in_channel v in
close_in channel;
top_handle (k V.unit_value) (* effect Close_out : out_channel -> unit *)
| V.Call ("Close_out", v , k) ->
let channel = V.to_out_channel v in
close_out channel;
top_handle (k V.unit_value) (* effect Write_file : (out_channel * string) -> unit *)
| V.Call ("Write_file", v , k) ->
let channel = V.to_out_channel (V.first v) in
let text = V.to_str (V.second v) in
(try
output_string channel text;
flush channel;
top_handle (k V.unit_value)
with End_of_file ->
close_out channel;
top_handle (k V.unit_value)
) (* effect Read_line : in_channel -> string *)
| V.Call ("Read_line", v, k) ->
let channel = V.to_in_channel v in
let text = ref "" in
(
try
text := !text ^ (input_line channel);
top_handle (k (V.Const (Const.of_string !text)))
with End_of_file ->
close_in channel;
top_handle (k (V.Const (Const.of_string !text)))
) Thanks a lot for your help! |
|
But other than that, great work :-) |
Thank you : ) |
Hello all!
Thank you in advance for any help!
I was wondering whether or not it is possible to read and write to files in Eff?
The text was updated successfully, but these errors were encountered: