[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