On Sunday, 8 October 2023 at 06:02:14 UTC, Jonathan M Davis wrote:
> The problem is that the compiler needs to be able to verify that the types match, and when the return type of a function is a dynamic array such as int[], it has no way of knowing how many elements the array has and therefore can't verify at compile time that the assignment will work. add a runtime check to verify that the number of elements match, but that's not the sort of thing that you typically do with a statically typed language.
I agree.
And solutions like "algebraic types" used by typescript are not applicable to D (You cant declare int|undefined)
const sorted=<T>([first,...xs]:T[]):T[] => first===undefined ? [] : [
...sorted(xs.filter(x=> x<=first )), first, ...sorted( xs.filter(x=> x > first))
];
console.log( sorted([1,2,3,4,-1,-2,-3]) );
But it should with pattern matching
auto sorted(T)(T[] entries) =>
match(entries) {
case [item, ...others] => ...
otherwise => []
}
Or with overloading (patter matching expressions on function signature... similar to haskell)
auto sorted(T)(T[] [item, ...others]) => ...;
auto sorted(T)(T[] []) => [];
Well, not really: because compiler can't predict witch "sorted" version will be called on compile time. (May be it should be a syntax suggar of an unique sorted method with match in the body)
> However, while there are some benefits to being able to do this, the response by many programmers from statically typed languages is that it's cleaner to create a struct for this sort of thing
I completly agree
> , since then the values are contained together, and they have names associated with them (since they'll be member variables of the struct). So, while some programmers definitely want tuple types to be built into D, a number of others don't like the idea. As such, it's an open question whether we'll ever have such tuples in D.
Destructuring is only a Syntax sugar applicable to well known types (i.e. Structs). It is not related (exclusively) with tuples:
The type of a function call (or a parameter) is perfectly known.
Typescript applies destructuring based on type matching (type members names):
type ICounter = {
inc: ()=>void
dec: ()=>void
value: ()=>number
}
function Counter(n:number=0):ICounter {
return {
inc: ()=>{ n++ };
dec: ()=>{ n-- }
value: ()=> n;
}
}
const {inc,value} = Counter();
inc();
inc();
console.assert( value() === 2 );
inc();
console.assert( value() === 3 );
It could be portable with Structs in D.
Personally, I found it is specially useful with parameters for "dependencies injection":
function CarsDAO( {db:{ withTransaction }, logger:{ info }}: IContext ):ICarsDao {
return {
createCar,
updateCar
}
function createCar(data:CarDto):Promise<string> {
info("Lets create a car");
return withTransaction( trx=> trx.executeQuery("insert ..... returning key") );
}
}
const context:IContext = {
logger: Singleton(logger),
db: Singleton(Db),
carsDao: Singleton(CarsDao),
}
(async ({ carsDAO:{ createCar }, logger }:IContext)=>{
data:CarDTO = { registration: "ASD1232", model: "Citroën XS" };
const key = await createCar( data )
logger.info( `Car ${key} has been registered`);
})(context);
This kind of destructuring is semantically rich.
Note: The "hard" part for this kind of solutions (dependency injection not based on classes) is the clousures management, and D solves it magnificently...
> Either way, the unpacking of dynamic arrays likely stands no chance whatsoever of ever being added, > because it would require runtime checks to determine whether the unpacking was valid.
This is what pattern matching, some day, at runtime, should solve :-)
-- Antonio