Last active
October 2, 2022 14:29
-
-
Save luizmb/2957ab83d43d8261c73e737c6165585d to your computer and use it in GitHub Desktop.
Simple C++ functional language query interface (LINQ-alike) prototype
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef Limit_hpp | |
#define Limit_hpp | |
#include "Linq.hpp" | |
template<typename T> | |
class Limit { | |
private: | |
unsigned long limit = 0; | |
public: | |
Limit(unsigned long limit) { | |
this->limit = limit; | |
} | |
friend Linq<T> operator>>(const std::vector<T>& left, const Limit& right) | |
{ | |
Linq<T> linq; | |
linq.set_collection(left); | |
linq.set_limit(right.limit); | |
return linq; | |
} | |
friend Linq<T>* operator>>(Linq<T>* left, const Limit& right) | |
{ | |
left->set_limit(right.limit); | |
return left; | |
} | |
friend Linq<T> operator>>(Linq<T>& left, const Limit& right) | |
{ | |
left.limit = right.limit; | |
return left; | |
} | |
}; | |
#endif /* Limit_hpp */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "Linq.hpp" | |
template<typename T> | |
Linq<T>::Linq() { }; | |
template<typename T> | |
Linq<T>::Linq(std::vector<T> collection) { | |
set_collection(collection); | |
}; | |
template<typename T> | |
Linq<T> * Linq<T>::set_collection(std::vector<T> collection) { | |
this->collection = collection; | |
return this; | |
}; | |
template<typename T> | |
Linq<T> * Linq<T>::where(std::function<bool (T)> expression) { | |
this->expressions.push_back(expression); | |
return this; | |
}; | |
template<typename T> | |
Linq<T> * Linq<T>::set_limit(unsigned long limit) { | |
this->limit = limit; | |
return this; | |
}; | |
template<typename T> | |
Linq<T> * Linq<T>::set_skip(unsigned long skip) { | |
this->skip = skip; | |
return this; | |
}; | |
template<typename T> | |
T Linq<T>::first() { | |
if (this->collection.size() <= this->skip) { | |
return NULL; | |
} | |
for (unsigned long i = this->skip; i < this->collection.size(); i++) { | |
T item = this->collection.at(i); | |
if (shouldInclude(item)) { | |
return item; | |
} | |
} | |
return NULL; | |
}; | |
template<typename T> | |
T Linq<T>::last() { | |
if (this->collection.size() <= this->skip) { | |
return NULL; | |
} | |
for (unsigned long i = this->collection.size() - 1 - this->skip; ; --i) { | |
T item = this->collection.at(i); | |
if (shouldInclude(item)) { | |
return item; | |
} | |
} | |
return NULL; | |
}; | |
template<typename T> | |
std::vector<T> Linq<T>::to_list() { | |
if (this->collection.size() <= this->skip) { | |
return std::vector<T>(); | |
} | |
std::vector<T> filteredCollection; | |
int count = 0; | |
for (unsigned long i = this->skip; i < this->collection.size(); i++) { | |
T item = this->collection.at(i); | |
if (shouldInclude(item)) { | |
filteredCollection.push_back(item); | |
if (++count == this->limit) { | |
return filteredCollection; | |
} | |
} | |
} | |
return filteredCollection; | |
}; | |
template<typename T> | |
bool Linq<T>::shouldInclude(T item) { | |
if (this->expressions.size() == 0) return true; | |
for (std::function<bool (T)> w : this->expressions) { | |
if (!w(item)) { | |
return false; | |
} | |
} | |
return true; | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
#include "LinqFramework.hpp" | |
using namespace std; | |
typedef vector<int> IntArray; | |
typedef vector<string> StringArray; | |
IntArray give_me_numbers() { | |
return from((IntArray){ 1, 3, 5, 6, 7, 8, 10, 11, 13, 16, 18 }) | |
>> Where<int>([] (int i) { return i % 2 == 0; }) | |
>> Where<int>([] (int i) { return i <= 10; }); | |
} | |
StringArray give_me_strings() { | |
return from((StringArray){ "aa", "ab", "abc", "bb", "bc", "bcd", "cc", "cd", "cde", "dd", "de", "def" }) | |
>> Where<string>([] (string i) { return i.length() == 2; }) | |
>> Where<string>([] (string i) { return i[0] != 'c'; }); | |
} | |
StringArray give_me_strings_with_pages() { | |
return (StringArray){ "aa", "ab", "abc", "bb", "bc", "bcd", "cc", "cd", "cde", "dd", "de", "def" } | |
>> Where<string>([] (string i) { return i.length() == 2; }) | |
>> Where<string>([] (string i) { return i[0] != 'c'; }) | |
>> Skip<string>(2) | |
>> Limit<string>(3); | |
} | |
string give_me_first_string() { | |
return (StringArray){ "aa", "ab", "abc", "bb", "bc", "bcd", "cc", "cd", "cde", "dd", "de", "def" } | |
>> Where<string>([] (string i) { return i.length() == 2; }) | |
>> Where<string>([] (string i) { return i[0] != 'a'; }) | |
>> Where<string>([] (string i) { return i != "bb"; }); | |
} | |
string stringify(string item) { | |
return item; | |
} | |
string stringify(int item) { | |
return to_string(item); | |
} | |
template<typename T> | |
string print(vector<T> array) { | |
string result; | |
for (T item : array) { | |
result.append(stringify(item) + " "); | |
} | |
return result; | |
} | |
int main(int argc, const char * argv[]) { | |
cout << print(give_me_numbers()) << endl; | |
cout << print(give_me_strings()) << endl; | |
cout << print(give_me_strings_with_pages()) << endl; | |
cout << give_me_first_string() << endl; | |
return 0; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef Linq_hpp | |
#define Linq_hpp | |
#include <vector> | |
#include <functional> | |
template<typename T> | |
class Linq { | |
private: | |
std::vector<T> collection; | |
std::vector<std::function<bool (T)>> expressions; | |
unsigned long skip = 0; | |
unsigned long limit = 0; | |
bool shouldInclude(T item); | |
public: | |
Linq(); | |
Linq(std::vector<T> collection); | |
Linq<T> *set_collection(std::vector<T> collection); | |
Linq<T> *where(std::function<bool (T)> expression); | |
Linq<T> *set_limit(unsigned long limit); | |
Linq<T> *set_skip(unsigned long skip); | |
T first(); | |
T last(); | |
std::vector<T> to_list(); | |
operator std::vector<T> () { | |
return to_list(); | |
} | |
operator T () { | |
return first(); | |
} | |
}; | |
template<typename T> | |
Linq<T> from(std::vector<T> collection) { | |
return Linq<T>(collection); | |
} | |
#endif /* Linq_hpp */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef LinqFramework_hpp | |
#define LinqFramework_hpp | |
#include "Linq.hpp" | |
#include "Skip.hpp" | |
#include "Limit.hpp" | |
#include "Where.hpp" | |
#include "Linq.cpp" | |
#endif /* LinqFramework_hpp */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef Skip_hpp | |
#define Skip_hpp | |
#include "Linq.hpp" | |
template<typename T> | |
class Skip { | |
private: | |
unsigned long skip = 0; | |
public: | |
Skip(unsigned long skip) { | |
this->skip = skip; | |
} | |
friend Linq<T> operator>>(const std::vector<T>& left, const Skip& right) | |
{ | |
Linq<T> linq; | |
linq.set_collection(left); | |
linq.set_skip(right.skip); | |
return linq; | |
} | |
friend Linq<T>* operator>>(Linq<T>* left, const Skip& right) | |
{ | |
left->set_skip(right.skip); | |
return left; | |
} | |
friend Linq<T> operator>>(Linq<T>& left, const Skip& right) | |
{ | |
left.skip = right.skip; | |
return left; | |
} | |
}; | |
#endif /* Skip_hpp */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef Where_hpp | |
#define Where_hpp | |
#include <functional> | |
#include "Linq.hpp" | |
template<typename T> | |
class Where { | |
private: | |
typedef std::function<bool (T)> Predicate; | |
public: | |
Predicate expression; | |
Where(Predicate expression) { | |
this->expression = expression; | |
} | |
friend Linq<T> operator>>(const std::vector<T>& left, const Where<T>& right) | |
{ | |
Linq<T> linq; | |
linq.set_collection(left); | |
linq.where(right.expression); | |
return linq; | |
} | |
friend Linq<T>* operator>>(Linq<T>* left, const Where<T>& right) | |
{ | |
left->where(right.expression); | |
return left; | |
} | |
friend Linq<T> operator>>(Linq<T>& left, const Where<T>& right) | |
{ | |
left.expressions.push_back(right); | |
return left; | |
} | |
bool evaluate(T item) { | |
return expression(item); | |
} | |
}; | |
#endif /* Where_hpp */ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment