Skip to content

Instantly share code, notes, and snippets.

@luizmb
Last active October 2, 2022 14:29
Show Gist options
  • Save luizmb/2957ab83d43d8261c73e737c6165585d to your computer and use it in GitHub Desktop.
Save luizmb/2957ab83d43d8261c73e737c6165585d to your computer and use it in GitHub Desktop.
Simple C++ functional language query interface (LINQ-alike) prototype
#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 */
#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;
};
#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;
}
#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 */
#ifndef LinqFramework_hpp
#define LinqFramework_hpp
#include "Linq.hpp"
#include "Skip.hpp"
#include "Limit.hpp"
#include "Where.hpp"
#include "Linq.cpp"
#endif /* LinqFramework_hpp */
#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 */
#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