Permalink
Switch branches/tags
Nothing to show
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
66 lines (58 sloc) 1.78 KB
open Core.Std
open Async.Std
(* Generate a DuckDuckGo search URI from a query string *)
let query_uri query =
let base_uri = Uri.of_string "http://api.duckduckgo.com/?format=json" in
Uri.add_query_param base_uri ("q", [query])
(* part 1 *)
(* Extract the "Definition" or "Abstract" field from the DuckDuckGo results *)
let get_definition_from_json json =
match Yojson.Safe.from_string json with
| `Assoc kv_list ->
let find key =
begin match List.Assoc.find kv_list key with
| None | Some (`String "") -> None
| Some s -> Some (Yojson.Safe.to_string s)
end
in
begin match find "Abstract" with
| Some _ as x -> x
| None -> find "Definition"
end
| _ -> None
(* part 2 *)
(* Execute the DuckDuckGo search *)
let get_definition word =
Cohttp_async.Client.get (query_uri word)
>>= fun (_, body) ->
Pipe.to_list (Cohttp_async.Body.to_pipe body)
>>| fun strings ->
(word, get_definition_from_json (String.concat strings))
(* part 3 *)
(* Print out a word/definition pair *)
let print_result (word,definition) =
printf "%s\n%s\n\n%s\n\n"
word
(String.init (String.length word) ~f:(fun _ -> '-'))
(match definition with
| None -> "No definition found"
| Some def ->
String.concat ~sep:"\n"
(Wrapper.wrap (Wrapper.make 70) def))
(* part 4 *)
(* Run many searches in parallel, printing out the results after they're all
done. *)
let search_and_print words =
Deferred.all (List.map words ~f:get_definition)
>>| fun results ->
List.iter results ~f:print_result
(* part 5 *)
let () =
Command.async_basic
~summary:"Retrieve definitions from duckduckgo search engine"
Command.Spec.(
empty
+> anon (sequence ("word" %: string))
)
(fun words () -> search_and_print words)
|> Command.run