December 24, 2008
aarti_pl wrote:
> Andrei Alexandrescu pisze:
>  > We're trying to make that work. D is due for an operator overhaul.
>  >
>  > Andrei
> 
> Is there any chance that we get possibility to overload "raw operators", like in C++? I think that they may coexist with currently defined operator overloads with simple semantic rules, which will not allow them to work together at the same time.
> 
> I know that they may obfuscate code, but they are extremely useful when defining in D domain specific languages. For example I try to make SQL expressions work as D expressions:

> 
> string query = "SELECT * FROM a WHERE id=5;";
> -->
> Query query = Select(a).Where(Equals(id, 5));
> 
> * "id" is D object in second expression
> 
> This translation is quite awful and unreadable. It would be so much better to get:
> 
> Query query = Select(a).Where(id == 5);

I think that's still awful. I prefer:
Query query = mixin(SQL("SELECT * FROM a WHERE id=5"));


> 
> With implicit casts there will be perfect environment, to define DSL-s *in* D and *not* using unsafe strings.
> 
> BR
> Marcin Kuszczak
> (aarti_pl)
December 24, 2008
Tue, 23 Dec 2008 19:14:16 -0500, Christopher Wright wrote:

> Denis Koroskin wrote:
>> Slightly off-topic.
>> 
>> How would you implement, say, LIKE condition? Similar to the following, perhaps:
>> Query query = Select(a).Where(id.Like("%substring%"));
>> 
>> You could implement "==" the same way:
>> Query query = Select(a).Where(id.EqualsTo(5));
> 
> downs way:
> auto query1 = select(a) /where/ "id" /eq/ 5;
> auto query2 = select(a) /where/ "name" /like/ "%bob%";

What a nice trick!

I don't like operator abuse, but sometimes it's a lesser evil.  And it's definitely the case with SQL queries.
December 24, 2008
Don pisze:
> aarti_pl wrote:
>> Andrei Alexandrescu pisze:
>>  > We're trying to make that work. D is due for an operator overhaul.
>>  >
>>  > Andrei
>>
>> Is there any chance that we get possibility to overload "raw operators", like in C++? I think that they may coexist with currently defined operator overloads with simple semantic rules, which will not allow them to work together at the same time.
>>
>> I know that they may obfuscate code, but they are extremely useful when defining in D domain specific languages. For example I try to make SQL expressions work as D expressions:
> 
>>
>> string query = "SELECT * FROM a WHERE id=5;";
>> -->
>> Query query = Select(a).Where(Equals(id, 5));
>>
>> * "id" is D object in second expression
>>
>> This translation is quite awful and unreadable. It would be so much better to get:
>>
>> Query query = Select(a).Where(id == 5);
> 
> I think that's still awful. I prefer:
> Query query = mixin(SQL("SELECT * FROM a WHERE id=5"));
>

Thanks for example - it talks to me more than 1000 words :-)

Your proposal is indeed interesting. (And I think it is what Dennis Luehring was reffering to).

But I have to say it has some drawbacks. Let me enumerate them:

1. Extending such a queries on runtime would be rather difficult IMHO, and will not look very nice. With my solution you can do something like this:
---
Column cols = [person.name, person.surname, person.nick];
for(i=0; i<rows; i++) {
  InsertStatement insert = Insert();
  foreach(Column col; cols) {
    insert ~= insert.insert(col, getText(i, col));
  }
  db.execute(insert);
}

* example not tested, but something like this is already possible in my framework.

Constructing queries dynamically is very useful for creating e.g. universal gui controls which could be just binded to database tables.

Another useful example is sending SQL expression (not the whole statement) as an argument to function.

To make it work nicely with mixins IMHO you will have to make this kind of SQL to look much uglier than in this simple case.

Do you have any proposals how it could look like with mixins?

2. I see also problem with IDE-s which will have to be changed to understand DLSs in mixins. I think that it is doable and even can be done quite nice, but currently there is *no* support for such a feature. It means that you will not have:

a. syntax highlighting
b. no IDE proposing your names of variables and methods
c. no refactoring

Currently in Eclipse I can rename database column names in my program with only single mouse click (Java version of my framework, which is the main branch currently). When SQLs will be in form of string mixins they will not change during refactoring. You will have to write special refactoring tools for your library to make it done.

