www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - ugly and/or useless features in the language.

reply Alain De Vos <devosalain ymail.com> writes:
Which parts in dlang don't you use and why ?

Personally i have no need for enum types, immutable is doing fine.
Auto return types i find dangerous to use.
Voldermont types.
Named initialiser.
Tuple features.
Maybe some other ?
Feature creep can make your own code unreadable.

Offcourse taste can very from person to person.
May 15
next sibling parent reply Ola Fosheim Grostad <ola.fosheim.grostad gmail.com> writes:
On Saturday, 15 May 2021 at 14:31:08 UTC, Alain De Vos wrote:
 Feature creep can make your own code unreadable.
Having many ways to express the same concept makes code harder to read. This is an issue in C++, but you can combat it by creating coding norms. In general it is better to have fewer features and instead improve metaprogramming so that missing features can be done in a library. Also some features could be merged, like alias and enum constants.
May 15
parent reply Tony <tonytdominguez aol.com> writes:
On Saturday, 15 May 2021 at 21:15:01 UTC, Ola Fosheim Grostad 
wrote:
 On Saturday, 15 May 2021 at 14:31:08 UTC, Alain De Vos wrote:
 In general it is better to have fewer features and instead 
 improve metaprogramming so that missing features can be done in 
 a library.
Why is metaprogramming added features better than the same features added in the language? One is standard between entities, the other is not.
May 23
next sibling parent sighoya <sighoya gmail.com> writes:
On Sunday, 23 May 2021 at 08:35:31 UTC, Tony wrote:
 Why is metaprogramming added features better than the same 
 features added in the language? One is standard between 
 entities, the other is not.
Some points: - Some features aren't general enough to be added as builtin but make sense to have them in libraries - library features could be extended and modified arbitrarily which isn't possible with builtin features - if better library features are found they can simply be removed from the library while probably breaking the library, it doesn't break the language which is much of a bigger problem - most problems with builtin features is that they overwrite grammar for a certain scope a.k.a syntactic sugar leading to learn new rules/a new language (see C++) while a general framework would reuse the same grammar again and again providing uniformity - most builtin features are added incrementally to a language in order to be predictable/implementable, unfortunately this leads often to fragmentation because later with enough practical experience you see another approach to solve the problem, making this approach available may overlap with the feature you already added, i.e. it solves to some extent the same problems but with other tradeoffs making it hard to choose the right approach. There are also disadvantages, among them the locality/globaility problem: Implementing features via macros may need context information and other existing features need to be informed of the new feature in order to handle it correctly which would require many hooks which can't be solved solely with macros. We would require massive compiler reflection support for this. Further, it is unclear how it would behave at boundaries where hooks would collide with each other.
May 23
prev sibling parent reply Ola Fosheim Grostad <ola.fosheim.grostad gmail.com> writes:
On Sunday, 23 May 2021 at 08:35:31 UTC, Tony wrote:
 On Saturday, 15 May 2021 at 21:15:01 UTC, Ola Fosheim Grostad 
 wrote:
 Why is metaprogramming added features better than the same 
 features added in the language? One is standard between 
 entities, the other is not.
There are many reasons, one important one is consistency and being able to prove that the type system is sound/reasonable. Syntactic sugar is ok though, so adding syntax does not create problems as long as what it expands to can be expressed constuctively using exising language constructs.
May 23
parent reply Ola Fosheim Grostad <ola.fosheim.grostad gmail.com> writes:
On Sunday, 23 May 2021 at 10:24:53 UTC, Ola Fosheim Grostad wrote:
 On Sunday, 23 May 2021 at 08:35:31 UTC, Tony wrote:
 On Saturday, 15 May 2021 at 21:15:01 UTC, Ola Fosheim Grostad 
 wrote:
 Why is metaprogramming added features better than the same 
 features added in the language? One is standard between 
 entities, the other is not.
