برنامه نویسی

Tsonnet #5 – JSON چاپ زیبا

به سری TSONNET خوش آمدید!

در پست قبلی ، ما انواع عددی را دوباره اصلاح کردیم:

امروز ، من می خواهم با لایه ارائه مقابله کنم: چاپ کننده خروجی JSON.

در print عملکرد در واقع چاپ “JSON” نیست ، فقط بازنمایی های ارزش خام.

Yojson یک انتخاب بسیار رایج برای تجزیه JSON در OCAML است.

بیایید آن را با OPAM نصب کنیم:

$ opam install yojson
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

و آن را به وابستگی های ما در پروژه Dune اضافه کنید:

Diff-Git A/Dune-Project B/Dune-Project INDEX 383BBEF..775351B 100644
--- A/Dune Project
+++ b/dune-project
-33،7 +33،9
   (bisect_ppx (و: با آزمون
- (> = 2.8.3))))
+ (> = 2.8.3))) + (yojson + (> = 2.2.2))
  (برچسب ها (کامپایلر مترجم JSONNET)))
Diff -git a/tsonnet.opam b/tsonnet.opam شاخص 31C792C..16783C3 100644
--- a/tsonnet.opam
+++ b/tsonnet.opam
-15،6 +15،7 بستگی دارد: [
   "menhir" {= "20240715"}
   "alcotest" {with-test & >= "1.8.0"}
   "bisect_ppx" {with-test & >= "2.8.3"}
+  "yojson" {>= "2.2.2"}
   "odoc" {with-doc}
 ]
 ساخت: [
Enter fullscreen mode

Exit fullscreen mode

The opam file is automatically updated by dune.

Before using the library, we need to specify that the lib config will depend on yojson:

diff --git a/lib/dune b/lib/dune
index 3452131..05c4dc3 100644
--- a/lib/dune
+++ b/lib/dune
@@ -1,7 +1,8 @@
 (library
  (name tsonnet)
  (instrumentation
-  (backend bisect_ppx)))
+  (backend bisect_ppx))
+ (libraries yojson))

 (menhir
  (modules parser))
Enter fullscreen mode

Exit fullscreen mode

To get rid of the printfs, we need a way of converting a expr to JSON.

Let’s encapsulate the expression conversion in a new module, dedicated to transforming expressions into JSON representation:

diff --git a/lib/json.ml b/lib/json.ml
new file mode 100644
index 0000000..886d2bd
--- /dev/null
+++ b/lib/json.ml
@@ -0,0 +1,17 @@
+open Ast
+
+let rec expr_to_yojson : (expr -> Yojson.t) = function
+  | Number n ->
+    (match n with
+    | Int i -> `Int i
+    | Float f -> `Float f)
+  | Null -> `Null
+  | Bool b -> `Bool b
+  | String s -> `String s
+  | Array values -> `List (List.map expr_to_yojson values)
+  | Object attrs ->
+    let eval' = fun (k, v) -> (k, expr_to_yojson v)
+    in `Assoc (List.map eval' attrs)
+  | _ -> failwith "value type not representable as JSON"
+
+let expr_to_string expr = Yojson.pretty_to_string (expr_to_yojson expr)
Enter fullscreen mode

Exit fullscreen mode

The new Json module will implement two functions. The function expr_to_yojson basically maps our expr types to Yojson.t. The function expr_to_string will use the previous function to convert from Yojson.t to string.

If eventually we decide to change the way we want to render JSON, like using a more performant library, for example, we refactor this module and there’s no need to update anywhere else — maybe the tests.

With that, we can remove our messy hand-written print function:

diff --git a/lib/tsonnet.ml b/lib/tsonnet.ml
index 832b56c..a528488 100644
--- a/lib/tsonnet.ml
+++ b/lib/tsonnet.ml
@@ -6,24 +6,6 @@ let parse (s: string) : expr =
   let ast = Parser.prog Lexer.read lexbuf in
   ast

-let rec print = function
-  | Number n ->
-    (match n with
-    | Int i -> Printf.sprintf "%d" i
-    | Float f -> Printf.sprintf "%f" f)
-  | Null -> Printf.sprintf "null"
-  | Bool b -> Printf.sprintf "%b" b
-  | String s -> Printf.sprintf "\"%s\"" s
-  | Array values -> Printf.sprintf "[%s]"(string.concat" ، "(لیست. مقادیر چاپی)) - | شیء شی -> - اجازه دهید print_key_val = تابع - | (k ، v) -> printf.sprintf" \ "٪ s \": ٪ s " k (print v) - in - printf.sprintf "{٪ s}" ( - string.concat "،" (list.map print_key_val جاذبه) -) - | _ -> failwith "اجرا نشده" -
 اجازه دهید تفسیر_BIN_OP (OP: BIN_OP) (N1: شماره) (N2: شماره): Expr = Match OP ، N1 ، N2 با | اضافه کردن ، (int a) ، (int b) -> شماره (int (a + b))
-52،7 +34،7 اجازه دهید تفسیر (e: expr): expr = | (شماره V1) ، (شماره V2) -> تفسیر_BIN_OP OP V1 V2 | _ -> FailWith "عملیات باینری نامعتبر"

-let Run (S: String): expr =
+اجازه دهید اجرا شود (s: string) =
   اجازه دهید AST = تجزیه در let let letuated_ast = تفسیر AST در
- ارزیابی_ست
+ json.expr_to_string ارزیابی_ast
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

ماژول کتابخانه Tsonnet بسیار تمیز تر به نظر می رسد!

همانطور که ما در حال ساختن run عملکرد بازگشت a string، ما باید به روز کنیم main.ml بر این اساس:

diff --git a/bin/main.ml b/bin/main.ml
index 78e9bb8..723b106 100644
--- a/bin/main.ml
+++ b/bin/main.ml
@@ -7,8 +7,8 @@ let run_parser filename =
   let input_channel = open_in filename in
   let content = really_input_string input_channel (in_channel_length input_channel) in
   close_in input_channel;
-  let expr = Tsonnet.run content in
-  print_endline (Tsonnet.print expr)
+  let result = Tsonnet.run content in
+  print_endline result

 let () =
   Arg.parse spec_list anonymous_fun usage_msg;
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

و تست های CRAM نیز باید خروجی را منعکس کنند:

diff --git a/bin/usage.t b/bin/usage.t
index a8fc82f..b488efe 100644
--- a/bin/usage.t
+++ b/bin/usage.t
@@ -7,7 +7,14 @@ Using the Tsonnet program:
   "Hello, world!"

   $ tsonnet ../samples/literals/object.jsonnet
-  {"int_attr": 1, "float_attr": 4.200000, "string_attr": "Hello, world!", "null_attr": null, "array_attr": [1, false, {}], "obj_attr": {"a": true, "b": false, "c": {"d": [42]}}}
+  {
+    "int_attr": 1,
+    "float_attr": 4.2,
+    "string_attr": "Hello, world!",
+    "null_attr": null,
+    "array_attr": [ 1, false, {} ],
+    "obj_attr": { "a": true, "b": false, "c": { "d": [ 42 ] } }
+  }

   $ tsonnet ../samples/binary_operations.jsonnet
-  44.700000
+  44.7 
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

یکی از ترفندهایی که زندگی ما را بسیار آسان می کند این واقعیت است که Dune ویژگی ای به نام دارد promoteبشر

چه کاری انجام می دهد؟ اگر تست ها اجرا شوند و خروجی صحیح باشد ، اما تفاوت متناقض است ، شما می توانید آن را ترویج کنید ، به این معنی که تفاوت آن را برای شما با یک دستور واحد اعمال می کند:

$ dune runtest --auto-promote
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

دستور بالا آزمایش ها را دوباره اجرا می کند و تفاوت خروجی را در پرونده های مربوطه اعمال می کند.

این فوق العاده مفید است! من در اینجا به جزئیات نمی پردازم ، اما واقعاً توصیه می کنم مستندات متفاوت و تبلیغی را بخوانید.

مراقب باشید ، این می تواند شما را در برابر ابزار ساختمان فعلی خود ناراحت کند – با احتیاط. واقعاً جادو می شود! 😜

این احساس بهتر است که یک خروجی زیبا چاپ شده داشته باشید ، اینطور نیست؟!


با تشکر از شما برای خواندن بیت شاید عاقلانه! برای دریافت پست های جدید درباره TSONNET مشترک شوید.

عکس توسط پیت گودفری در Unsplash

نوشته های مشابه

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

دکمه بازگشت به بالا