3. Sometimes having more expressiveness in language can avoid creating new DSLs. I think it is a Good Thing (tm). In fact I took that way and decided to integrate SQL DSL language into mother language. That way programmers don't have to learn new syntax, but just use existing syntax of mother language to solve specific problems. Using DSL in mother language resolves then into just writing special kind of API, which can be used in standard way to achieve goal. D and most other languages from C family are almost perfect candidates to make something like this with SQL.

So while I can agree that original SQL looks much better than any kind of its imitation, I think that it is not necessary better for productivity.

Additionally I think that string mixins need some more features to make it possible to solve point 2. IDE will have to know what kind of DSL is in mixin. Maybe something like this:

mixin(sql.query, "SELECT ....");
mixin(sql.expression, "person.doctorid = doctor.id");
mixin(sql.statement, "INSERT ....");

...where sql.query, sql.expression, sql.statement are kind of markers usefull for IDE.

BR
Marcin Kuszczak
(aarti_pl)
December 24, 2008
Christopher Wright pisze:
> Denis Koroskin wrote:
>> Slightly off-topic.
>>
>> How would you implement, say, LIKE condition? Similar to the following, perhaps:
>> Query query = Select(a).Where(id.Like("%substring%"));
>>
>> You could implement "==" the same way:
>> Query query = Select(a).Where(id.EqualsTo(5));
> 
> downs way:
> auto query1 = select(a) /where/ "id" /eq/ 5;
> auto query2 = select(a) /where/ "name" /like/ "%bob%";

Nice, but I am not so sure that as much intuitive? :-)

BR
Marcin Kuszczak
(aarti_pl)
December 24, 2008
Sergey Gromov pisze:
>> downs way:
>> auto query1 = select(a) /where/ "id" /eq/ 5;
>> auto query2 = select(a) /where/ "name" /like/ "%bob%";
> 
> What a nice trick!
> 
> I don't like operator abuse, but sometimes it's a lesser evil.  And it's
> definitely the case with SQL queries.

I agree. In D raw operator overloading should be probably as discouraging as cast operator :-)

e.g.
opRawEqual()
opRawNotEquals()
etc.