There are many reasons, one important one is consistency and being able to prove that the type system is sound/reasonable. Syntactic sugar is ok though, so adding syntax does not create problems as long as what it expands to can be expressed constuctively using exising language constructs.
As an example D has a focus on memory safety, but in order to prove that property you have to prove that all possible combinations of language constructs (all valid programs) retains memory satety as a propery. The more distinct features you have, the more difficult it get because you get more and more combinations.
May 23
parent reply Alain De Vos <devosalain ymail.com> writes:
It is sufficient to have a bit complex gui and database access 
and the  safe annotation can nowhere be used in your program.
The compiler misses scopes checks without.
May 23
parent reply Ola Fosheim Grostad <ola.fosheim.grostad gmail.com> writes:
On Sunday, 23 May 2021 at 12:08:31 UTC, Alain De Vos wrote:
 It is sufficient to have a bit complex gui and database access 
 and the  safe annotation can nowhere be used in your program.
 The compiler misses scopes checks without.
I think you are supposed to use trusted to tell the compiler that the code is safe if you are certain that calling the code cannot create issues. I dont use safe myself, maybe someone else have better advice.
May 23
parent reply Alain De Vos <devosalain ymail.com> writes:
This one compiles without any problem.
Maybe someone can enlighten us on the status of 
scope(d)-variables and dip-1000.
It is not fully clear for me.
```
import std.stdio;
void main()  trusted
{
int *q=null;
     {
	int a;
	q=&a;
     }
*q=5;
}
```
May 23
next sibling parent Dennis <dkorpel gmail.com> writes:
On Sunday, 23 May 2021 at 14:13:36 UTC, Alain De Vos wrote:
 This one compiles without any problem.
You annotated main ` trusted`, which means you want the compiler to assume it to be ` safe` without checking it. Mark it ` safe` and it reports:
 Error: address of variable `a` assigned to `q` with longer 
 lifetime
May 23
prev sibling parent Mike Parker <aldacron gmail.com> writes:
On Sunday, 23 May 2021 at 14:13:36 UTC, Alain De Vos wrote:
 This one compiles without any problem.
 Maybe someone can enlighten us on the status of 
 scope(d)-variables and dip-1000.
 It is not fully clear for me.
 ```
 import std.stdio;
 void main()  trusted
 {
 int *q=null;
     {
 	int a;
 	q=&a;
     }
 *q=5;
 }
 ```
You might find this helpful: https://dlang.org/blog/2016/09/28/how-to-write-trusted-code-in-d/
May 23
prev sibling next sibling parent zjh <fqbqrr 163.com> writes:
I want to be able to support CP936, not just UTF8.

I can't use CP936. It's my pet peeve.

Hopefully we can solve the coding problem just like Python with 
#encoding= GBK.
May 15
prev sibling next sibling parent reply "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Sat, May 15, 2021 at 02:31:08PM +0000, Alain De Vos via Digitalmars-d-learn
wrote:
 Which parts in dlang don't you use and why ?
 
 Personally i have no need for enum types, immutable is doing fine.
 Auto return types i find dangerous to use.
 Voldermont types.
 Named initialiser.
 Tuple features.
 Maybe some other ?
 Feature creep can make your own code unreadable.
 
 Offcourse taste can very from person to person.
