1. পরিচিতি

Expr হল গো ভাষার জন্য প্রস্তুত একটি ডায়নামিক কনফিগারেশন সলিউশন, যা সহজ সিনট্যাক্স এবং শক্তিশালী কর্মক্ষমতা বৈশিষ্ট্যের জন্য পরিচিত। Expr এক্সপ্রেশন ইঞ্জিনের কোর বিশ্বাস করে সুরক্ষা, গতি এবং সহজবোধ্যতায়, এটি অ্যাক্সেস নিয়ন্ত্রণ, ডেটা ফিল্টারিং, এবং সম্পদ ব্যবস্থাপনা প্রসঙ্গে উপযোগী। গোতে প্রযোগ করার সময়, Expr অ্যাপ্লিকেশনগুলির প্রতিষ্ঠানিক নিয়ম পরিচালনার ক্ষমতা অতিক্রম করে। অন্য ভাষার ইন্টারপ্রেটার বা স্ক্রিপ্ট ইঞ্জিনের বিপরীতে, Expr প্রাথমিক ধরনের পরীক্ষা নকল এবং বাইটকোড জেনারেট করে পরিসংখ্যানের মন্তব্য করে, অভিন্যাস এবং সুরক্ষা উভয় নিশ্চিত করে।

2. Expr ইনস্টল করা

আপনি গো ভাষার প্যাকেজ ম্যানেজমেন্ট টুল go get ব্যবহার করে Expr এক্সপ্রেশন ইঞ্জিন ইনস্টল করতে পারেন:

go get github.com/expr-lang/expr

এই কমান্ডটি এক্সপ্রেশন ইঞ্জিন লাইব্রেরি ফাইলগুলি ডাউনলোড করবে এবং তারা আপনার গো প্রজেক্টে ইনস্টল করে, যাতে আপনি আপনার গো কোডে ইমপোর্ট করতে পারেন।

3. দ্রুত শুরু

3.1 সাধারণ এক্সপ্রেশন কম্পাইল এবং এক্সিকিউট করা

একটি সাধারণ উদাহরণ দিয়ে শুরু করা যাক: একটি সাধারণ এক্সপ্রেশন লেখা, এটি কম্পাইল করা, এবং তারপর রান করে ফলাফল প্রাপ্ত করা।

package main

import (
	"fmt"
	"github.com/expr-lang/expr"
)

func main() {
	// একটি বুনিয়াদী যোগ এক্সপ্রেশন কম্পাইল করা
	program, err := expr.Compile(`2 + 2`)
	if err != nil {
		panic(err)
	}

	// নমোনা মিলিয়ে তৈরি এনভায়রনমেন্ট ছাড়া কম্পাইলড এক্সপ্রেশন রান করা 
	output, err := expr.Run(program, nil)
	if err != nil {
		panic(err)
	}

	// ফলাফল মুদ্রণ
	fmt.Println(output)  // ৪ আউটপুট হবে
}

এই উদাহরণে, এক্সপ্রেশন 2 + 2 এক্সিকিউট যোগ্য বাইটকোডে কম্পাইল হয়, এবং তারপর আউটপুট তৈরি করতে ব্যবহৃত হয়।

3.2 ভেরিয়েবল এক্সপ্রেশন ব্যবহার

পরবর্তী, আমরা একটি ভেরিয়েবল ধারণ করা বেশির্ভাবেঃ একটি এনভায়রনমেন্ট তৈরি করা যা ভেরিয়েবল সম্পর্কে এবং এই ভেরিয়েবল ব্যবহার করা সম্পর্কে একটি এক্সপ্রেশন লিখা।

package main

import (
	"fmt"
	"github.com/expr-lang/expr"
)

func main() {
	// ভেরিয়েবল সহ একটি উত্পাদন তৈরি করা
	env := map[string]interface{}{
		"foo": 100,
		"bar": 200,
	}

	// এনভায়রনমেন্ট থেকে ভেরিয়েবল ব্যবহার করা একটি এক্সপ্রেশন কম্পাইল করা 
	program, err := expr.Compile(`foo + bar`, expr.Env(env))
	if err != nil {
		panic(err)
	}

	// এক্সপ্রেশন রান করা
	output, err := expr.Run(program, env)
	if err != nil {
		panic(err)
	}

	// ফলাফল মুদ্রণ
	fmt.Println(output)  // ৩০০ আউটপুট হবে
}

