ocaml hashtbl remove function - ocaml

How come the Hashtbl remove restores the previous binding.
Hashtbl.add t key1
Hashtbl.remove t key1
Hashtbl.remove t key1 => This should do anything but not restore the key1 !
Anyway, how come I can remove something making sure and if it was deleted before then proper flow shall be followed?
val remove : ('a, 'b) t -> 'a -> unit
Hashtbl.remove tbl x removes the current binding of x in tbl, restoring the previous binding if it exists. It does nothing if x is not bound in tbl.

There are two legitimate mode of uses of Hashtbl: always using Hashtbl.replace, which ensures that each key only has one binding in the table, or using the table as a multi-mapping (each key pointing to a list of values) with Hasthbl.add, Hashtbl.find and Hashtbl.find_all.
Please make sure that you understand which mode of use you're interested in. There is no point in adding several bindings to the same key if you don't want to keep old bindings (this can result in performance issues, memory leaks and stack overflows); in that case you should use Hashtbl.replace instead of Hashtbl.add, and Hashtbl.remove will do exactly what you expect.
If you are using the hashtable as a multi-mapping, and want a function that remove all bindings for a key, you can implement it yourslef (code untested):
let rec remove_all tbl key =
if Hashtbl.mem tbl key then begin
Hashtbl.remove tbl key;
remove_all tbl key
end
Edit: I just understood that another way to read your (hard to understand) question is "how can I make sure that there is a key to remove in the table, instead of silently doing nothing when remove is called?". cago provides a code snippet for that, in essence you can use Hashtbl.mem to check that the binding exists when you assume it should exist.

If you use Hashtbl.replace instead of Hashtbl.add you'll replace the current binding of the key in t. So the function Hashtbl.remove will not restore anything.
You can also write your own remove function :
let remove tbl key =
if Hashtbl.mem tbl key then Hashtbl.remove tbl key
else raise Nothing_to_remove_in_the_hashtbl
Hashtbl.replace t key1 value;;
remove t key1;;
remove t key1;; (* raise Nothing_to_remove_in_the_hashtbl *)

Related

Different result in OCaml and ReasonML

There is a case mapping two vectors into a single vector. I expected that the result of both ML should be same. Unfortunately, the result of ReasonML is different. Please help and comment how to fix it.
OCaml
List.map2 (fun x y -> x+y) [1;2;3] [10;20;30];;
[11;;22;;33]
ReasonML
Js.log(List.map2 ( (fun (x,y) => x+y), [1,2,3], [10,20,30]))
[11,[22,[33,0]]]
This is the same result. If you run:
Js.log([11,22,33]);
You'll get:
[11,[22,[33,0]]]
The result is the same, but you're using different methods of printing them. If instead of Js.log you use rtop or sketch.sh, you'll get the output you expect:
- : list(int) = [11, 22, 33]
Js.log prints it differently because it is a BuckleScript binding to console.log, which will print the JavaScript-representation of the value you give to it. And lists don't exist in JavaScript, only arrays do.
The way BuckleScript represents lists is pretty much the same way it is done natively. A list in OCaml and Reason is a "cons-cell", which is essentially a tuple or a 2-element array, where the first item is the value of that cell and the last item is a pointer to the next cell. The list type is essentially defined like this:
type list('a) =
| Node('a, list('a))
| Empty;
And with this definition could have been constructed with:
Node(11, Node(22, Node(33, Empty)))
which is represented in JavaScript like this:
[11,[22,[33,0]]]
^ ^ ^ ^
| | | The Empty list
| | Third value
| Second value
First value
Lists are defined this way because immutability makes this representation very efficient. Because we can add or remove values without copying all the items of the old list into a new one. To add an item we only need to create one new "cons-cell". Using the JavaScript representation with imagined immutability:
const old = [11,[22,[33,0]]];
const new = [99, old];
And to remove an item from the front we don't have to create anything. We can just get a reference to and re-use a sub-list, because we know it won't change.
const old = [11,[22,[33,0]]];
const new = old[1];
The downside of lists is that adding and removing items to the end is relatively expensive. But in practice, if you structure your code in a functional way, using recursion, the list will be very natural to work with. And very efficient.
#Igor Kapkov, thank you for your help. Base on your comment, I found a pipeline statement in the link, there is a summary.
let a = List.map2 ( (fun (x,y) => x+y), [1,2,3], [10,20,30] )
let logl = l => l |> Array.of_list |> Js.log;
a |> logl
[11,22,33]

Store a list in Erlang ETS

