[FoRK] Top general purpose languages: Practical choices for app logic / presentation & web / server apps
Stephen Williams
sdw at lig.net
Fri Jan 21 12:07:18 PST 2011
On 1/18/11 7:01 PM, Damien Morton wrote:
> On Tue, Jan 18, 2011 at 10:09 PM, Stephen Williams<sdw at lig.net> wrote:
>> On 1/18/11 2:31 PM, Damien Morton wrote:
>>> ...
>>> I found this list of LINQ providers:
>>> http://blog.linqexchange.com/index.php/links-to-linq-providers/
>>>
>>> LINQ is something quite unique to C#. The closest thing I can think of is
>>> some of the LISP meta level programming.
>>>
>>> Doesn't seem too difficult to do in Java or C++ in some analogous way. I
>> will take another look soon, especially since I've been thinking of concise
>> programming issues.
>
> Do take another look. Its not something that can be implemented in a library
> system - it needs to be implemented at the language/compiler level.
>
> There are two main parts to it
> 1. an SQL like language, which gets transformed to a pipeline of function
> calls with lambdas as parameters (essentially map, reduce, select, etc)
> 2. The ability to declare that a lambda function parameter is not a function
> reference, but rather is a parse tree (of a lambda). e.g. in
> collection.where(x=>x>3) can have the x=>x>3 boolean predicate turned into a
> parse tree which is transformed and interpreted, for example, against an
> SQL store.
>
> There are hackish sorts of ways of doing this in C++, by overloading
> operators and such. As far as I know the only way to do this in Java is by
> analyzing bytecodes and trying to rebuild the parse tree that way.
It seems like, from the C++ point of view, that you could trigger operator->parse tree by anchoring the expression in a type that
has operators that do that. This is similar to doing String s; return s+bob+... and getting String::operator+ relative to the type
of bob. Or, for Java or C++, you just precompile to get the right thing which is essentially what LINQ is doing. In any case, I
still think that a good library API can make things just about as simple in many cases. There is a good argument for lambdas,
closures, and functional programming, but that is mostly here now for Java/C++ (can easy enough in Javascript and Python I think).
For instance, my recent DOM-like XML API for Java, Ssx, could hardly be simpler to use by an application.
First, these comments:
http://stackoverflow.com/questions/1217228/what-is-the-java-equivalent-for-linq
> Dont worry about LINQ, Microsoft themselves have moved ahead away from LINQ with the entity framework, which is basically
> hibernate or JPA.
> Take a look at the Entity Framework. Its functionality superceeds LINQ for SQL...They may be implementeddifferently but the goals
> are the same. – mP <http://stackoverflow.com/users/56524/mp> Jul 30 '10
What is LINQ?
http://weblogs.asp.net/kennykerr/archive/2006/05/11/The-Linq-between-C_2300_-and-C_2B002B00_.aspx
>
> IEnumerable<int> query = from n in numbers
> where n < 5
> orderby n
> select n;
>
> C# uses patterns, not unlike the way C++ templates work, to translate query expressions into method calls. Because of this, the
> query expression is suitably type-safe and is not simply an expression evaluated at runtime as is the case with many loosely-typed
> languages. The query expression above can be rewritten using method calls and this is essentially what the compiler does on your
> behalf:
>
> IEnumerable<int> _subset = Sequence.Where<int>(numbers,
> n => n < 5);
>
> IEnumerable<int> query = Sequence.OrderBy<int, int>(_subset,
> n => n);
>
> This now looks a lot more like C# but there is still the matter of the parameter expressions. These are known as C# lambda
> expressions, which provide a more concise syntax for writing anonymous methods. This can in turn be rewritten using anonymous
> methods as follows:
>
> IEnumerable<int> _subset = Sequence.Where<int>(numbers,
> delegate(int n) { return n < 5; });
>
> IEnumerable<int> query = Sequence.OrderBy<int, int>(_subset,
> delegate(int n) { return n; });
>
> So as you can see, query expressions are much like “for each” statements where the compiler takes a simpler expression and
> produces the more verbose imperative code on your behalf. Writing the query expression is just so much simpler and to-the-point:
Here's what I've found so far for Java and C++. The biggest problem is that you'd like to have a single method, more or less, for
most languages. Of course, Visual C++ apparently doesn't have LINQ (or didn't for a long time), so it seems that LINQ is CLR-only.
http://social.msdn.microsoft.com/forums/en-US/linqprojectgeneral/thread/0e48da8e-3f4e-4e81-94b9-ee3bab6eb196/
I would use P-Stade/Boost based Oven and maybe Boost.Phoenix for C++.
For Java, I'd want something that does not try to generate bytecodes at runtime as that won't work with Android/Dalvik. I haven't
verified yet whether that is a problem with these. It appears that Querydsl or sbql4j would be the best choices, and maybe jaque
when Java has closures. (The current, non-closure version of jaque is OK, but not as compelling.)
Wikipedia on the standard query operators for LINQ:
https://secure.wikimedia.org/wikipedia/en/wiki/Language_Integrated_Query
Related Java projects:
Java Closures (available soon, usable really as soon as there is a source->bytecode compiler):
http://www.javac.info/
Guava-libraries, Google Core Libraries
https://code.google.com/p/guava-libraries/
Stack-Based Architecture (SBA) and Stack-Based Query Language (SBQL), used by sbql4j
http://sbql.pl/overview/
google-guice
https://code.google.com/p/google-guice/
Boost.Iterator/Range/Actors
http://www.boost.org/doc/libs/1_39_0/libs/iterator/doc/index.html
http://www.boost.org/doc/libs/1_39_0/libs/range/doc/utility_class.html#iter_range
http://www.boost.org/doc/libs/1_38_0/libs/spirit/phoenix/doc/html/phoenix/actors.html
LINQ-like for Java:
A comparison of some of them:
http://source.mysema.com/display/querydsl/Similar+frameworks
Jaque:
https://code.google.com/p/jaque/
Near-term version:
r= from(data,
where( { Integer i=> i> 5 },
orderBy( { Integer i1, Integer i2=> i1-i2},
groupBy( {Integer i=> "a"},
orderBy( { Group<String, Integer> g1, Group<String, Integer> g2=> g1.getKey().compareTo(g2.getKey()) },
select( { Group<String, Integer> g=> 4 } ))))));
Querydsl
http://source.mysema.com/display/querydsl/Examples
HQLQuery q =new HibernateQuery(session);
QCat mother=new QCat("mother");// query type
QCat offspr=new QCat("offspr");
List<Family> families = q.from(mother).leftJoin(mother.kittens, offspr)
.list(new QFamily(mother, mother.mate;, offspr));
ScalaQL
http://permalink.gmane.org/gmane.comp.lang.scala.announce/154
http://www.sts.tu-harburg.de/people/mi.garcia/ScalaQL/
Supports compile-time interpretation of a LINQ query embedded as a string, or a Scala query with LINQ-like semantics.
Quaere, orphaned project that could do this:
http://quaere.codehaus.org/
City[] cities=City.ALL_CITIES;
Iterable<City> largePopulations =
from("city").in(cities).
orderBy("city.getName()").
orderByDescending("city.getPopulation()").
select("city");
for (City city : largePopulations) {
System.out.println(city);
}
sbql4j
https://code.google.com/p/sbql4j/
*It's 100% compatible with current Java Virtual Machines, and can be safely used in any Java project (compatible with Java 6).*
It integrates tightly with Java which means:
* Java variables can be used in queries directly (no special syntax like /setParameterX/ is required).
* Queries returns Java objects (collection or single object depending on query and used Java types).
* Java methods and constructors can be invoked inside queries.
* Query language is type-safe - queries are checked in compile time.
* *Queries can be translated to pure Java code (with no reflection usage) so execution is very fast.* (Description
<http://code.google.com/p/sbql4j/wiki/WikiCodeGeneration>)
SBQL4J gives Java developers full power of SBQL query language <http://sbql.pl/overview/> . Multiply nested and complicated queries
are well-supported, which can't be written in any other query language (including LINQ).
Available operators:
* arithmetic and algebraic: /+, -. *, /, %, == , != , >, <, >=, <=, OR, AND, NOT, instanceof/
* aggregating: /sum, count, avg, min, max/
* set operators: /union, intersect, unique, minus, in, ','/ (comma - structure constructor)
* quantifiers: /all, any/
* non-algebraic operators /'.'/ (dot - navigation, projection, path expressions), /where, join, order by, close by/ (transitive
closure - something like CONNECT BY in Oracle)
* range operators: [<range>] (for example /collection/[5], /collection/[3..7], /collection/[2..*])
* auxiliary name operators: /as, group as/
* constructor: /new/
List<Product> products= getProductList();
List<Product> expensiveInStockProducts= #{
products
where unitsInStock> 0 and unitPrice> 3.00
};
String[] words= { "aPPLE", "AbAcUs", "bRaNcH", "BlUeBeRrY", "ClOvEr", "cHeRry" };
Comparator<String> comp= new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
return o1.toLowerCase().compareTo(o2.toLowerCase());
}
};
List<String> sortedWords= #{
wordsas w
orderby w.length(); wusing comp
};
List<Department> dept= data.getDepts();
Boolean res= #{
all(deptas d)
any((d.employs minus d.boss) as e)
(e.salary== d.boss.salary)
};
List<Department> dept= data.getDepts();
Struct res= #{
min(dept.count(employs)) as minimum,
avg(dept.count(employs)) as average,
max(dept.count(employs)) as maximum
};
Siena
http://www.sienaproject.com/index.html
List<Employee> someEmployees= Employee.all()
.filter("firstName", "Mark")
.order("-lastName")
.fetch(10);
LINQ-like systems for C++:
ARARAT
http://www.docstoc.com/docs/2623236/Simple-and-Safe-SQL-Queries-with-C-Templates-via-the-ARARAT-System
LINQ++
http://hjiang.net/archives/229
|DataSet<vector<Person> > results =
insert(
from(guests)
.where(&_1 ->*&Person::age> 30))
.into(
from(guests)
.where(&_1 ->*&Person::name == "joe"));
|
Oven -Oven is an advanced implementation ofRange Library Proposal <http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1871.html>
http://p-stade.sourceforge.net/oven/doc/html/index.html
range sieve(range rng)
{
return rng|dropped(1)|filtered(regular(lambda::_1 % value_front(rng) != 0));
}
range primes
= iteration(range(counting(2, max_count)), &::sieve)|transformed(value_front);
int main()
{
std::cout << (primes|taken(200));
}
(proposed) Boost.Qlang, using C++0x lambdas, which seems to be mostly available in GCC and Visual C++ now.
http://lists.boost.org/Archives/boost/2009/10/157063.php
struct Person {
std::string name_;
std::string surname_;
int age_;
public:
Person(const std::string & name, const std::string & surname,
int age) :
name_(name), surname_(surname), age_(age) {}
};
vector<Person> persons = { {"German", "Gallardone", 23}, {"Pedro", "Ruiz", 28},
{"Hilario", "Pinose", 34},
{"Manolito", "Gafotas", 29},
{"Tomas", "Todonte", 56}, {"Tomas",
"Ruiz", 33}};
Example 1:
auto query = from(persons).where([](const Person & d) { return d.surname_ == "Ruiz"; }).
select(full_object);
Boost.Phoenix - functional programming: seems cool, but they don't have the compelling examples that Oven does.
http://www.boost.org/doc/libs/1_38_0/libs/spirit/phoenix/doc/html/phoenix/actors.html
Lazy statements, functions, operators using functors, actors, etc.
find_if(c.begin(), c.end(), arg1 % 2 == 1)
QxOrm - potentially interesting, especially for some interesting Qt code
http://www.qxorm.com/qxorm_en/home.html
Stephen
--
Stephen D. Williams sdw at lig.net stephendwilliams at gmail.com LinkedIn: http://sdw.st/in
V:650-450-UNIX (8649) V:866.SDW.UNIX V:703.371.9362 F:703.995.0407
AIM:sdw Skype:StephenDWilliams Yahoo:sdwlignet Resume: http://sdw.st/gres
Personal: http://sdw.st facebook.com/sdwlig twitter.com/scienteer
More information about the FoRK
mailing list