এই উদাহরণে, এনভায়রনমেন্ট env ভেরিয়েবল foo এবং bar রয়েছে। এক্সপ্রেশন foo + bar কম্পাইলেশনের সময় ভেরিয়েবল গুলির প্রকার ধারণ করে, এবং রানটাইমে এই ভেরিয়েবলগুলির মান ব্যবহার করে এক্সপ্রেশনের ফলাফল মূল্যায়ন করতে।

4. ডিটেলে Expr সিনটেক্স

4.1 ভেরিয়েবল এবং লিটারেল

Expr এক্সপ্রেশন ইঞ্জিন সাধারণ ডাটা ধরনের লিটারেল, যথাযথ সংখ্যা, স্ট্রিং এবং বুলিয়ান মান নিয়ে কাজ করতে পারে। লিটারেল হল কোডে সরাসরি লিখিত ডেটা মান, উদাহরণ: 42, "hello", এবং true

সংখ্যা

Expr এ, আপনি সরাসরি পূর্ণসংখ্যা এবং দশমিক সংখ্যা লিখতে পারেন:

42      // পূর্ণসংখ্যা 42 প্রদর্শন করে 
3.14    // দশমিক সংখ্যা 3.14 প্রদর্শন করে

স্ট্রিং

স্ট্রিং লিটারেল ডাবল কোট " বা ব্যাকটিক `` দ্বারা ঘোষিত হয়। উদাহরণ:

"hello, world" // ডাবল কোটে ঘোষিত স্ট্রিং, ওয়া escape ক্যারেক্টার সমর্থন করে 
`hello, world` // ব্যাকটিক ল্যাহমেন্ট দ্বারা ঘোষিত স্ট্রিং, মুক্তি অক্ষরের সমর্থন ছাড়াই স্ট্রিং ফরম্যাট রক্ষা করে

বুলিয়ান

এখানে দুইটি বুলিয়ান মান আছে, true এবং false, যা সত্য এবং মিথ্যা প্রদর্শন করে:

true   // বুলিয়ান সত্যের মান
false  // বুলিয়ান মিথ্যা মান

ভেরিয়েবল

Expr একেবারে এনভায়রনমেন্টে ভেরিয়েবলের সংজ্ঞা অনুমতি দেয় এবং তারপর প্রকাশ যাচ্ছে। উদাহরণ:

env := map[string]interface{}{
    "age": 25,
    "name": "Alice",
}

তাহলে এক্সপ্রেশনে, আপনি age এবং name উল্লেখ করতে পারেন।

age > 18  // চেক করুন যে বয়স ১৮ এর চেয়ে বড়
name == "Alice"  // নাম "Alice" এর সমান কি না সে তৈরি

4.2 অপারেটর

Expr এক্সপ্রেশন ইঞ্জিন ধারণকে ধরে পরিযোজ্য অপারেটর, যেমন গণিত অপারেটর, যুক্তিসম্বন্ধী অপারেটর, তুলনা অপারেটর, এবং পোষাক অপারেটর ইত্যাদি।

গাণিতিক ও তার্কিক অপারেটরস

গাণিতিক অপারেটরস এর মধ্যে যোগ (+), বিয়োগ (-), গুণ (*), ভাগ (/), এবং ভাগশেষ (%) রয়েছে। তার্কিক অপারেটরস এর মধ্যে লজিক্যাল AND (&&), লজিক্যাল OR (||), এবং লজিক্যাল NOT (!) রয়েছে, উদাহরণস্বরূপ:

2 + 2 // ফলাফল 4 হবে
7 % 3 // ফলাফল 1 হবে
!true // ফলাফল false হবে
age >= 18 && name == "Alice" // চেক করুন যদি বয়স 18 এর চেয়ে কম না এবং নাম "Alice" এর সমান হয়

