December 16, 2020
On Wednesday, 16 December 2020 at 12:30:06 UTC, ddcovery wrote:
> On Wednesday, 16 December 2020 at 10:39:38 UTC, Max Haughton wrote:
>> On Wednesday, 16 December 2020 at 10:04:03 UTC, ddcovery wrote:
>>> On Tuesday, 15 December 2020 at 17:45:20 UTC, a11e99z wrote:
>>>
>>>> [...]
>>>
>>> From my personal experience, the complication comes because D libraries and compiler itself follows the "convention" over "contract" way (similar to the "convention" over "configuration" with ruby on rails :-) ).
>>>
>>> [...]
>>
>> Consider that C++ has only just got template constraints (concepts), and they have been at the design stage, roughly, since I was born on to this earth.
>>
>> We have template constraints already, we could have nicer template constraints as a fairly trivial library solution (composing them isn't hard), but ultimately more templates puts a lot of pressure on the compiler for not much benefit.
>
> As a good friend told me 20 years ago: "strong typing allows you to see an application as a set of gears that fit together perfectly"... with templates, you don't know the shape of the gears until compiler tries to build them... this opens a lot of possibilities and introduces some problems.
>
> Problem with "template constraints" is it tries to give a "declarative" vision of something that is solved imperatively  (if you generate a "isEquatable" constraint... you must generate imperative static code to check what "isEquatable" means) and this is a barrier for "intelligense" systems like VSCode plugins that helps developers to check it's code BEFORE it is compiled.  The plugin can't determine what "isEquatable" means and can't help you saying "Person class is not Equatable"... a template constraint is a "custom" blackbox that, semantically, doesn't associate language dependent declarative concepts (like inheritance or interfaces).  Correct me if I'm in an error... I am not really experienced D developer.
>
> If you will work with D, you must be aware about this kind of "small" barriers.

Yes your analysis is correct. The barrier to a better intellisense is clearly that it would have to to check expressions semantics and be able to evaluate them statically, just like the compiler does.

Static interfaces for example would make intellisense easier (not need to rewrite the ASTs !) but would provide a less modular subset of what is possible with D (also known as static introspection).

Honestly if I was to create a language I would be **very** prudent with the adoption of templates (and even generics) and would rather choose static interfaces. For intelissense the simple contract that class X implements the behavior defined by static interface Y and for a specified type is simple enough.

But for D it's too late. You can have a library solution for static interfaces but then it will be template-based and that don't help.
December 16, 2020
On Wednesday, 16 December 2020 at 10:04:03 UTC, ddcovery wrote:
> On Tuesday, 15 December 2020 at 17:45:20 UTC, a11e99z wrote:
>
>> D is already very complicated for newbies.
>> if u cannot write program (something connect to http/grpc service) in a few hours than "f*ck it".
>> man need 4-12 months for learning D.
>
> From my personal experience, the complication comes because D libraries and compiler itself follows the "convention" over "contract" way (similar to the "convention" over "configuration" with ruby on rails :-) ).
>
> Example:  Do you need to be equatable... then add an "opEquals" method to your class/struct (operator overload)... you don't need to implement the "IEquatable" or "IComparable" interface.
>
> A first look to ranges libraries (it is really impressive) exposes that it is based on introspection (static/compile time  code), not on interfaces/contracts.  This makes it difficult for newbies to understand how it works because there is not a "contract" (an interface) explaining you what it does.   If you try to read de comments in the own library, it is oriented to doc generation:  it is extensive and thought for post processed documentation generation and really impossible (in my case) as a guidance to understand the function signature.  The only way to read this "comments" is navigating to dlang.org web and reading the generated documentation.
>
> This gives the real power and weakness to D:   The missing contracts delegates to the compile-time static code the final real code generation... you need to compile to know if you are developing well, no interfaces/contracts can be used to guide you before this phase.  The problem is clean:  functions signature doesn't gives you enough information to understand what exactly it does and you need 4 or more months to acquire the knowledge (the intuition of the typical developer is not enough: you must work it to adapt)
>
> It is like beginning with Functional programming:  you need to understand what it means before trying to write complex code... and D introduces a new paradigm itself for developers that usually works in "productive" more known ways.
>
> Of course, when you change your way of thinking, D reveals it's real power:  *auto*, *alias*,... the same function can be applied to thinks that are not related.  It's magic? not: D doesn't use generics, it uses templates and templates are not generics.
>
> Newbies need to understand this two main concepts:
> * D is not based in contracts (it can, but it tries not to use):  Type resolution is more "introspection" based than declaration based.
> * D has templates, NOT generics...
>
>
>
> Final conclusion... look at this:
>
> void main(){
>   0.doThis!(n=>assert(n==0));
>   assert( 0.doThis!(n=>n) == 0 );
>   assert( "hello".doThis!(s=>s) == "hello" );
>   assert( "hello".doThis!(s=>s.length) == 5 );
>   assert( doThis!(u=>u)(true) );
> }
> auto doThis(alias f, T)(T value){
>   // Nothing in the "alias f" tells you that it must be an unary function or
>   // witch type must return...
>   return f(value);
> }
>
> Someone coming from java or c# will suffer an aneurysm, but it is really... wonderful? :-)