I cannot live without auto return types and Voldemort types. They are my bread and butter. Take them away, and I might as well go back to C/C++. Also, unittests. The quality of my code has improved by leaps and bounds ever since I started writing unittests, and their convenience (you can write them literally next to the code they test) cannot be overstated. What I find inconvenient: - const-correctness, including immutable. It's all nice and everything because of its strong guarantees, but that also greatly limits its usefulness. In practice, I find that it's really only usable in self-contained, low-level code / leaf node modules in the program's dependency graph. For high-level code it quickly becomes a burden to maintain const-correctness, and often the need for casts will arise because there will always be *something* that wants logical const rather than physical const / immutable, so APIs that try to be const correct usually have bugs / missing cases where something should be const but can't be, or something should accept mutable but can't because of overzealous application of const. - Don't get me started about inout, which is quirky, has ambiguous cases as soon as delegates / function pointers are involved, and just introduces weird corner cases into the type system. Terrible for generic code because of the difficulty of dealing with cases involving inout in a generic way. What I find ugly: - shared, and all of its quirks and incomplete implementation. - The fact that byte + byte cannot be assigned back to a byte without a cast. The fact that f(1) will choose the f(bool) overload instead of the f(int) overload. The fact that Walter insists that bool is a 1-bit integral type instead of a true boolean type. - Autodecoding in Phobos, the big wart that we still haven't rid ourselves of after so many years. - Attribute proliferation. We should have had type inference integrated into the language from the beginning, but alas, that ship has already long sailed and it's too late to change that now. - Other incomplete / half-implemented stuff in D. T -- There are three kinds of people in the world: those who can count, and those who can't.
May 16
parent Ola Fosheim Grostad <ola.fosheim.grostad gmail.com> writes:
On Sunday, 16 May 2021 at 16:16:22 UTC, H. S. Teoh wrote:
 I cannot live without auto return types and Voldemort types. 
 They are my bread and butter. Take them away, and I might as 
 well go back to C/C++.
C++ has both?
 What I find ugly:
 - shared, and all of its quirks and incomplete implementation.
Shared semantics are wrong, as in not safe. Someone with a theoretical background should have been consulted... I am not really sure why it was given semantics with no complete solution, you cannot evolve concurrency designs.
 - The fact that byte + byte cannot be assigned back to a byte 
 without a
   cast.
I dont think you should be able to do anything with bytes without a cast...
 - Attribute proliferation.  We should have had type inference 
 integrated
   into the language from the beginning, but alas, that ship has 
 already
   long sailed and it's too late to change that now
Why is it too late? I dont think it is.
May 17
prev sibling next sibling parent reply Berni44 <someone somemail.com> writes:
On Saturday, 15 May 2021 at 14:31:08 UTC, Alain De Vos wrote:
 Which parts in dlang don't you use and why?
There is one feature (actually a mix of features) I'd be happy not to use, but it is not possible: I call it autoreals, because it resembles somewhat the idea behind autodecoding - in both cases the compiler (or Phobos) does something automatically that you cannot avoid and sometimes causes real headache, but which you could do easily yourself if it were not done automatically): What I'm talking about is - reals being differently implemented on different computers - reals being internally used for computation and intermediate storage - reals being automatically used in CTFE (and reals in CTFE might differ from the reals at runtime) All together this ends in generic code (for example in libraries) behaving more or less like a random generator; at least it feels like this. I would be able to cope with the first point by either not using reals at all or `static if` to generate separate code for every version. But together with the other two "features" reals cannot be ignored anymore. You cannot even assume a function with return type double to return a double. So to be sure to have a double, when a double is needed you need to do stuff like ``` double d = some_fun(); ulong tmp = *cast(ulong*) &d; tmp ^= 12543; /* maybe here some more ugly stuff that doesn't change the value until it is enough to trick the optimizer */ tmp ^= 12543; d = *cast(double*) &tmp; ``` Even worse with CTFE, where you get values that are neither NaN, nor infinity but larger then `<type>.max`. And you cannot even use `static if` to find out which reals are used in CTFE, because CTFE might use different reals or reals on an other platform or whatever. So to be able to find out which real you use, you need to add more ugly code like ``` if (__ctfe) { if (real.max + 1 != real.infinity && real.max + 10 - 20 < real.max) { ... } else { } } ``` Finally you end up writing several hundred lines of code for something that would have fitted in one line without autoreals; probably you would prefer to write a library (using heavy amount of `asm` parts) with types `Float` and `Double` that is just doing what float and double are normally supposed to do. What I really dislike about this is, that you have no means to escape from it, while the other way round it would be easy: If you really want to use reals instead of double, you could just use reals...
May 17
next sibling parent Alain De Vos <devosalain ymail.com> writes:
For a number it's best to have something you know how many bytes 
it takes in memory.
May 18
prev sibling parent Alain De Vos <devosalain ymail.com> writes:
Knowing the number of bytes in memory is a good thing.
May 18
prev sibling next sibling parent reply sighoya <sighoya gmail.com> writes:
On Saturday, 15 May 2021 at 14:31:08 UTC, Alain De Vos wrote:
 Which parts in dlang don't you use and why ?