তুলনা অপারেটরস

তুলনা অপারেটরস এর মধ্যে সমান (==), সমান নয় (!=), কম (<), কম বা সমান (<=), বেশি (>), এবং বেশি বা সমান (>=) রয়েছে, যার মাধ্যমে দুটি মান তুলনা করা হয়:

age == 25 // চেক করুন যদি বয়স 25 এর সমান হয়
age != 18 // চেক করুন যদি বয়স 18 এর সমান না হয়
age > 20  // চেক করুন যদি বয়স 20 এর চেয়ে বেশি হয়

সেট অপারেটরস

Expr এর মধ্যে কিছু অপারেটরস রয়েছে যা সেট সঙ্গে কাজ করার জন্য, উদাহরণস্বরূপ in যা দিয়ে চেক করা যায় কোন উপাদানটি সেটে আছে কিনা। সেটগুলি হতে পারে অ্যারে, স্লাইস, বা ম্যাপ:

"user" in ["user", "admin"]  // true, কারণ "user" অ্যারেতে আছে
3 in {1: true, 2: false}     // false, কারণ 3 ম্যাপে কী নয়

এছাড়াও, কিছু উন্নত সেট অপারেটর ফাংশন রয়েছে, যেমন all, any, one, এবং none, যা অনামোয় ফাংশন (ল্যাম্বডা) ব্যবহার করে।

all(tweets, {.Len <= 240})  // চেক করুন যে সমস্ত টুইটের লেন ক্ষেত্র 240 ছাড়া না করে
any(tweets, {.Len > 200})   // চেক করুন কি টুইটের মধ্যে কোন লেন ক্ষেত্র 200 এর চেয়ে বেশি

সদস্য অপারেটর

Expr এর অভ্যন্তরীণ ভাষায়, সদস্য অপারেটরটি আমাদেরকে Go ভাষার struct এর বৈশিষ্ট্যগুলির অ্যাক্সেস করার সুযোগ দেয়। এই বৈশিষ্ট্য দ্বারা Expr এর কমপ্লেক্স ডেটা স্ট্রাকচার সরাসরি ম্যানিপুলেট করার সুবিধা প্রদান করে।

সদস্য অপারেটরটি খুব সহজ, শুধুমাত্র প্রপার্টি নামের পরে . অপারেটরটি ব্যবহার করুন। উদাহরণস্বরূপ, যদি আমাদের নিম্নলিখিত struct থাকে:

type User struct {
    Name string
    Age  int
}

তাহলে আপনি নিম্নলিখিত একটি চলাচল লিখতে পারেন যেখানে User ডেটা পরিস্থিতির Name প্রপার্টি অ্যাক্সেস করতে:

env := map[string]interface{}{
    "user": User{Name: "Alice", Age: 25},
}

code := `user.Name`

program, err := expr.Compile(code, expr.Env(env))
if err != nil {
    panic(err)
}

output, err := expr.Run(program, env)
if err != nil {
    panic(err)
}

fmt.Println(output) // আউটপুট: Alice

nil মান নিয়ন্ত্রণ

বৈশিষ্ট্য অ্যাক্সেস করার সময়, আপনি যেকোনো স্থিতিতে পাবেন যে অবজেক্টটি nil হয়ে যায়। Expr তাই স্বীকৃতি প্রদান করে যে, যদি স্ট্রাকচার বা সনাক্ত প্রপার্টি nil হয়, তাহলে সে রানটাইম প্যানিক ত্রুটি না থেকে নিয়ন্ত্রণ দেবে।

?. অপারেটরটি ব্যবহার করে বৈশিষ্ট্য অ্যাক্সেস করুন। যদি অবজেক্টটি nil হয়, তবে এটি ত্রুটি না পেতে প্রতিস্থাপন হবে।

author.User?.Name

সমতুল্য অভিব্যক্তি

author.User != nil ? author.User.Name : nil

?? অপারেটরটি প্রাথমিকভাবে ডিফল্ট মান ফেরত আনার জন্য ব্যবহার করা হয়:

author.User?.Name ?? "অজানা"

সমতুল্য অভিব্যক্তি

author.User != nil ? author.User.Name : "অজানা"

পাইপ অপারেটর

Expr এর পাইপ অপারেটর (|) হলো একটি অভিব্যক্তির ফলাফল অন্য একটি অভিব্যক্তিতে প্যারামিটার হিসেবে পাঠানোর জন্য ব্যবহৃত হয়। এটি Unix shell এর পাইপ অপারেশনের মতো, একাধিক ফাংশনাল মডিউলকে একসাথে চেইন করে প্রসেসিং পাইপলাইন তৈরি করতে দেয়। Expr এ এটি ব্যবহার করা হয় আরও স্পষ্ট এবং সংক্ষিপ্ত অভিব্যক্তি তৈরি করার জন্য।

উদাহরণস্বরূপ, যদি আমাদের একজন ব্যবহারকারীর নাম এবং একটি স্বাগত বার্তার টেমপ্লেট পেতে চাই:

env := map[string]interface{}{
    "user":      User{Name: "Bob", Age: 30},
    "get_name":  func(u User) string { return u.Name },
    "greet_msg": "Hello, %s!",
}

code := `get_name(user) | sprintf(greet_msg)`

program, err := expr.Compile(code, expr.Env(env))
if err != nil {
    panic(err)
}

output, err := expr.Run(program, env)
if err != nil {
    panic(err)
}

fmt.Println(output) // আউটপুট: Hello, Bob!

এই উদাহরণে, আমরা প্রথমে get_name(user) দিয়ে ব্যবহারকারীর নাম পাচ্ছি, তারপর পাইপ অপারেটর | ব্যবহার করে অবশেষের স্বাগত বার্তা তৈরি করতে sprintf ফাংশনে নাম পাঠাচ্ছি।

পাইপ অপারেটর ব্যবহার করা যায় কোডের মডিউলার হওয়ায়, কোড পুনর্ব্যবহারযোগ্য করায় এবং অভিব্যক্তিগুলি আরও পঠনীয় হওয়ায়।

4.3 ফাংশনগুলি

Expr এ প্রস্তুত ফাংশনগুলি এবং কাস্টম ফাংশন সমর্থন করে, যা এক্সপ্রেশনগুলিকে আরও শক্তিশালী এবং সময়গত করে।

প্রস্তুত ফাংশন ব্যবহার

len, all, none, any ইত্যাদি প্রস্তুত ফাংশনগুলি অভিব্যক্তিতে সরাসরি ব্যবহৃত যেতে পারে।

// প্রস্তুত ফাংশন ব্যবহারের উদাহরণ
program, err := expr.Compile(`all(users, {.Age >= 18})`, expr.Env(env))
if err != nil {
    panic(err)
}

// লক্ষ্য করুন: এখানে env এ ব্যবহারকারী ভেরিয়েবল থাকতে হবে, এবং প্রতিটি ব্যবহারকারীর সম্পদ হওয়া আবশ্যক
output, err := expr.Run(program, env)
fmt.Print(output) // যদি env এ সব ব্যবহারকারী 18 বছরের বা তার চেয়ে বেশি বয়সী হয়, তবে এটি সত্য রিটার্ন করবে

কাস্টম ফাংশন সংজ্ঞায়িত এবং ব্যবহার

Expr এ, আপনি পরিবেশ ম্যাপিং এ ফাংশনের সংজ্ঞায়ন পাস করে কাস্টম ফাংশন তৈরি করতে পারেন।

// কাস্টম ফাংশন উদাহরণ
env := map[string]interface{}{
    "greet": func(name string) string {
        return fmt.Sprintf("Hello, %s!", name)
    },
}

program, err := expr.Compile(`greet("World")`, expr.Env(env))
if err != nil {
    panic(err)
}

output, err := expr.Run(program, env)
fmt.Print(output) // রিটার্ন করবে: Hello, World!

