เริ่มต้นได้ง่าย
ห้องสมุดส่วนหัวเดี่ยว
API ที่ปราศจากแมโคร
ไม่มีการจัดสรรหน่วยความจำกอง
การพกพา: ทดสอบอย่างต่อเนื่องภายใต้ Ubuntu, MacOS และ Windows โดยใช้ GCC/Clang/MSVC
ไม่มีการพึ่งพาภายนอก
ความน่าเชื่อถือ: ตัวเลือกการตรวจสอบคอมไพเลอร์ที่เข้มงวด + sanitizers + valgrind
รูปแบบการประกอบ
ผู้ใช้สามารถกำหนดรูปแบบของตัวเองได้ไม่ว่าจะผ่านการเขียนรูปแบบที่มีอยู่หรือสร้างรูปแบบใหม่
รองรับภาชนะบรรจุที่เหมือน tuple-like และ range
การสนับสนุนบางส่วนสำหรับการแสดงออกอย่างต่อเนื่อง
matchit.h เพียงดาวน์โหลดไฟล์ส่วนหัว matchit.h และใส่ไว้ในไดเรกทอรีรวมของคุณสำหรับการพึ่งพา
แค่นั้นแค่นั้น
คุณสามารถดาวน์โหลดผ่านคำสั่ง bash นี้
wget https://raw.githubusercontent.com/BowenFu/matchit.cpp/main/include/matchit.hรวมรหัสตัวอย่างใน cmakelists ของคุณ txt:
include (FetchContent)
FetchContent_Declare(
matchit
GIT_REPOSITORY https://github.com/BowenFu/matchit.cpp.git
GIT_TAG main)
FetchContent_GetProperties(matchit)
if ( NOT matchit_POPULATED)
FetchContent_Populate(matchit)
add_subdirectory ( ${matchit_SOURCE_DIR} ${matchit_BINARY_DIR}
EXCLUDE_FROM_ALL )
endif ()
message ( STATUS "Matchit header are present at ${matchit_SOURCE_DIR} " ) และเพิ่ม ${matchit_SOURCE_DIR}/include ไปยังเส้นทางรวมของคุณ
แทนที่ main ด้วยแท็กรีลีสล่าสุดเพื่อหลีกเลี่ยงความเข้ากันได้ของ API
โคลน repo ผ่าน
git clone --depth 1 https://github.com/BowenFu/matchit.cpp
ติดตั้งไลบรารีผ่าน
cd matchit.cpp
cmake -B ./build
cd build
make install
จากนั้นใช้ find_package ใน cmakelists.txt ของคุณ
(ขอบคุณ @daljit97 สำหรับการเพิ่มการสนับสนุน)
vcpkg install matchit
ตอนนี้ห้องสมุดได้ถูกส่งไปยังดัชนี Conan Center
ตอนนี้คุณสามารถติดตั้งไลบรารีผ่านโคนัน
(ขอบคุณ @sanblch สำหรับการเพิ่มการสนับสนุน)
เพื่อให้การดีบักของคุณง่ายขึ้นให้ลองเขียนฟังก์ชั่น Lambda ของคุณในบรรทัดแยกต่างหากเพื่อให้คุณสามารถกำหนดจุดพักในนั้นได้
pattern | xyz = [&]
{
// Separate lines for function body <- set break points here
}เป็นมิตรกับการดีบักมากกว่าเมื่อเทียบกับ
pattern | xyz = [&] { /* some codes here */ }, // <- Set break points here, you will debug into the library.อย่าแก้ไขข้อบกพร่องในห้องสมุดนี้เว้นแต่คุณจะตัดสินใจรูทสาเหตุ / แก้ไขข้อบกพร่องบางอย่างในไลบรารีนี้เช่นเดียวกับที่คุณจะไม่ดีบักในตัวแปร STL หรือช่วง
โปรดลองสร้างตัวอย่างน้อยที่สุดเพื่อทำซ้ำปัญหาที่คุณพบ คุณสามารถทำให้เกิดปัญหาได้เร็วขึ้นในลักษณะนั้น
นอกจากนี้คุณยังสามารถสร้างปัญหาใน repo นี้และแนบรหัสตัวอย่างน้อยที่สุดและฉันจะพยายามตอบกลับโดยเร็วที่สุด (บางครั้งโปรดคาดหวังว่าจะมีความล่าช้าหนึ่งหรือสองวัน)
สำหรับรายละเอียดการออกแบบไวยากรณ์โปรดดูการอ้างอิง
เอกสารจาก Rust to Match (IT) ให้ตัวอย่างที่เทียบเท่าสำหรับตัวอย่างสนิมที่สอดคล้องกัน
ที่นั่นคุณอาจมีรูปภาพของการเข้ารหัสที่มี match(it) จะเป็นเช่นนั้น
เอกสารจากข้อเสนอการจับคู่รูปแบบเพื่อให้ตรงกับ (IT) ให้ตัวอย่างที่เทียบเท่าสำหรับตัวอย่างที่สอดคล้องกันในข้อเสนอการจับคู่รูปแบบการจับคู่
ที่นั่นคุณจะเห็นข้อดีและข้อเสียของห้องสมุดเหนือข้อเสนอ
มาเริ่มการเดินทางในห้องสมุดกันเถอะ!
(สำหรับตัวอย่างที่สมบูรณ์โปรดดูไดเรกทอรีตัวอย่าง)
ตัวอย่างต่อไปนี้แสดงให้เห็นถึงวิธีการใช้งานแฟคทอเรียลโดยใช้ไลบรารี match(it)
# include " matchit.h "
constexpr int32_t factorial ( int32_t n)
{
using namespace matchit ;
assert (n >= 0 );
return match (n)(
pattern | 0 = 1 ,
pattern | _ = [n] { return n * factorial (n - 1 ); }
);
}ไวยากรณ์พื้นฐาน สำหรับการจับคู่รูปแบบคือ
match (VALUE)
(
pattern | PATTERN1 = HANDLER1,
pattern | PATTERN2 = HANDLER2,
...
)นี่คือการเรียกใช้ฟังก์ชันและจะส่งคืนค่าบางส่วนที่ส่งคืนโดยตัวจัดการ ประเภทการส่งคืนเป็นประเภททั่วไปสำหรับตัวจัดการทั้งหมด ประเภทการส่งคืนจะเป็นโมฆะหากตัวจัดการทั้งหมดไม่ส่งคืนค่า ประเภทผลตอบแทนที่เข้ากันไม่ได้จากตัวจัดการหลายตัวเป็นข้อผิดพลาดในการรวบรวม เมื่อตัวจัดการส่งคืนค่ารูปแบบจะต้องครบถ้วนสมบูรณ์ ข้อผิดพลาดรันไทม์จะเกิดขึ้นหากรูปแบบทั้งหมดไม่ตรงกับ มันไม่ใช่ข้อผิดพลาดหากประเภทการส่งคืนของตัวจัดการเป็นโมฆะทั้งหมด
ตัวจัดการยังสามารถเป็นค่าหรือตัวแปร ID 1 เทียบเท่ากับ []{return 1;}
Wildcard _ จะตรงกับค่าใด ๆ มันเป็นวิธีปฏิบัติทั่วไปที่จะใช้เป็นรูปแบบสุดท้ายเสมอโดยมีบทบาทเดียวกันในห้องสมุดของเราเช่น default case สำหรับคำสั่ง switch เพื่อหลีกเลี่ยงการหลบหนี
เราสามารถจับ คู่หลายค่า ในเวลาเดียวกัน:
# include " matchit.h "
constexpr int32_t gcd ( int32_t a, int32_t b)
{
using namespace matchit ;
return match (a, b)(
pattern | ds (_, 0 ) = [&] { return a >= 0 ? a : -a; },
pattern | _ = [&] { return gcd (b, a%b); }
);
}
static_assert (gcd( 12 , 6 ) == 6); โปรดทราบว่ารูปแบบบางอย่างรองรับการจับคู่ constexpr เช่นคุณสามารถจับคู่ได้ในเวลาคอมไพล์ จากตัวอย่างโค้ดด้านบนเราจะเห็นว่า gcd(12, 6) สามารถดำเนินการในเวลารวบรวม
แตกต่างจากรูปแบบการจับคู่ในภาษาการเขียนโปรแกรมอื่น ๆ ตัวแปรสามารถใช้ตามปกติภายในรูปแบบ ใน match(it) ซึ่งแสดงในตัวอย่างต่อไปนี้:
# include " matchit.h "
# include < map >
template < typename Map, typename Key>
constexpr bool contains (Map const & map, Key const & key)
{
using namespace matchit ;
return match (map. find (key))(
pattern | map. end () = false ,
pattern | _ = true
);
}เราสามารถใช้ รูปแบบการแสดง เพื่อวางข้อ จำกัด บางอย่างเกี่ยวกับค่าที่จะจับคู่
constexpr double relu ( double value)
{
return match (value)(
pattern | (_ >= 0 ) = value,
pattern | _ = 0
);
}
static_assert (relu( 5 ) == 5);
static_assert (relu(- 5 ) == 0); เราโอเวอร์โหลดผู้ให้บริการบางรายสำหรับสัญลักษณ์ไวด์การ์ด _ เพื่ออำนวยความสะดวกในการใช้งานภาคพื้นขั้นพื้นฐาน
บางครั้งเราต้องการแบ่งปันหนึ่งตัวจัดการสำหรับหลายรูปแบบ หรือรูปแบบ คือการช่วยเหลือ:
# include " matchit.h "
constexpr bool isValid ( int32_t n)
{
using namespace matchit ;
return match (n)(
pattern | or_ ( 1 , 3 , 5 ) = true ,
pattern | _ = false
);
}
static_assert (isValid( 5 ));
static_assert (!isValid( 6 ));และรูปแบบ สำหรับการรวมรูปแบบการแสดงหลายรูปแบบ
รูปแบบแอพนั้น ทรงพลังเมื่อคุณต้องการดึงข้อมูลบางส่วนออกจากเรื่อง ไวยากรณ์ของมันคือ
app (PROJECTION, PATTERN)ตัวอย่างง่ายๆในการตรวจสอบว่าจำนวนมีขนาดใหญ่สามารถ:
# include " matchit.h "
constexpr bool isLarge ( double value)
{
using namespace matchit ;
return match (value)(
pattern | app (_ * _, _ > 1000 ) = true ,
pattern | _ = false
);
}
// app with projection returning scalar types is supported by constexpr match.
static_assert (isLarge( 100 )); โปรดทราบว่า _ * _ สร้างวัตถุฟังก์ชั่นที่คำนวณกำลังสองของอินพุตสามารถพิจารณารุ่นสั้น ๆ ของ [](auto&& x){ return x*x;}
เราสามารถผูกค่าได้หรือไม่ถ้าเราแยกพวกเขาไปแล้ว? แน่นอนว่า รูปแบบตัวระบุ เหมาะสำหรับคุณ
มาบันทึกผลลัพธ์สแควร์ด้วยรูปแบบตัวระบุรหัสจะเป็น
# include < iostream >
# include " matchit.h "
bool checkAndlogLarge ( double value)
{
using namespace matchit ;
Id< double > s;
return match (value)(
pattern | app (_ * _, s. at (_ > 1000 )) = [&] {
std::cout << value << " ^2 = " << *s << " > 1000! " << std::endl;
return true ; },
pattern | _ = false
);
} ในการใช้รูปแบบตัวระบุ เราจำเป็นต้องกำหนด/ประกาศตัวระบุ ( Id<double> s ) ก่อน (อย่าทำเครื่องหมายเป็น const.) สิ่งนี้อาจแปลกเล็กน้อยถ้าคุณใช้รูปแบบตัวระบุในภาษาการเขียนโปรแกรมอื่น ๆ นี่เป็นเพราะการ จำกัด ภาษา แต่อย่าอารมณ์เสีย คำพูดที่เพิ่มเข้ามานี้ทำให้เราสามารถ ใช้ตัวแปรภายในรูปแบบ ได้ คุณอาจไม่สามารถทำสิ่งนี้ได้ในภาษาการเขียนโปรแกรมอื่น ๆ
ที่นี่ * ตัวดำเนินการใช้เพื่อลดค่าค่าภายในตัวระบุ สิ่งหนึ่งที่ควรทราบคือตัวระบุนั้นถูกต้องภายในขอบเขต match เท่านั้น อย่าพยายามทำสิ่งที่อยู่ข้างนอก
Id::at คล้ายกับ รูปแบบ @ ใน Rust, IE, ผูกค่าเมื่อ Subpattern จับคู่
โปรดทราบเมื่อตัวระบุเดียวกันถูกผูกไว้หลายครั้งค่าที่ถูกผูกไว้จะต้องเท่ากับซึ่งกันและกันผ่าน operator== ตัวอย่างเพื่อตรวจสอบว่าอาร์เรย์มีความสมมาตรหรือไม่:
# include " matchit.h "
constexpr bool symmetric (std::array< int32_t , 5 > const & arr)
{
using namespace matchit ;
Id< int32_t > i, j;
return match (arr)(
pattern | ds (i, j, _, j, i) = true ,
pattern | _ = false
);
}
static_assert (symmetric(std::array< int32_t , 5 >{ 5 , 0 , 3 , 7 , 10 }) == false);
static_assert (symmetric(std::array< int32_t , 5 >{ 5 , 0 , 3 , 0 , 5 }) == true);
static_assert (symmetric(std::array< int32_t , 5 >{ 5 , 1 , 3 , 0 , 5 }) == false); ตอนนี้เรามาถึงส่วนที่ทรงพลังที่สุด: รูปแบบการทำลายโครงสร้าง รูปแบบการทำลายล้างสามารถใช้สำหรับ std::tuple , std::pair , std::array (ภาชนะบรรจุขนาดคงที่) และภาชนะบรรจุแบบไดนามิกหรือช่วงขนาด ( std::vector , std::list , std::set และอื่น ๆ ) ด้วย std::begin และ std::end รองรับ
สามารถละเว้นรูปแบบภายใน ds ด้านนอกสุด เมื่อรูปแบบได้รับพารามิเตอร์หลายตัวพวกเขาจะได้รับการปฏิบัติเป็นรูปแบบย่อยของรูปแบบ DS
# include " matchit.h "
template < typename T1, typename T2>
constexpr auto eval (std::tuple< char , T1, T2> const & expr)
{
using namespace matchit ;
Id<T1> i;
Id<T2> j;
return match (expr)(
pattern | ds ( ' + ' , i, j) = i + j,
pattern | ds ( ' - ' , i, j) = i - j,
pattern | ds ( ' * ' , i, j) = i * j,
pattern | ds ( ' / ' , i, j) = i / j,
pattern | _ = []
{
assert ( false );
return - 1 ;
});
} ผู้ให้บริการบางรายได้รับการโอเวอร์โหลดสำหรับ Id ดังนั้น i + j จะส่งคืนฟังก์ชั่น nullary ที่ส่งคืนค่า *i + *j
นอกจากนี้ยังมีวิธีการทำลายโครงสร้างโครงสร้าง / คลาสของคุณทำให้โครงสร้าง / คลาส tuple ของคุณเหมือนหรือใช้รูปแบบแอพ ตัวเลือกที่สองดูเหมือน
// Another option to destructure your struct / class.
constexpr auto dsByMember (DummyStruct const &v)
{
using namespace matchit ;
// compose patterns for destructuring struct DummyStruct.
constexpr auto dsA = dsVia (&DummyStruct::size, &DummyStruct::name);
Id< char const *> name;
return match (v)(
pattern | dsA ( 2 , name) = name,
pattern | _ = " not matched "
);
};
static_assert (dsByMember(DummyStruct{ 1 , " 123 " }) == std::string_view{ " not matched " });
static_assert (dsByMember(DummyStruct{ 2 , " 123 " }) == std::string_view{ " 123 " });มาเดินทางต่อกันเถอะ บางครั้งคุณมีตัวระบุหลายตัวและคุณต้องการออกแรง จำกัด ความสัมพันธ์ของพวกเขา เป็นไปได้ไหม? แน่นอน! มาที่นี่ ยามการแข่งขัน ไวยากรณ์ของมันคือ
pattern | PATTERN | when(GUARD) = HANDLERบอกว่าเราต้องการจับคู่เฉพาะเมื่อผลรวมของตัวระบุสองตัวเท่ากับค่าบางอย่างเราสามารถเขียนรหัสเป็น
# include < array >
# include " matchit.h "
constexpr bool sumIs (std::array< int32_t , 2 > const & arr, int32_t s)
{
using namespace matchit ;
Id< int32_t > i, j;
return match (arr)(
pattern | ds (i, j) | when (i + j == s) = true ,
pattern | _ = false
);
}
static_assert (sumIs(std::array< int32_t , 2 >{ 5 , 6 }, 11 )); มันเจ๋งใช่มั้ย โปรดทราบว่า i + j == s จะส่งคืนฟังก์ชัน nullary ที่ส่งคืนผลลัพธ์ของ *i + *j == s
ตอนนี้เรามาที่ รูปแบบ ooo นั่นคืออะไร? คุณอาจถาม ในภาษาการเขียนโปรแกรมบางอย่างเรียกว่า รูปแบบการพักผ่อน คุณสามารถจับคู่จำนวนรายการโดยพลการกับมัน สามารถใช้งานได้ภายในรูปแบบ ds เท่านั้นและอย่างที่รูปแบบ OOO ส่วนใหญ่สามารถปรากฏในรูปแบบ ds คุณสามารถเขียนโค้ดได้ตามที่คุณต้องการตรวจสอบรูปแบบของ tuple
# include < array >
# include " matchit.h "
template < typename Tuple>
constexpr int32_t detectTuplePattern (Tuple const & tuple)
{
using namespace matchit ;
return match (tuple)
(
pattern | ds ( 2 , ooo, 2 ) = 4 ,
pattern | ds ( 2 , ooo ) = 3 ,
pattern | ds (ooo, 2 ) = 2 ,
pattern | ds (ooo ) = 1
);
}
static_assert (detectTuplePattern(std::make_tuple( 2 , 3 , 5 , 7 , 2 )) == 4); ยิ่งไปกว่านั้นเราสามารถ ผูกช่วงย่อยกับรูปแบบ ooo เมื่อทำลายโครงสร้าง std::array หรือคอนเทนเนอร์ / ช่วงอื่น ๆ มันค่อนข้างเจ๋ง เราสามารถตรวจสอบได้ว่า AN/A array/vector/list/set/map/subrange/... มีความสมมาตรด้วย:
template < typename Range>
constexpr bool recursiveSymmetric (Range const &range)
{
Id< int32_t > i;
Id<SubrangeT<Range const >> subrange;
return match (range)(
pattern | ds (i, subrange. at (ooo), i) = [&] { return recursiveSymmetric (*subrange); },
pattern | ds (_, ooo, _) = false ,
pattern | _ = true
);ในรูปแบบแรกเราต้องการให้หัวเท่ากับจุดสิ้นสุด และถ้าเป็นเช่นนั้นเราจะตรวจสอบส่วนที่เหลือ (ถูกผูกไว้เพื่อย่อย) ผ่านการโทรแบบเรียกซ้ำ เมื่อการโทรซ้อนกันบางอย่างไม่ตรงตามข้อกำหนดนั้น (ตกอยู่ในรูปแบบที่สอง) การตรวจสอบจะล้มเหลว มิฉะนั้นเมื่อมีองค์ประกอบเดียวที่เหลืออยู่หรือขนาดช่วงเป็นศูนย์รูปแบบสุดท้ายจะถูกจับคู่เรากลับมาจริง
เราได้ทำกับรูปแบบหลักของเราแล้ว ตอนนี้มาเริ่มการเดินทางของ รูปแบบการเขียน
คุณควรคุ้นเคยกับ รูปแบบบางอย่าง และ ไม่มีรูปแบบ หากคุณใช้คุณสมบัติการจับคู่รูปแบบใน Rust
รูปแบบบางอย่าง / ไม่มีเลยสามารถใช้เพื่อจับคู่พอยน์เตอร์ดิบ std::optional std::unique_ptr , std::shared_ptr และประเภทอื่น ๆ ที่สามารถแปลงเป็น bool และ dereferenced ตัวอย่างทั่วไปสามารถ
# include " matchit.h "
template < typename T>
constexpr auto square (std::optional<T> const & t)
{
using namespace matchit ;
Id<T> id;
return match (t)(
pattern | some (id) = id * id,
pattern | none = 0
);
}
constexpr auto x = std::make_optional( 5 );
static_assert (square(x) == 25);รูปแบบบางรูปแบบยอมรับรูปแบบย่อย ในตัวอย่าง subpattern เป็นตัวระบุและเราผูกผลลัพธ์ที่ได้รับการอ้างอิงไว้ ไม่มีรูปแบบอยู่คนเดียว
รูปแบบบางอย่างและไม่มีรูปแบบอะตอมใน match(it) พวกเขาจะแต่งผ่าน
template < typename T>
constexpr auto cast = []( auto && input) {
return static_cast <T>(input);
};
constexpr auto deref = []( auto &&x) { return *x; };
constexpr auto some = []( auto const pat) {
return and_ ( app (cast< bool >, true ), app (deref, pat));
};
constexpr auto none = app(cast< bool >, false );สำหรับรูปแบบบางอย่างก่อนอื่นเราจะใช้ค่าเป็นค่าบูลีนหากค่าบูลีนเป็นจริงเราสามารถทำการตรวจสอบเพิ่มเติมได้ มิฉะนั้นการแข่งขันจะล้มเหลว สำหรับรูปแบบที่ไม่มีเราเพียงตรวจสอบว่าค่าบูลีนที่แปลงเป็นเท็จหรือไม่
เนื่องจากรูปแบบ มีประโยชน์มากสำหรับการจัดการ sum type รวมรวมถึงลำดับชั้นของคลาส, std::variant และ std::any std::variant และ std::any สามารถเยี่ยมชมได้
# include " matchit.h "
template < typename T>
constexpr auto getClassName (T const & v)
{
using namespace matchit ;
return match (v)(
pattern | as< char const *>(_) = " chars " ,
pattern | as< int32_t >(_) = " int32_t "
);
}
constexpr std::variant< int32_t , char const *> v = 123 ;
static_assert (getClassName(v) == std::string_view{ " int32_t " });ลำดับชั้นของชั้นเรียนสามารถจับคู่เป็น
struct Shape
{
virtual ~Shape () = default ;
};
struct Circle : Shape {};
struct Square : Shape {};
auto getClassName (Shape const &s)
{
return match (s)(
pattern | as<Circle>(_) = " Circle " ,
pattern | as<Square>(_) = " Square "
);
}เนื่องจากรูปแบบไม่ใช่รูปแบบอะตอมเช่นกัน มันประกอบผ่าน
template < typename T>
constexpr AsPointer<T> asPointer;
template < typename T>
constexpr auto as = []( auto const pat) {
return app (asPointer<T>, some (pat));
}; สำหรับคลาส dynamic_cast ถูกใช้โดยค่าเริ่มต้นเป็นรูปแบบ แต่เราสามารถเปลี่ยนพฤติกรรมผ่าน จุดปรับแต่ง ผู้ใช้สามารถปรับแต่งการหล่อลงผ่านการกำหนดฟังก์ชั่น get_if สำหรับคลาสของพวกเขาคล้ายกับ std::get_if สำหรับ std::variant :
# include < iostream >
# include " matchit.h "
enum class Kind { kONE , kTWO };
class Num
{
public:
virtual ~Num () = default ;
virtual Kind kind () const = 0;
};
class One : public Num
{
public:
constexpr static auto k = Kind:: kONE ;
Kind kind () const override { return k; }
};
class Two : public Num
{
public:
constexpr static auto k = Kind:: kTWO ;
Kind kind () const override
{
return k;
}
};
template <Kind k>
constexpr auto kind = app(&Num::kind, k);
template < typename T>
auto get_if (Num const * num) {
return static_cast <T const *>(num-> kind () == T::k ? num : nullptr );
}
int32_t staticCastAs (Num const & input)
{
using namespace matchit ;
return match (input)(
pattern | as<One>(_) = 1 ,
pattern | kind<Kind:: kTWO > = 2 ,
pattern | _ = 3
);
}
int32_t main ()
{
std::cout << staticCastAs (One{}) << std::endl;
return 0 ;
}มี จุดประเพณี เพิ่มเติม
ผู้ใช้สามารถเชี่ยวชาญ PatternTraits หากพวกเขาต้องการเพิ่มรูปแบบใหม่เอี่ยม
สิ่งหนึ่งที่ควรทราบคือ Id ไม่ใช่ประเภทธรรมดา สำเนาใด ๆ ของมันเป็นเพียงการอ้างอิงถึงมัน ดังนั้นอย่าพยายามส่งคืนจากที่กำหนดไว้
กรณีที่ไม่ดีจะเป็น
auto badId ()
{
Id< int > x;
return x;
} การส่งคืนรูปแบบที่ประกอบขึ้นรวมถึง Id ท้องถิ่นก็ไม่ถูกต้องเช่นกัน
auto badPattern ()
{
Id< int > x;
return composeSomePattern (x);
} แนวปฏิบัติที่ดีคือการกำหนด Id ใกล้เคียงกับการใช้งานในการจับคู่รูปแบบ
auto goodPattern ()
{
Id< int > x;
auto somePattern = composeSomePattern (x);
return match (...)
(
pattern | somePattern = ...
);
} mathiu เป็นระบบพีชคณิตคอมพิวเตอร์ง่าย ๆ ที่สร้างขึ้นเมื่อ match(it)
ตัวอย่างง่าย ๆ ของ mathiu :
auto const x = symbol( " x " );
auto const e = x ^ fraction( 2 , 3 );
auto const d = diff(e, x);
// prints (* 2/3 (^ x -1/3))
std::cout << toString(d) << std::endl;OpenNask: แอสเซมเบลอร์ 80x86 เช่น MASM/NASM สำหรับระบบปฏิบัติการขนาดเล็ก
หากคุณทราบถึงโครงการอื่น ๆ ที่ใช้ห้องสมุดนี้โปรดแจ้งให้เราทราบโดยส่งปัญหาหรือ PR
หากคุณมีคำถามหรือแนวคิดใด ๆ เกี่ยวกับห้องสมุดโปรดเปิดปัญหา
ยินดีต้อนรับการอภิปราย / ปัญหา / PRS
การออกแบบไวยากรณ์ / รูปแบบของ match(it) ได้รับอิทธิพลอย่างมากจากงานที่เกี่ยวข้องเหล่านี้
หากคุณสนใจใน match(it) คุณอาจสนใจ HSPP ซึ่งนำการเขียนโปรแกรมสไตล์ Haskell มาที่ C ++
โปรดแสดง repo แบ่งปัน repo หรือสนับสนุนหนึ่งดอลลาร์เพื่อแจ้งให้เราทราบว่าห้องสมุดนี้มีความสำคัญ
ขอบคุณทุกคนสำหรับการสนับสนุนรหัสและการส่งในข้อบกพร่อง
โดยเฉพาะอย่างยิ่งขอบคุณผู้มีส่วนร่วมต่อไปนี้:
Hugo Etchegoyen (@hugoethegoyen)
ขอบคุณ @e-dant สำหรับการสนับสนุนโครงการนี้