Advertisement

Idle: Wished-for programming language design?

Started by June 08, 2013 07:44 PM
36 comments, last by cr88192 11 years, 8 months ago

'll have to disagree on the null topic, hell even the guy who created the concept of null disagrees and cites it as his worse mistake ever. If you think of it null is a very bad idea, it's a way to represent an incorrect state, so that you can check for that incorrect state later on, what's better is not allowing an incorrect state at any time and sticking to that, this means redisigning many APIs but then that's also why i wouldn't mind breaking changes. I would like a C# without null, without being able to declare something that would lead to null, without the null keyword etc.

I've heard this sentiment echoed a number of places, and being mainly a C++ programmer, any place where I have the luxury I use references, but there are many times where I have to use pointers instead of references. How do you handle the situation where you require delayed construction of an object? Or there are circular dependencies? I find I often come across cases where I can't initialize an object to a valid state till a while after the object is created/used. Some are trivial to work around, but not all. How do you work around this? For example, how would you implement a double-linked list?

or, even, say, implement a linked list with a finite length?... you need something to terminate the list with, and this is generally done with a null...

also, a null type is pretty useful when implementing something like a hash-table, where not all the entries will necessarily have valid values.

much better I think would be having an explicit "not null" notation, rather than eliminating null from a language...

now, as for people thinking things were a mistake:

there is also a tired argument that many people also believe that the concept of variable assignment is a mistake.

doesn't really mean that there is as much practical usefulness for languages which lack the concept of variable assignment though (they typically only really gain niche usage).

sometimes the benefits of a feature outweigh the costs...

Some things like linked lists would need to change a bit yes, i don't see a problem with that, i'd gladly embrace some change in exchange for getting rid of null. Also all languages don't need to be good for everything, as i mentioned those changes wouldn't necesarily be good for games / realtime apps, but for exemple in years working on business application development, i haven't needed a linked list once, not once.

If an entry doesn't have a hash value, then it shouldn't be in a hash table to begin with imho, so that's a positive vote for no nulls from my side, disallowing the kind of hacky "lets fix issue X by using null and changing the expected behavior" type of mentality that resides around it. If something can't properly be defined in a specialized collection, don't try to stuff it in that collection, and be glad the framework is telling you you can't!

And yes many people think that "X" or "Y" or "Z", what's noteworthy here is not that "someone" thinks that null shouldn't exist, nor even that someone significant thinks so, it's that the GUY WHO INVENTED IT thinks so, that's quite a huge diference in my book and definately noteworthy.

Sure you can find dozens of things you can't do if you remove nulls, but you must first think of 2 things : 1) are those things actually good? and 2) if i try to solve it without nulls, do i not end up with a better result?

May not be a good solution as i just think of it as i type but for example linkedlist could simply return element interfaces wraping the value with IElement having current / hasnext/hasprevious and being castable in IPreviousElement:Element if it hasprevious and vice versa, that way you could end up on an ielement that hasnext = false and you'd know it's not castable to an INextElementContainer , if you checked it you'd see it's underlying type is a FinalElement:IElement and that it doesn't contain any null properties. There, double linked list without null.

but, why not just flag which variables you don't want to ever be null? then it can be largely enforced at compile-time, and all is good.

this way, where needed, this can be enforced, and the language can still be useful for doing general purpose programming.

also, it wouldn't require common data structures to be implemented with wacky "under the hood" logic either (or lead to people circumventing it using convoluted mechanisms).

EDIT: sort of like, "Foo! obj=new Foo();" or "@NonNull Foo obj=new Foo();"...

ADD: my language already defines "type!" as an explicit non-null indicator, and exists as the logical inverse of "type?".

