13/01/2019, 00:30

Tìm hiểu về gem Dentaku

Dentaku là một trình phân tích cú pháp và đánh giá cho ngôn ngữ công thức toán học và logic cho phép liên kết thời gian chạy của các giá trị với các biến được tham chiếu trong các công thức. Nó được dự định để đánh giá một cách an toàn các biểu thức không đáng tin cậy mà không cần mở các lỗ hổng ...

Dentaku là một trình phân tích cú pháp và đánh giá cho ngôn ngữ công thức toán học và logic cho phép liên kết thời gian chạy của các giá trị với các biến được tham chiếu trong các công thức. Nó được dự định để đánh giá một cách an toàn các biểu thức không đáng tin cậy mà không cần mở các lỗ hổng bảo mật.

Để sử dụng Dentaku, cần thêm gem Dentaku vào Gemfile

#Gemfile
gem "dentaku"

Sau đó chạy bundle install

Lấy một ví dụ đơn giản sử dụng Dentaku:

vari = Dentaku::Calculator.new
vari.evaluate("8 * 7")
#=> 56

Hoặc có thể tham chiếu 1 biến:

vari.evaluate("abc * 7", abc: 8)
#=> 56

Mặc định Dentaku sẽ không phân biệt chữ hoa và chữ thường, nếu các biến giống nhau nó sẽ sử dụng biến sau cùng, Ví dụ:

vari.evaluate("abc * 7", abc: 8, Abc: 7, aBc: 6)
#=> 42

Nếu muốn phân biệt chữ hoa và chữ thường, ez, Ví dụ:

vari = Dentaku::Calculator.new(case_sensitive: true)
vari.evaluate("abc * 7", abc: 8, Abc: 7, aBc: 6)
#=> 56

Có thể lưu trữ giá trị vào các biến để có thể sử dụng lại:

vari.bind(remem: 10)
vari.evaluate("remem + 10")
#=> 20

Method evaluate sẽ trả về nil nếu có lỗi trong công thức. Để bắn ra exception thì sử dụng evaluate!, Ví dụ:

vari.evaluate("10 + x")
#=> nil
vari.evaluate!("10 + x")
#=> Dentaku::UnboundVariableError: Dentaku::UnboundVariableError

Nếu hiệu suất là một mối quan tâm, bạn có thể kích hoạt bộ đệm ẩn AST:

Dentaku.enable_ast_cache!

Dentaku sẽ lưu trữ AST của từng công thức mà nó đánh giá, do đó các đánh giá tiếp theo (ngay cả với các giá trị khác nhau cho các biến) sẽ nhanh hơn nhiều - gần hơn với tốc độ Ruby bản địa gấp 4 lần.

Math: +, -, *, /, %, ^, |, &.

Tất cả các function từ module Math cảu Ruby, bao gồm: SIN, COS, TAN, etc. So sánh: <, >, <=, >=, <>, !=, =

Logic: IF, AND, OR, NOT, SWITCH

Numeric: MIN, MAX, SUM, AVG, COUNT, ROUND, ROUNDDOWN, ROUNDUP

Selections: CASE

String: LEFT, RIGHT, MID, LEN, FIND, SUBSTITUTE, CONCAT, CONTAINS

Nếu các công thức của bạn dựa vào nhau, chúng có thể cần được giải quyết theo một thứ tự cụ thể. Ví dụ: Thu nhập hàng tháng monthly_income của bạn là 50. Để tính thuế thu nhập income_taxes thì cẩn phải tính thu nhập hàng năm trước annual_income, theo dõi đoạn code dưới:

calc = Dentaku::Calculator.new
calc.bind(monthly_income: 50)
need_to_compute = {
  income_taxes: "annual_income / 5",
  annual_income: "monthly_income * 10"
}

Để Dentalu biết đc thứ tự thực hiện các phép tính trên, ta chỉ cần:

calc.solve!(need_to_compute)
#=> {annual_income: 500, income_taxes: 100}

Bạn có thể xem ví dụ sau:

vari.evaluate("abc * 7 /* This is a comment */", abc: 8)
#=> 7

Comments có thể là một dòng hoặc nhiều dòng:

/*
 * This is a multi-line comment
 */

/*
 This is another type of multi-line comment
 */

Bạn có thể tự tạo cho mình 1 function theo ý bạn, Ví dụ:

var = Dentaku::Calculator.new
var.add_function(:pow, :numeric, ->(a, b) { a ** b })
var.evaluate("POW(3,2)")
#=> 9

Mỗi chức năng có thể được đặt bí danh bởi các từ đồng nghĩa. Ví dụ, nó có thể hữu ích nếu ứng dụng của bạn là đa ngôn ngữ.

Dentaku.aliases = {
  round: ['rrrrround!', 'округлить']
}

Dentaku('rrrrround!(8.2) + округлить(8.4)') # the same as round(8.2) + round(8.4)
# 16

Bạn cũng có thể thêm chúng khi khởi tạo Dentaku::Calculator, Ví dụ:

aliases = {
  round: ['rrrrround!', 'округлить']
}
var = Dentaku::Calculator.new(aliases: aliases)
var.evaluate('rrrrround!(8.2) + округлить(8.4)')
# 16

Cảm ơn các bạn đã xem bài viết, hãy để lại comment của bạn cho bài viết của mình, nếu thấy hay hãy upvote, share để được đẹp trai và xinh gái hơn.

0