Well, I don't like magic constructs in the language like the type of AliasSeq you can't touch. But the more general problem in D are not features per se, but how they are composed of. For instance: Why no AST macros instead of string mixins, templates, mixin templates and alias? All these forms could be special ast macros. Structs are nice but at the same time awful to use because they are incompatible with interfaces and classes, I hope this will change to some extent, but I think it wouldn't be that smooth. Being multi-paradigmatic seems nice at a first sight, but which paradigm should your standard library and other frameworks follow? Providing all paradigms at once make your frameworks redundant and bloated, so you just follow one which is most of the time not OOP. This is the same problematic with custom memory containers. I wish we would only use structs as ref/value types with the ability to box them to interfaces automatically increasing compatibility between libraries to a large extent.
May 22
parent reply Ola Fosheim =?UTF-8?B?R3LDuHN0YWQ=?= <ola.fosheim.grostad gmail.com> writes:
On Saturday, 22 May 2021 at 13:26:38 UTC, sighoya wrote:
 But the more general problem in D are not features per se, but 
 how they are composed of.
 For instance: Why no AST macros instead of string mixins, 
 templates, mixin templates and alias?
 All these forms could be special ast macros.
I think AST macros require a tiny core language and having most of the language features being implemented by macros. The D AST is not really suitable as it stands. D is a bit like C++ in this regard, there might be a minimal core language that could be distilled from it, but it would take a D3 full breaking change to get there, so it won't happen.
 Structs are nice but at the same time awful to use because they 
 are incompatible with interfaces and classes, I hope this will 
 change to some extent, but I think it wouldn't be that smooth.
You could probably expose classes in a form that is compatible with structs, but that would expose implementation details and give implementors less freedom.
May 22
parent reply sighoya <sighoya gmail.com> writes:
On Saturday, 22 May 2021 at 13:31:45 UTC, Ola Fosheim Grøstad 
wrote:
The D AST is not really suitable as it stands.
D is a bit like C++ in this regard, there might be a minimal 
core language that could be distilled from it, but it would take 
a D3 full breaking change to get there, so it won't happen.
Well, I think D without templates is already a lightweight core language. The real cost comes with the template language. But I think providing an external ast tree mapped onto the changing internal one used by DMD would be a feasible approach.
May 22
parent Ola Fosheim Grostad <ola.fosheim.grostad gmail.com> writes:
On Saturday, 22 May 2021 at 17:32:34 UTC, sighoya wrote:
 But I think providing an external ast tree mapped onto the 
 changing internal one used by DMD would be a feasible approach.
It is feasible, but if you want to do it well you should think in terms of rewrite engines with patternmatching, think XSLT or Pure (not exactly, but in that direction). I think it is better to design such a language from scratch.
May 22
prev sibling parent z <z z.com> writes:
On Saturday, 15 May 2021 at 14:31:08 UTC, Alain De Vos wrote:
 Which parts in dlang don't you use and why ?

 Auto return types i find dangerous to use.
I found `auto` and `ref`(yes just `ref`) return types very useful for bypassing the type system, eg.: ```D ///function requires lvalue and the return value can be of any type while still being the same data. ref mutateSomething(A)(ref A something) { static if (isArray!A){/*...*/} else {/*...*/} return something; } ``` Other than that, i've found tuples limited in usage compared to just using a struct or static arrays.(the main problem is the inability to use runtime indexing even if the types match.) The rest, i don't use from lack of interest or awareness it even exists.
May 23