BR
Marcin Kuszczak
(aarti_pl)
December 24, 2008
dennis luehring pisze:
>> It is possible and it works :-)
>> But with operator overloading it is so much more readable, than without it.
>>
>> Creating queries at runtime is quite common:
>>
>> age = 20;
>> string query = "Select name, surname FROM persons WHERE age = " + to!(string)(age);
> 
> that is not object + operator based - your flexibilty here comes from your string and the "runtime" interpretation of the sql semantic in your database ...
> 
> if you need an additional "LIKE" based on an codition you need to rebuild your object/operator concatination in complete:
> 
> if( gui.checkbox == true )
> {
>   SELECT a from b
> }
> else
> {
>   SELECT a from b WHERE c LIKE '% ~ C ~ %'
> }
> 
>> Compile time checking of SQLs will not be enough for any bigger program.
>> How would you insert your data into database? INSERT needs values which are taken e.g. from GUI and completely unknown at compile-time.
> 
> why is a value that comes from an gui not compile-time?
> not the value is what you need - its the type (when we talk about type safetyness)
> 
> how does vector-array get into Don's Blade strings? and why do i get
> compile-time errors when using the wrong type inside of the string?
> 
> and you can't even speak of type-safetyness when using only strings in your database communication - how can be your results typesafe
> (i don't like string[string] results-set) because the safetiness is programatical
> 
>> BTW. In recent release Boost team added a whole brand new library for domain specific languages embedded languages called Proto. I think that it means that there is quite a big need for such features. E.g. for mocking frameworks which will also profit from extended DSL sublanguages support in programming languages.
> 
> you should read into the details of using mixins - they are much much more flexible than you think (not just boring strings) - and with the base feature-set of D something like mock wouldn't even exist
> and what the boost guys to is to get around c++ base feature-set to express new thing with c++
> 
> @Ary does syntax coloring and smart auto-completen help while writing
> spirit based parsers? the complete meaning of ( * - \ ... is different to "normal" code
> 
> btw: don syntaxtree is also an great example of using mixins
> http://www.dsource.org/projects/mathextra/browser/trunk/blade/SyntaxTree.d

While I see your points here, there are still arguments against mixins. Please see my answer to Don's post.

BR
Marcin
(aarti_pl)
December 25, 2008
Reply to dennis,

> what about other domain-specific languages like the blade stuff
> or an ebnf parser (dparser?)

dparse  

http://www.dsource.org/projects/scrapple/browser/trunk/dparser/dparse.d

> - should these be more operator overloading dependend

Avoiding operator overloading was one of the objectives of dpares. My opinion of DSL's is that they should either use a syntax designed specifically for them or use a syntax that is designed to be much more general than for a general purpose language. But then I'm biased as this is getting into my day job.


December 25, 2008
Era Scarecrow schrieb:
>  Recently i've started reading about lex and yacc (or flex and bison) and as a comment in there, it wouldn't be too hard to use substitution and have a pre-processor convert it into pure D code.

and the name of that pre-processor is "mixin" in D, you can parse and generate code in here :-)
December 25, 2008
BCS schrieb:

>My opinion of DSL's is that they should either
>use a syntax designed specifically for
>them or use a syntax that is designed to be much more
>general than for a general purpose language.

perfect answer and my opinion too


December 26, 2008
aarti_pl wrote:
> Don pisze:
>> aarti_pl wrote:
>>> Andrei Alexandrescu pisze:
>>>  > We're trying to make that work. D is due for an operator overhaul.
>>>  >
>>>  > Andrei
>>>
>>> Is there any chance that we get possibility to overload "raw operators", like in C++? I think that they may coexist with currently defined operator overloads with simple semantic rules, which will not allow them to work together at the same time.
>>>
>>> I know that they may obfuscate code, but they are extremely useful when defining in D domain specific languages. For example I try to make SQL expressions work as D expressions:
>>
>>>
>>> string query = "SELECT * FROM a WHERE id=5;";
>>> -->
>>> Query query = Select(a).Where(Equals(id, 5));
>>>
>>> * "id" is D object in second expression
>>>
>>> This translation is quite awful and unreadable. It would be so much better to get:
>>>
>>> Query query = Select(a).Where(id == 5);
>>
>> I think that's still awful. I prefer:
>> Query query = mixin(SQL("SELECT * FROM a WHERE id=5"));
>  >
> 
> Thanks for example - it talks to me more than 1000 words :-)
> 
> Your proposal is indeed interesting. (And I think it is what Dennis Luehring was reffering to).
> 
> But I have to say it has some drawbacks. Let me enumerate them:
> 
> 1. Extending such a queries on runtime would be rather difficult IMHO, and will not look very nice. With my solution you can do something like this:
> ---
> Column cols = [person.name, person.surname, person.nick];
> for(i=0; i<rows; i++) {
>   InsertStatement insert = Insert();
>   foreach(Column col; cols) {
>     insert ~= insert.insert(col, getText(i, col));
>   }
>   db.execute(insert);
> }
> 
> * example not tested, but something like this is already possible in my framework.
> 
> Constructing queries dynamically is very useful for creating e.g. universal gui controls which could be just binded to database tables.
> 
> Another useful example is sending SQL expression (not the whole statement) as an argument to function.
> 
> To make it work nicely with mixins IMHO you will have to make this kind of SQL to look much uglier than in this simple case.
> 
> Do you have any proposals how it could look like with mixins?

There's nothing stopping you from using local variables in the mixin string. A simple possibility is to use $ for embedded variables. (You can avoid that, but it's much more difficult, and has some minor downsides, you can't have use a local variable called 'select', for example).
I pretty much got this working for BLADE, but the CTFE memory bug makes it completely unusable at present.

> 2. I see also problem with IDE-s which will have to be changed to understand DLSs in mixins. I think that it is doable and even can be done quite nice, but currently there is *no* support for such a feature. It means that you will not have:
> 
> a. syntax highlighting
> b. no IDE proposing your names of variables and methods
> c. no refactoring

That's true, and indeed very difficult to solve.

> 3. Sometimes having more expressiveness in language can avoid creating new DSLs. I think it is a Good Thing (tm). In fact I took that way and decided to integrate SQL DSL language into mother language. That way programmers don't have to learn new syntax, but just use existing syntax of mother language to solve specific problems. Using DSL in mother language resolves then into just writing special kind of API, which can be used in standard way to achieve goal. D and most other languages from C family are almost perfect candidates to make something like this with SQL.
> 
> So while I can agree that original SQL looks much better than any kind of its imitation, I think that it is not necessary better for productivity.

That's a worthwhile criticism of DSLs in general.