Expr ব্যবহার করার সময় ফাংশনগুলি ব্যবহার করার সময়, আপনি আপনার কোড মডিউলারাইজ করতে পারেন এবং এক্সপ্রেশনে জটিল লজিককে মনোরম করতে পারেন। ভেরিয়েবল, অপারেটর এবং ফাংশনগুলি সংযোগ করে এক্সপ্রেশনগুলি শক্তিশালী এবং ব্যবহার সহজ করার সাথে সাথে সর্বদা টাইপ সেফটি নিশ্চিত করা উচিত।

5. প্রস্তুত ফাংশন নথি

Expr এক্সপ্রেশন ইঞ্জিন ডেভেলপারদের জন্য বিভিন্ন জটিল সংক্রান্ত স্থিতি নিবারণের জন্য একটি ধারাবাহিক প্রস্তুত ফাংশনসেট প্রদান করে। নীচে, আমরা এই প্রস্তুত ফাংশনগুলি এবং তাদের ব্যবহারের বিস্তারিত বর্ণনা করব।

all

all ফাংশনটি একটি দেখা যাবে যদি সমস্ত উপাদানের সম্পূর্ণ শর্ত মেনে চলে। এটি দুইটি প্যারামিটার গ্রহণ করে: সংগ্রহ এবং শর্ত এক্সপ্রেশন।

// 240 এর কম লেখার শর্তে সমস্ত টুইটের জন্য চেক করা
code := `all(tweets, len(.Content) < 240)`

any

all এর মতো, any ফাংশনটি একটি শর্ত মেনে চলে কিনা তা চেক করতে ব্যবহৃত হয়।

// 240 এর বেশি লেখার শর্তে কোনও টুইটের জন্য চেক করা
code := `any(tweets, len(.Content) > 240)`

none

none ফাংশনটি একটি শর্ত মেনে চলে না তা চেক করতে ব্যবহৃত হয়।

// নিশ্চিত করা হয়েছে যে কোনও টুইট পুনরাবৃত্তি না করে
code := `none(tweets, .IsRepeated)`

one

one ফাংশনটি একটি শর্ত মেনে চলে তার প্রমাণ দেয় যে কেবল একজন উপাদান যথাক্রমে সম্পূর্ণ শর্ত মেনে চলে।

// যদি একটি টুইটে নির্দিষ্ট শব্দটি থাকে তাহলে কেবলমাত্র এটি চেক করুন
code := `one(tweets, contains(.Content, "keyword"))`

filter

filter ফাংশনটি দেওয়া শর্ত মেনে চলে সংগ্রহের উপাদানগুলি ফিল্টার করতে ব্যবহৃত হয়।

// সব টুইট ফিল্টার করতে যেখানে প্রাথমিকতা দেওয়া আছে
code := `filter(tweets, .IsPriority)`

map

map ফাংশনটি একটি নির্দিষ্ট পদ্ধতিতে সংগ্রহের উপাদানগুলির রূপ

len

len ফাংশনটি ব্যবহার করা হয় একটি সংগ্রহ বা স্ট্রিং-এর দৈর্ঘ্য পেতে।

// ইউজারনেমের দৈর্ঘ্য নিতে
code := `len(username)`

contains

contains ফাংশনটি ব্যবহার করা হয় একটি স্ট্রিং যদি কোন উপ-স্ট্রিং বা কোন সংগ্রহ কোন নির্দিষ্ট উপাদান কে ধারণ করে তা চেক করতে।

// ইলিগাল অক্ষর কি ইউজারনেমে আছে তা চেক করা 
code := `contains(username, "illegal characters")`

উপরে উল্লিখিত ফাংশনগুলি কোন ধরনের ডাটা এবং লজিক সম্বন্ধে একেবারে এবং কার্যকরীতা সহজে এবং দক্ষতার সাথে হ্যান্ডেল করতে সক্ষম করে তেমনই। আরো বিস্তারিত ফাংশনের তালিকা এবং ব্যবহারের নির্দেশিকা দেখতে দয়া করে অফিসিয়াল Expr ডকুমেন্টেশনে দেখুন।