You mean like this, yeah it is a bit more boilerplate, but no I didn't suffer an aneurysm

using System;
using System.Linq.Expressions;


public static class Helpers
{
	public static R dothis<T, R>(this T val, Expression<Func<T,R>> f)
	{
		var func = f.Compile();
		return func(val);
	}
	
	public static void dothis<T>(this T val, Expression<Action<T>> f)
	{
		var func = f.Compile();
		func(val);
	}
}

public class Program
{
	public static void Main()
	{
		0.dothis(n => assert(() => n == 0));
		System.Diagnostics.Debug.Assert(0.dothis(n => n) == 0);
		System.Diagnostics.Debug.Assert("hello".dothis(n => n) == "hello");
		System.Diagnostics.Debug.Assert(Helpers.dothis(true, n => n));
	}
	
	public static void assert(Expression<Func<bool>> exp) {
		var expc = exp.Compile();
		System.Diagnostics.Debug.Assert(expc());
	}
}


December 16, 2020
On Wednesday, 16 December 2020 at 13:26:44 UTC, Paulo Pinto wrote:
> On Wednesday, 16 December 2020 at 10:04:03 UTC, ddcovery wrote:
>> ...
>>
>> Final conclusion... look at this:
>>
>> void main(){
>>   0.doThis!(n=>assert(n==0));
>>   assert( 0.doThis!(n=>n) == 0 );
>>   assert( "hello".doThis!(s=>s) == "hello" );
>>   assert( "hello".doThis!(s=>s.length) == 5 );
>>   assert( doThis!(u=>u)(true) );
>> }
>> auto doThis(alias f, T)(T value){
>>   // Nothing in the "alias f" tells you that it must be an unary function or
>>   // witch type must return...
>>   return f(value);
>> }
>>
>> Someone coming from java or c# will suffer an aneurysm, but it is really... wonderful? :-)
>
> You mean like this, yeah it is a bit more boilerplate, but no I didn't suffer an aneurysm
>
> using System;
> using System.Linq.Expressions;
>
>
> public static class Helpers
> {
> 	public static R dothis<T, R>(this T val, Expression<Func<T,R>> f)
> 	{
> 		var func = f.Compile();
> 		return func(val);
> 	}
> 	
> 	public static void dothis<T>(this T val, Expression<Action<T>> f)
> 	{
> 		var func = f.Compile();
> 		func(val);
> 	}
> }
>
> public class Program
> {
> 	public static void Main()
> 	{
> 		0.dothis(n => assert(() => n == 0));
> 		System.Diagnostics.Debug.Assert(0.dothis(n => n) == 0);
> 		System.Diagnostics.Debug.Assert("hello".dothis(n => n) == "hello");
> 		System.Diagnostics.Debug.Assert(Helpers.dothis(true, n => n));
> 	}
> 	
> 	public static void assert(Expression<Func<bool>> exp) {
> 		var expc = exp.Compile();
> 		System.Diagnostics.Debug.Assert(expc());
> 	}
> }

Ahhhh... you read the entire post... thanks!!!

You have to recognize that you know D (and you like it)... otherwise, first impression could have been "What?"...  methods are "extension" methods by default, you can put "auto" as a result, you can declare an "alias f" and compiler will do the magic inference... it is a lot of work under scenes (impressive one)...

I'm curious about how a Java developer will try to solve the same problem.
December 16, 2020
On Tuesday, 15 December 2020 at 11:59:46 UTC, Max Haughton wrote:
> It would be more fruitful to annotate non-GC code i.e. it would need to be subject to ownership checking, which will require annotation to interact with existing D semantics (specifically for interprocedural analysis)

There should be a distinction between libraries and application. Libraries should type annotate ownership, borrowing and deterministic destruction. Then they can be used with or without GC and a precise GC would be faster with this in place.

But D has to choose whether it should support high level programming or not, that would determine which direction the lnguage should go. Right now it is aiming for stagnation. Well, that won't last...
1 2 3 4 5
Next ›   Last »