#ocaml #command-line-arguments #record
#ocaml #аргументы командной строки #запись
Вопрос:
Это немного смущает, но мне показали программу OCaml, в которой я знаю, что хочу делать, но я не могу найти документацию, которая помогла бы мне написать то, что я хочу, в правильном синтаксисе, поскольку я никогда раньше не использовал этот язык.
Я внес довольно много рабочих изменений в программу, и это последнее изменение, которое мне нужно внести, и я не могу его обработать!
Существует запись определенного типа (используемый синтаксис меня сбил с толку) с именем caps_default
:
let caps_default =
{
browserName = Firefox ;
version = "" ;
platform = ANY ;
username = "" ;
accessKey = "" ;
javascriptEnabled = true
}
;;
Затем эти переменные определяются для получения аргументов командной строки:
exception Incorrect_cmdline of string option
;;
let browser_name = ref ""
and hub_url_opt = ref ""
and target_url_opt = ref ""
and xml_out_string = ref ""
and user_name = ref ""
and access_key = ref ""
;;
Я добавил два новых аргумента с именами ‘username’ и ‘accessKey’, и я хочу добавить их в запись «caps».
Продолжая, здесь анализируются аргументы командной строки:
let (target_url, hub_url, caps, xml_out) =
try
parse_cmdline
[
( noshort , "browser-name" , None, (atmost_once browser_name (Incorrect_cmdline (Some "browser-name"))) ) ;
( noshort , "hub-url" , None, (atmost_once hub_url_opt (Incorrect_cmdline (Some "hub-url"))) ) ;
( noshort , "target-url" , None, (atmost_once target_url_opt (Incorrect_cmdline (Some "target-url"))) ) ;
( noshort , "xml-output" , None, (atmost_once xml_out_string (Incorrect_cmdline (Some "xml-output"))) ) ;
( noshort , "username" , None, (atmost_once user_name (Incorrect_cmdline (Some "username"))) ) ;
( noshort , "accessKey" , None, (atmost_once access_key (Incorrect_cmdline (Some "accessKey"))) ) ;
( noshort , "help" , Some (fun s -> raise (Incorrect_cmdline None)) , None );
]
( fun x -> raise (Incorrect_cmdline None)) ;
ignore (List.map
(fun s -> if BatString.is_empty !s then raise (Incorrect_cmdline None) else () )
[ browser_name ; hub_url_opt ; target_url_opt ] );
let target_url =
try
Neturl.parse_url !target_url_opt
with
Neturl.Malformed_URL ->
raise (Incorrect_cmdline (Some ("Invalid target url: " ^ !target_url_opt)))
and hub_url =
try
Neturl.parse_url !hub_url_opt
with
Neturl.Malformed_URL ->
raise (Incorrect_cmdline (Some ("Invalid hub url: " ^ !hub_url_opt)))
and xml_out =
if BatString.is_empty !xml_out_string
then fun s -> ignore s
else
let chan = open_out !xml_out_string in
(fun xml ->
output_string chan (Xml.to_string xml) ;
close_out chan )
(* Continued below *)
Я хочу использовать мои новые параметры аргумента командной строки username
и accessKey
, присвоенные переменным user_name
и access_key
, для передачи в caps
запись, которая определена в назначениях let ниже:
(* Continued from above *)
and caps =
{ caps_default with username = !user_name } (* My addition *)
{ caps_default with accessKey = !access_key } (* My addition *)
match !browser_name with (* This switch is original and worked *)
| "firefox" -> { caps_default with browserName = Firefox }
| "chrome" -> { caps_default with browserName = Chrome }
| "html_unit" -> { caps_default with browserName = HtmlUnit }
| "ie" -> { caps_default with browserName = InternetExplorer }
| "iphone" -> { caps_default with browserName = IPhone }
| _ -> raise (Incorrect_cmdline (Some ("Invalid browser name: " ^ !browser_name)))
in
(target_url, hub_url, caps, xml_out)
with
Incorrect_cmdline arg ->
(match arg with | None -> () | Some msg -> print_endline msg) ;
print_synopsis () ;
exit 48
;; (* End of relevant code *)
Experimenting I could comment out the original author’s switch for —browser-name and assign a single value by putting a solemn line surrounded by curly braces:
and caps=
{ caps_default with browserName = Chrome } (* Hard-coding a Chrome choice *)
or
and caps=
{ caps_default with username = !user_name } (* Sharing only --username *)
or
and caps=
{ caps_default with accessKey = !access_key } (* Sharing only --accessKey *)
Can someone point me in the correct direction? I want to keep the switch the original author wrote but also transmit the username
and accessKey
strings to the caps
record on top of that. Can I change the caps
object later? Can I modify default_caps
beforehand and then copy it to caps
?
This code is only run once per execution, so modifying the default_caps
object is of absolutely no concern, even if it’s not very kosher to do so.
Thanks for any assistance!
Update
Numerous thanks to Dr. Scofield’s assistance so far. Curiously I am now being met with a slightly different error complaining about what I can only assume is a mis-match of type. Here is the content of the error:
File "tester.ml", line 110, characters 40-47:
Error: This expression has type Selenium.Json_client.capabilities
but an expression was expected of type Selenium.Json_client.browser
Строка 110
{ caps_default with browserName = browser;
в фрагменте кода мистера Скофилда 40-47 browser
.
Определение типа default_caps
‘s capabilities
как таковое:
type capabilities =
{
browserName : browser ;
version : string ;
platform : platform ;
javascriptEnabled : bool ;
username : string ;
accessKey : string ;
}
И аналогично, тип browser
:
type browser =
Chrome | Firefox | HtmlUnit | InternetExplorer | IPhone
mli (интерфейс, правильно?) определения идентичны, если это важно.
Обновление, часть 2
Небольшая коррекция необходима только для упрощения кода из этого:
match !browser_name with
| "firefox" -> { caps_default with browserName = Firefox }
| "chrome" -> { caps_default with browserName = Chrome }
| "html_unit" -> { caps_default with browserName = HtmlUnit }
| "ie" -> { caps_default with browserName = InternetExplorer }
| "iphone" -> { caps_default with browserName = IPhone }
| _ -> raise (Incorrect_cmdline (Some ("Invalid browser name: " ^ !browser_name)))
к этому:
match !browser_name with
| "firefox" -> Firefox
| "chrome" -> Chrome
| "html_unit" -> HtmlUnit
| "ie" -> InternetExplorer
| "iphone" -> IPhone
| _ -> raise (Incorrect_cmdline (Some ("Invalid browser name: " ^ !browser_name)))
Прежде чем продолжить:
in
{ caps_default with browserName = browser;
username = !user_name;
accessKey = !access_key;
}
Ответ №1:
Возможно, вам придется изучить немного больше OCaml, чем вы хотите, чтобы сделать это 🙂
Названный объект caps_default
является записью, то есть он имеет тип записи. Вам нужно будет найти определение этого типа записи и добавить к нему свои новые возможности.
Обновить
Хорошо, у вас уже был исправлен тип записи. Вот некоторый код
and caps =
let browser =
match !browser_name with
| "firefox" -> Firefox
| "chrome" -> Chrome
| "html_unit" -> HtmlUnit
| "ie" -> InternetExplorer
| "iphone" -> IPhone
| _ ->
raise (Incorrect_cmdline
(Some ("Invalid browser name: " ^ !browser_name)))
in
{ caps_default with browserName = browser;
username = !user_name;
accessKey = !access_key;
}
in
(target_url, hub_url, caps, xml_out)
(Излишне говорить, что это непроверенный код.)
Обновление 2
(Исправлено написание user_name
, спасибо.)
Комментарии:
1. Ах, я подозревал, что это запись, я уже это сделал, и, к счастью, я дал им оба строковых типа. Увы, я все еще не понимаю, как правильно назначить полученные аргументы командной строки
caps
и поддерживать существующий коммутатор.2. Пока это отличная помощь. Но, что любопытно, я столкнулся с еще одной проблемой, связанной с неправильным соответствием типов. Я обновил исходный вопрос новой частью в конце.
3. В моем исходном коде были ошибки. Посмотрите на приведенный выше код еще раз. (Извините.)
4. А-ха! Да, я вижу, где что-то пошло не так. Большое вам спасибо, мистер Скофилд, похоже, это отлично подходит для моих нужд. Я бы проголосовал за ваш ответ, но, видимо, мне нужно еще 2 представителя, чтобы сделать это, хах. PS: Еще одно крошечное исправление — это
!username
когда оно должно быть!user_name
для всех, кто может увидеть это позже в качестве руководства.