digitalmars.D - strict
- bearophile (53/53) Feb 14 2010 Pure functions are nice because a smart compiler can sometimes perform s...
- BCS (22/32) Feb 14 2010 I Like the idea but I think that is a bit /to/ explicit. It makes me thi...
- bearophile (7/9) Feb 15 2010 A better syntax can be invented, do you like this one?
- bearophile (5/9) Feb 15 2010 As I have designed it now it's something optional, you don't have to use...
Pure functions are nice because a smart compiler can sometimes perform some optimizations with them that aren't possible with normal functions. But for me their main advantage is that they help avoid some bugs, because they can't modify global state nor change their behaviour on its base (we can ignore memory overflow, and maybe even exceptions). My Python/Delphi programs that are mostly composed of nearly-pure functions are often the ones with the lower bug count. I have seen that's true in OOP too: methods that are static (and don't use static attributes, they are pure methods, essentially) are often the less buggy ones. So I use static methods where I can, every time I can write a method that uses just the input arguments. But programming in D with just pure functions is not always handy, and in OOP I sometimes must alter instance attributes, so they can't be pure. And sometimes using a variable that's not an argument of the function produces a little faster code/function. So in D I can think of something intermediate between a pure function and a normal function/method, something that keeps code flexible but with a lower bug count. For this I can think about an attribute strict that can be used on a free function, a nested function, an object method, and even a class (it means all it methods are strict). Even strict modules are possible (it means all callables inside it are strict). (If I will ever design a new imperative language this will be the default behaviour. Using outer names randomly as in "nonlocal" statements). strict denotes a normal function/method, where all the names (variable) it uses inside are written down in an explicit way. Some of such names are normal function arguments, the other names can be global variables, variables from an outer function, instance attributes, static class attributes, enums. // inside here types are optional strict(in int y, in z, out k, inout w) int foo(int x) { // ... code } This function/method "foo" takes int "x" as argument. Foo can't use outer/instance/static names beside "y","z","w","k" ("y" and "z" can't be written inside foo, "k" can't be read inside foo, and "w" is read/write by foo). Some alternative syntaxes, a better syntax can be invented: strict_in(int y, z) strict_out(k) strict_inout(w) int foo(int x) { // ... code } strict int foo(int x) { in int y; in z; // types are optional out k; inout w; // ... code } strict [in int y, in z, out k, inout w] int foo(int x) { // ... code } in int y; in z; out k; inout w; strict int foo(int x) { // ... code } strict int foo(int x) { strict_in int y; strictl_in z; strict_out k; strict_inout w; // ... code } strict int foo(int x) { nonlocal_in int y nonlocal_in z nonlocal_out k nonlocal_inout w // ... code } Why it's useful: system theory says that improving the separation of subsystems you reduce unwanted side effects, improving the reliability of the whole system. That's why D modules too must produce a better isolation: as in Python "import bar;" has to import only the "bar" name in the namespace, so for example there are no new global variables and no surprises. This is a small change to the D module system that will improve D code. A simple syntax like "import foo: *;" can be used for the current (to be discouraged) behaviour. Bye, bearophile
Feb 14 2010
Hello bearophile,strict denotes a normal function/method, where all the names (variable) it uses inside are written down in an explicit way. Some of such names are normal function arguments, the other names can be global variables, variables from an outer function, instance attributes, static class attributes, enums. // inside here types are optional strict(in int y, in z, out k, inout w) int foo(int x) { // ... code }I Like the idea but I think that is a bit /to/ explicit. It makes me think of the declared exceptions thing in Java. I don't remember exactly what the problem is there (I've done next to no Java) but being overly explicit seems to me to be an invitation for problems. Might the following get most of the advantages? strict acts like pure but allows the function to modify it's arguments. that plus some relaxed rules about what can be used for default parameters would get >90% of what I see you asking for: int a; void Outer() { int b; strict int Inner(int i, ref j = b, out k = a) { k = j; return i + j; } int m = Inner(); } -- <IXOYE><
Feb 14 2010
retard:This kind of code is just unreadable. It's so bad it might be a joke as well..A better syntax can be invented, do you like this one? outer(in int y, in z, out k, inout w) int foo(int x) { // ... code } Bye, bearophile
Feb 15 2010
BCS:I Like the idea but I think that is a bit /to/ explicit. It makes me think of the declared exceptions thing in Java. I don't remember exactly what the problem is there (I've done next to no Java) but being overly explicit seems to me to be an invitation for problems.As I have designed it now it's something optional, you don't have to use outer() if you don't want to use it. And even if you use it, you can use it in just one function in isolation (if you apply outer to a class/module all its methods/callables will need the annotations). So I think it's very different from Java checked exceptions, that are a little viral. Another nice thing of this idea is that you don't need to modify or remove things from D2 to implement it, it seems a purely additive change. Bye, bearophile
Feb 15 2010