return a list from external.ml
Closed this issue · 12 comments
type value =
| Const of Const.t
| Tuple of value list
| Record of (OldUtils.field, value) Assoc.t
| Variant of OldUtils.label * value option
| Closure of closure
| Handler of (result -> result)
I was trying to use Split as an external function
I got it to work but the return value is of this type (Tuple of value list)
However, I want to return a string list instead of tuple
I tried to make a new constructor for lists but still the value retuned comes as a tuple
type value =
| Const of Const.t
| Tuple of value list
| List of value list
| Record of (OldUtils.field, value) Assoc.t
| Variant of OldUtils.label * value option
| Closure of closure
| Handler of (result -> result)
Any ideas?
Thanks,
Ghadeer
Lists are encoded as Variants
with the labels OldUtils.cons
and OldUtils.label
, so you probably need to use that to implement split
.
Is there any special reason you are trying to use split
as an external function?
It seems to be easy enough to implement in pervasives.eff
.
I wanted to implement it in pervasives.eff as this
let rec split l d =
match l with
[] -> [l]
| (c::cs) -> let rest = split cs d in
match c = d with
true -> (""::rest)
| false -> ( c ^ head rest ) :: tail rest
;;
but I got this issue
This expression has type string list but it should have type string.
When I looked online, they said I need to covert the string to list of chars using this method
let string_of_char c = String.make 1 c
(* Converts a string to a list of chars *)
let explode str =
let rec explode_inner cur_index chars =
if cur_index < String.length str then
let new_char = str.[cur_index] in
explode_inner (cur_index + 1) (chars @ [new_char])
else chars in
explode_inner 0 []
(* Converts a list of chars to a string *)
let rec implode chars =
match chars with
[] -> ""
| h::t -> string_of_char h ^ (implode t)
so I thought using it as external is more convient
Ah, I see, I though you were trying to implement List.split
.
The way I would try to do this, is add external functions equivalent to String.length
and String.get
.
That probably requires modifying Const.ml
and Const.mli
to safely extract the string from the constant.
Afterwards it is probably possible to implement split
in pervasives.eff
using the above two functions.
You can however try to modify your existing implementation to return a Variant
with the proper list constructor.
This is what I was about to do
I already have "get" and would add "length"
and then implement it in pervasives.eff
Thank you for your help and advice!
What is your split
supposed to do, in words? It looks like you just have a simple bug in the Eff code, you should try to fix that first.
split takes a string and a char and split the string to a list of strings using the char
$ split "Hello Hi" ' '
["Hello"; "Hi"]
The code you wrote does not do that (and I don't see what it's supposed to do). But yeah, if that's what you want ot do, you'll have to add characters to Eff. And may I ask what this is used for later on?
What is spit "foo bar bar qux " ' '
supposed to do? Split on all the spaces? Just the first one?
spit "foo bar bar qux " ' '
["foo"; "bar" ; "bar"; "qux"]
I need split for parsing the input I read from the file
I already took care of chars
Here's split that works with lists:
let split lst x =
let rec loop acc = function
| [] -> [acc]
| y :: ys ->
if x = y then
acc :: loop [] ys
else
loop (acc @ [y]) ys
in
loop [] lst
;;
Example:
# split [1;2;4;0;5;6;0;8;7] 0 ;;
- : int list list = [[1; 2; 4]; [5; 6]; [8; 7]]
# split ["H";"e";"l";"l";"o";" ";"w";"o";"r";"l";"d"] " " ;;
- : string list list = [["H"; "e"; "l"; "l"; "o"]; ["w"; "o"; "r"; "l"; "d"]]
This should be easy to adapt to strings and characters.
Yes that works, but I have to use explode
let split lst x =
let rec loop acc = function
| [] -> [acc]
| y :: ys ->
if x = y then
acc :: loop [] ys
else
loop (acc @ [y]) ys
in
loop [] (explode lst)
Thank you so much!
Whatever you're doing, it seems this will be inefficient. Perhaps it doesn't matter.