I am trying to insert a list into ETS to pull out later and for some reason it is saying it is a bad arg. I'm not sure if I'm inserting it incorrectly.
Is it just not possible to insert a list into ETS?
The offending line is ets:insert(table, [{parsed_file, UUIDs}]).
Here is the code:
readUUID(Id, Props) ->
fun () ->
%%TableBool = proplists:get_value(table_bool, Props, <<"">>),
[{_, Parsed}] = ets:lookup(table, parsed_bool),
case Parsed of
true ->
{uuids, UUIDs} = ets:lookup(table, parsed_bool),
Index = random:uniform(length(UUIDs)),
list_to_binary(lists:nth(Index, UUIDs));
false ->
[{_, Dir}] = ets:lookup(table, config_dir),
File = proplists:get_value(uuid_file, Props, <<"">>),
UUIDs = parse_file(filename:join([Dir, "config", File])),
ets:insert(table, [{parsed_file, {uuids, UUIDs}}]),
ets:insert(table, [{parsed_bool, true}]),
Index = random:uniform(length(UUIDs)),
list_to_binary(lists:nth(Index, UUIDs))
end
end.
parse_file(File) ->
{ok, Data} = file:read_file(File),
parse(Data, []).
parse([], Done) ->
lists:reverse(Done);
parse(Data, Done) ->
{Line, Rest} = case re:split(Data, "\n", [{return, list}, {parts, 2}]) of
[L,R] -> {L,R};
[L] -> {L,[]}
end,
parse(Rest, [Line|Done]).
If you create the table in the same proc with something like
ets:new(table, [set, named_table, public]).
then you should be ok. Default permissions are protected, where only creating process can write.
As a follow on to my comment about ets tables only containing tuples and what ets:lookup/2 returns the following line in your code:
{uuids, UUIDs} = ets:lookup(table, parsed_bool),
WILL ALWAYS GENERATE AN ERROR as ets:lookup/2 returns a list. The call 3 lines above may succeed. It seems like you are trying to do 2 lookups in table with key parsed_bool and expect to get 2 different types of answers: {_, Parsed} and {uuids, UUIDs}. Remember that ETS does not provide key-value tables but tables of tuples where one of the elements, default the first, is the key and doing ets:lookup/2 returns a list of the tuples with that key. How many you can get back depends on the properties of the table.
Check out the documentation of ETS tables.

converting list to tuple

I have few command-line options (5 for example) and I want to convert them to tuple. The problem is that I expect them to appear in correct order, so tuple can be easily built from list using pattern-match, but in real life options can be provided in random order, so I don't know if head of the list contain Verbose option or log file name?
I tried to think how to do that using continuation-passing style, however nothing useful comes into my mind.
Is that ever possible?
I think that I can "sort" the list to have it in predicted order, but it does not look good.
Also I could get rid of the tuple and create data record - however that will still lead up to checking the type of attribute and set the correct field of the record. Still a lot of typing.
Given what you describe, I think you have two options. Of the two, I would say that converting to a dictionary would be easiest, but converting to a Tuple would work and only be a little clumsy
So, take this definition:
options :: [OptDescr (String, String)]
options = [Option ['a'] ["alpha"] (ReqArg (\a -> ("alpha", a)) "empty") "",
Option ['b'] ["beta"] (ReqArg (\a -> ("beta", a)) "empty") "",
Option ['g'] ["gamma"] (ReqArg (\a -> ("gamma", a)) "empty") ""]
main = do
args <- getArgs
let (opts, nonopts, errs) = getOpt Permute options args
putStrLn $ show opts
From this, a couple of my example outputs are:
[("beta","b"),("alpha","a")]
[("alpha","a"),("gamma","g"),("beta","b")]
and so on. Same order as on the command line. But, because of the way I set it up above, I basically have an association list, so... if I in particular want a Tuple that has the values (alpha, beta, gamma), then my best option is...
(lookup "alpha" opts, lookup "beta" opts, lookup "gamma" opts)
You resulting data type would be (Maybe String, Maybe String, Maybe String), in the order of "alpha", "beta", and "gamma".

Yesod: Is it possible to to iterate a haskell list in Julius?

I have a list of coordinates that I need to put on map. Is it possible in julius to iterate the list ? Right now I am creating an hidden table in hamlet and accessing that table in julius which does not seem to be an ideal solution.
Could some one point to a better solution ? Thanks.
edit: Passing a JSON string for the list (which can be read by julius) seems to solve my problem.
As far as I know, you can't directly iterate over a list in julius. However, you can use the Monoid instance for the Javascript type to accomplish a similar effect. For example:
import Text.Julius
import Data.Monoid
rows :: [Int] -> t -> Javascript
rows xs = mconcat $ map row xs
where
row x = [julius|v[#{show x}] = #{show x};
|]
Then you can use rows xs wherever you'd normally put a julius block. For example, in ghci:
> renderJavascript $ rows [1..5] ()
"v[1] = 1;\nv[2] = 2;\nv[3] = 3;\nv[4] = 4;\nv[5] = 5;\n"

Lookup tables in OCaml

I would like to create a lookup table in OCaml. The table will have 7000+ entries that, upon lookup (by int), return a string. What is an appropriate data structure to use for this task? Should the table be externalized from the base code and if so, how does one go about "including" the lookup table to be accessible from his/her program?
Thanks.
If the strings are addressed using consecutive integers you could use an array.
Otherwise you can use a hash table (non-functional) or a Map (functional). To get started with the Map try:
module Int =
struct
type t = int
let compare = compare
end ;;
module IntMap = Map.Make(Int) ;;
If the table is too large to store in memory, you could store it in an external database and use bindings to dbm, bdb, sqlite,...
let table : (int,string) Hashtbl.t = Hashtbl.create 8192
To store the table in a separate file (e.g. as an array), simply create a file strings.ml with the content:
let tbl = [|
"String 0";
"String 1";
"String 2";
...7000 more...
|]
Compile this with:
ocamlc -c strings.ml
As explained in the manual, this defines a module Strings that other Ocaml modules can reference. For example, you can start a toplevel:
ocaml strings.cmo
And lookup a string by accessing a particular position in the array:
Strings.tbl.(1234) ;;