Hmm, regarding the null discussion, having both types, nullable and non nullable would be a good start (c# at least allows nullable for primitive types). Having non nullable as default and nullable as special version would be neat.

Fruny: Ftagn! Ia! Ia! std::time_put_byname! Mglui naflftagn std::codecvt eY'ha-nthlei!,char,mbstate_t>

Advertisement

C# with the following features would be nice.

- enum as a generic constraint

- ability to use ref / out on properties

- SIMD

I am happy with everything else atm in both C# / C++ but then I get told I am too easy to please -.-

Oh and people should be fined or jailed for confusing ASP.NET WebForms with ASP.NET MVC

Optional markup used for function argument validation and range restriction, shown in the IDE's "intellisense" tooltips as well.

"void fun(validate(arg < 100) int arg)" would cause an error if arg is greater-than-or-equal to 100.

"void fun(range(5, 10) int arg)" would automatically clamp "arg" in the 5-10 range before the function body executes.

Given just how much of programming is mathematics, these always seemed like a no-brainer to me but I've yet to use a language which implements something like them.

Fixed point decimals as a primitive type instead of having to rely on 3rd party APIs or rolling your own. They solve so many audio and video problems that I don't understand why we keep trudging on with the pitfalls of floating point numbers in languages that are typically used for game development.

Hmm, regarding the null discussion, having both types, nullable and non nullable would be a good start (c# at least allows nullable for primitive types). Having non nullable as default and nullable as special version would be neat.

yeah. conservative here is having non-null as the default behavior for value types, since typically null doesn't make sense for value types.

now, making non-null the default for reference types with explicit nullable references could be interesting, but would still be a bit unorthodox.

C# with the following features would be nice.

- enum as a generic constraint

- ability to use ref / out on properties

- SIMD

I am happy with everything else atm in both C# / C++ but then I get told I am too easy to please -.-

Oh and people should be fined or jailed for confusing ASP.NET WebForms with ASP.NET MVC

yep.

the issue with properties I think is mostly because ref/out are internally implemented as pointers, and supporting them with pointers would lead either to an implementation / performance issue, or to funky semantics (such as the setter for the property not being called until after the function-call returns, rather than immediately whenever the variable is assigned).

SIMD would also be nice.

a minor issue though is that there isn't really a "standard" cross-architecture SIMD, which would likely mean that the underlying mechanics would need to be abstracted some (potentially at some efficiency cost). this is likely to manifest itself in the HLL either as vector operators, as array-based operators, or some combination thereof.

even as such, it would probably still be better regarding usability than the use of ASM or explicit SIMD intrinsics, and higher performance than the use of straight scalar code (say because of programmers being like "screw it, not going to mess with the SSE intrinsics...").

Optional markup used for function argument validation and range restriction, shown in the IDE's "intellisense" tooltips as well.

"void fun(validate(arg < 100) int arg)" would cause an error if arg is greater-than-or-equal to 100.

"void fun(range(5, 10) int arg)" would automatically clamp "arg" in the 5-10 range before the function body executes.

Given just how much of programming is mathematics, these always seemed like a no-brainer to me but I've yet to use a language which implements something like them.

part of the issue here is mostly that range checks don't come free, and typically people only really add them in cases where it is essentially all but necessary in order to ensure correct operation of the underlying VM/runtime (such as the case of bounds-checks on arrays). correct operation of the program is more often seen as an issue for the programmer to deal with.

the sibling of this: range-defined numeric types, have existed in a few languages (even as far back as COBOL, and also in languages like Ada), but haven't really caught on due to it being relatively easier to simply have the programmer define things in terms of one of the machine-defined fixed-width numeric types (and presumably, because much of the time programmers don't care much about the exact range of a value much beyond "will it fit?").

Fixed point decimals as a primitive type instead of having to rely on 3rd party APIs or rolling your own. They solve so many audio and video problems that I don't understand why we keep trudging on with the pitfalls of floating point numbers in languages that are typically used for game development.

dunno...

most compiler people seem to think of fixed point mostly as "an embedded system thing", which leads to such annoyances as there being an ISO standard for fixed-point arithmetic in C, but compilers seemingly only have this enabled when compiling for targets like ARM.

it is like having "__int128" that only works on 64-bit targets, why?... it isn't actually really any more complicated to implement "__int128" on 32-bit x86 than it is to implement 64-bit "long-long", except that the performance is a little worse. it does more harm to have types which only exists on certain targets, than it does to have types which may just have lackluster performance on a given target.

I have read some compiler maintainers write things which implies that they believe that the DCT transform in a typical image or video codec *actually uses the cos() function*, and was like "sigh..." (a naive DCT using the "cos()" function is far too slow to even really be worthwhile for offline/batch image processing, much less for video...). (not that I don't appreciate having moderately fast sin/cos/sqrt/... functions though).

luckily at least, it isn't too critical, since fixed-point can be done easily enough using good old integers and shifts...

I guess this goes roughly in the same area as explicit endianess modifiers and language support for 16-bit half-floats.

Advertisement

'll have to disagree on the null topic, hell even the guy who created the concept of null disagrees and cites it as his worse mistake ever. If you think of it null is a very bad idea, it's a way to represent an incorrect state, so that you can check for that incorrect state later on, what's better is not allowing an incorrect state at any time and sticking to that, this means redisigning many APIs but then that's also why i wouldn't mind breaking changes. I would like a C# without null, without being able to declare something that would lead to null, without the null keyword etc.

I've heard this sentiment echoed a number of places, and being mainly a C++ programmer, any place where I have the luxury I use references, but there are many times where I have to use pointers instead of references. How do you handle the situation where you require delayed construction of an object? Or there are circular dependencies? I find I often come across cases where I can't initialize an object to a valid state till a while after the object is created/used. Some are trivial to work around, but not all. How do you work around this? For example, how would you implement a double-linked list?

or, even, say, implement a linked list with a finite length?... you need something to terminate the list with, and this is generally done with a null...

also, a null type is pretty useful when implementing something like a hash-table, where not all the entries will necessarily have valid values.

much better I think would be having an explicit "not null" notation, rather than eliminating null from a language...

now, as for people thinking things were a mistake:

there is also a tired argument that many people also believe that the concept of variable assignment is a mistake.

doesn't really mean that there is as much practical usefulness for languages which lack the concept of variable assignment though (they typically only really gain niche usage).

sometimes the benefits of a feature outweigh the costs...

Some things like linked lists would need to change a bit yes, i don't see a problem with that, i'd gladly embrace some change in exchange for getting rid of null. Also all languages don't need to be good for everything, as i mentioned those changes wouldn't necesarily be good for games / realtime apps, but for exemple in years working on business application development, i haven't needed a linked list once, not once.

If an entry doesn't have a hash value, then it shouldn't be in a hash table to begin with imho, so that's a positive vote for no nulls from my side, disallowing the kind of hacky "lets fix issue X by using null and changing the expected behavior" type of mentality that resides around it. If something can't properly be defined in a specialized collection, don't try to stuff it in that collection, and be glad the framework is telling you you can't!

And yes many people think that "X" or "Y" or "Z", what's noteworthy here is not that "someone" thinks that null shouldn't exist, nor even that someone significant thinks so, it's that the GUY WHO INVENTED IT thinks so, that's quite a huge diference in my book and definately noteworthy.

Sure you can find dozens of things you can't do if you remove nulls, but you must first think of 2 things : 1) are those things actually good? and 2) if i try to solve it without nulls, do i not end up with a better result?

May not be a good solution as i just think of it as i type but for example linkedlist could simply return element interfaces wraping the value with IElement having current / hasnext/hasprevious and being castable in IPreviousElement:Element if it hasprevious and vice versa, that way you could end up on an ielement that hasnext = false and you'd know it's not castable to an INextElementContainer , if you checked it you'd see it's underlying type is a FinalElement:IElement and that it doesn't contain any null properties. There, double linked list without null.

but, why not just flag which variables you don't want to ever be null? then it can be largely enforced at compile-time, and all is good.

this way, where needed, this can be enforced, and the language can still be useful for doing general purpose programming.

also, it wouldn't require common data structures to be implemented with wacky "under the hood" logic either (or lead to people circumventing it using convoluted mechanisms).

EDIT: sort of like, "Foo! obj=new Foo();" or "@NonNull Foo obj=new Foo();"...

ADD: my language already defines "type!" as an explicit non-null indicator, and exists as the logical inverse of "type?".

Because it doesn't enforce the same thing at all, if you only declare a variable to be non null, then that info cannot propage, if the very concept of null is gone, you can be guaranteed nothing you work with (including framework returned data and data passed to your functions) will ever be null, i don't care about declaring non null variables, i can already do that by never asigning null to them, i care about the concept of null being gone, and i actually LIKE the fact it changes design of the things you mention to work diferently, to me it's less brittle. For example the linked list is as simple to implement without null, insteaf of having linked list elements with current & next, you have Element with current, and FinalElement with Next , inheriting from Element, it's the same thing really, you just removed the use of the null concept for it.

Because it doesn't enforce the same thing at all, if you only declare a variable to be non null, then that info cannot propage, if the very concept of null is gone, you can be guaranteed nothing you work with (including framework returned data and data passed to your functions) will ever be null, i don't care about declaring non null variables, i can already do that by never asigning null to them, i care about the concept of null being gone, and i actually LIKE the fact it changes design of the things you mention to work diferently, to me it's less brittle. For example the linked list is as simple to implement without null, insteaf of having linked list elements with current & next, you have Element with current, and FinalElement with Next , inheriting from Element, it's the same thing really, you just removed the use of the null concept for it.

if the variable is declared non-null, then the runtime will not allow null to be assigned to it (this can be enforced both by static inference and, if needed, by throwing an exception when an attempt is made), and if explicit conversions are required, then there is incentive to use it consistently.

it is roughly the same sort of thing as keywords like 'const' or 'final'.

in the worst case, it is basically in the same camp as goto...

Optional markup used for function argument validation and range restriction, shown in the IDE's "intellisense" tooltips as well.

"void fun(validate(arg < 100) int arg)" would cause an error if arg is greater-than-or-equal to 100.

"void fun(range(5, 10) int arg)" would automatically clamp "arg" in the 5-10 range before the function body executes.

Given just how much of programming is mathematics, these always seemed like a no-brainer to me but I've yet to use a language which implements something like them.

Fixed point decimals as a primitive type instead of having to rely on 3rd party APIs or rolling your own. They solve so many audio and video problems that I don't understand why we keep trudging on with the pitfalls of floating point numbers in languages that are typically used for game development.

There's a reason why you don't see this. This does the same thing:


void fun(int arg)
{
     assert(arg < 100);
}

Automatic clamping makes a bit more sense though in some cases, since it presents some potential compile-time optimizations, whereas I don't think the above does.

On a related theme, I always wanted to see a "pure" keyword, which tells the compiler (and this can be statically enforced rather easily) that a function has no side effects. This is nice from both an optimization and a code correctness point of view.

Optional markup used for function argument validation and range restriction, shown in the IDE's "intellisense" tooltips as well.

"void fun(validate(arg < 100) int arg)" would cause an error if arg is greater-than-or-equal to 100.

"void fun(range(5, 10) int arg)" would automatically clamp "arg" in the 5-10 range before the function body executes.

Given just how much of programming is mathematics, these always seemed like a no-brainer to me but I've yet to use a language which implements something like them.

Fixed point decimals as a primitive type instead of having to rely on 3rd party APIs or rolling your own. They solve so many audio and video problems that I don't understand why we keep trudging on with the pitfalls of floating point numbers in languages that are typically used for game development.

There's a reason why you don't see this. This does the same thing:


void fun(int arg)
{
     assert(arg < 100);
}

Automatic clamping makes a bit more sense though in some cases, since it presents some potential compile-time optimizations, whereas I don't think the above does.

depends on how assert is implemented, but this sort of thing can be optimized for.

the less certain issue though is how many significant optimizations would be possible with this knowledge.

the main case where number ranges comes in relates to optimizing away array bounds checks, but in many other cases the type-systems work in such a way as to limit the usefulness of range-based arithmetic, and to what extent they are useful could be largely served by a few range-check and clamp related intrinsic functions.

assert(range(arg, 0, 50));

//or:

assert(arg.range(0, 50));

likewise:

y=clamp(x, 0.0, 1.0);

or:

y=x.clamp(0.0, 1.0);

On a related theme, I always wanted to see a "pure" keyword, which tells the compiler (and this can be statically enforced rather easily) that a function has no side effects. This is nice from both an optimization and a code correctness point of view.

from an optimization POV, this case can also be detected easily enough with or without a keyword.

however, the benefit that such a keyword would have is more that it allows the compiler to enforce this case (like, say, you intended the function to be pure but missed something).

This topic is closed to new replies.

Advertisement