September 27, 2014
On Saturday, 27 September 2014 at 09:32:19 UTC, Jacob Carlborg wrote:
> On 2014-09-27 02:47, Manu via Digitalmars-d wrote:
>
>> Initialisation logic often looks like this, and I buy the value of
>> exceptions in this case. However, I've never successfully implemented it yet though, because the calls that create code like that always seem to be extern-C calls in my experience... :/
>
> Perhaps you should wrap those call an throw an exception.

I often do something like this:

proc(someFunc(a, b, c));
proc(anotherFunc(d, e, f));

Where proc() processes the return value and conditionally throws on error.  You really need one such function per API, but that's not a big deal.  You can kind of get away with macros if you're using C, but all they can really do is jump to an expected Lerror label.
September 27, 2014
On Friday, 19 September 2014 at 23:47:06 UTC, Max Klyga wrote:
> Jonathan Blow just recorded a talk about the needs and ideas for a programming language for game developer.
>
> https://www.youtube.com/watch?v=TH9VCN6UkyQ
>
> This talk mentions D quite a lot of times.
> D is mentioned as the most probable to be adopted if it were possible for frictionless interaction with existing codebase.
> An interesting talk if you want to look at language design from game developer perspective.

The sequel:

A Programming Language for Games, talk #2
https://www.youtube.com/watch?v=5Nc68IdNKdg
September 27, 2014
On 9/27/2014 9:35 AM, ponce wrote:
> The sequel:
>
> A Programming Language for Games, talk #2
> https://www.youtube.com/watch?v=5Nc68IdNKdg

Yeah, I watched it. He advocates:

* pure functions

* local functions

* local functions with the same syntax as global functions

* safety which defaults to off

All of which D does right now.

The only interesting thing is he describes a way that functions (and blocks) can specify what global data they access, and then have the compiler issue errors for accessing any other global data. He has a way to do that both locally and transitively.

However, the same effect can be achieved via pure annotations and passing the globals needed by reference as function parameters.

Based on his talks about what he wants in a language, I infer he's not looked at D beyond "D has a GC, can't use it".

--------------------------------------

Another thing I found interesting is I had assumed he'd given these talks at a conference. Not so. He simply set up a webcam in his office. It's a great method - we should look into doing that.
September 27, 2014
On Sat, Sep 27, 2014 at 02:51:14PM -0700, Walter Bright via Digitalmars-d wrote: [...]
> The only interesting thing is he describes a way that functions (and blocks) can specify what global data they access, and then have the compiler issue errors for accessing any other global data. He has a way to do that both locally and transitively.

That sounds like PHP. *shudder*


> However, the same effect can be achieved via pure annotations and passing the globals needed by reference as function parameters.
[...]

I'm a fan of grouping related globals into structs with module level instances, and passed by reference to functions that need those specific globals. Truly-global globals are nasty, as are open sets of globals where you either don't access a global, or you (potentially) access *all* globals with no finer access granularity. (I had to debug C code that did that once... boy it was mind-bending when every function call could potentially arbitrarily change the global state.)


T

-- 
Computers are like a jungle: they have monitor lizards, rams, mice, c-moss, binary trees... and bugs.
September 27, 2014
Walter Bright:

> * local functions with the same syntax as global functions
>
> * safety which defaults to off
>
> All of which D does right now.

It could be nice to have a syntax like lambdas for small struct/class methods:
https://issues.dlang.org/show_bug.cgi?id=7176

struct Foo {
    int bar(int x) pure { return x * x; }
}

Becomes something like::

struct Foo {
    int bar = (int x) pure => x * x;
}

Ada2012 and C#6 have something like that (with a different syntax).


> The only interesting thing is he describes a way that functions (and blocks) can specify what global data they access, and then have the compiler issue errors for accessing any other global data. He has a way to do that both locally and transitively.

Unwanted access of global variables is a common source of troubles in my code. Time ago I suggested an optional @outer() function annotation:
https://d.puremagic.com/issues/show_bug.cgi?id=5007

Bye,
bearophile
September 27, 2014
On 9/27/2014 3:30 PM, bearophile wrote:
> Walter Bright:
>
>> * local functions with the same syntax as global functions
>>
>> * safety which defaults to off
>>
>> All of which D does right now.
>
> It could be nice to have a syntax like lambdas for small struct/class methods:
> https://issues.dlang.org/show_bug.cgi?id=7176
>
> struct Foo {
>      int bar(int x) pure { return x * x; }
> }
>
> Becomes something like::
>
> struct Foo {
>      int bar = (int x) pure => x * x;
> }

I see no gain from that syntax.


> Unwanted access of global variables is a common source of troubles in my code.
> Time ago I suggested an optional @outer() function annotation:
> https://d.puremagic.com/issues/show_bug.cgi?id=5007

I suggest using 'pure' and passing the globals you actually need as ref parameters.

September 27, 2014
Walter Bright:

>> It could be nice to have a syntax like lambdas for small struct/class methods:
>> https://issues.dlang.org/show_bug.cgi?id=7176
>>
>> struct Foo {
>>     int bar(int x) pure { return x * x; }
>> }
>>
>> Becomes something like::
>>
>> struct Foo {
>>     int bar = (int x) pure => x * x;
>> }
>
> I see no gain from that syntax.

Issue 7176 has currently seven votes, so someone seems to like it.

Now some D code is written in a functional style, this means many function bodies are very small, and sometimes they contain just a UFCS chain.
Usually editors (and Phobos style guides) format that bar function like:

int bar(int x) pure
{
    return x * x;
}

So now you have 4 lines instead of 1 line of the lambda-like syntax. Generally the presence of a  "return" is regarded as a "code smell" in functional-style code.


> I suggest using 'pure' and passing the globals you actually need as ref parameters.

This is what I usually do in D, but it has some small disadvantages:
- It increases the number of function arguments (they are 8 bytes each), increasing the size of the function, adding some stack management instructions. This slows the function a little, if the function is performance-critical.
- Sometimes you can't use "pure", for various reasons, like Phobos functions not yet pure, I/O action in your function, or other causes.
- If your pure function foo receives two global argument as out and ref, the function bar that calls it needs to access to global variables or it too needs those two ref/out arguments. The current design of @outer() is not transitive, so only foo needs to state what global variables are in/out/inout.
- @outer is more DRY, because you don't need to specify the type of the global variable received by ref, you just need to know its name.
- With @outer you can tighten some old code, without changing the signature of a function. If you have an old D module (or a C function converted to C) you often can't (or you don't want) to change the function signature to add the global arguments passed by ref. With @outer() the function signature doesn't change, so you can improve your legacy code. It allows a simpler refactoring of code.

More notes:
- SPARK language has added a feature similar to @outer, but more verbose. See comment 5 in issue 5007.
- @outer() is optional and it's fiddly because not it's not meant for small D script-like programs, it's meant as a help for medium-integrity D programs (where you may think about using Ada language instead).

Bye,
bearophile
September 27, 2014
On 9/27/2014 4:20 PM, bearophile wrote:
> Walter Bright:
>
>>> It could be nice to have a syntax like lambdas for small struct/class methods:
>>> https://issues.dlang.org/show_bug.cgi?id=7176
>>>
>>> struct Foo {
>>>     int bar(int x) pure { return x * x; }
>>> }
>>>
>>> Becomes something like::
>>>
>>> struct Foo {
>>>     int bar = (int x) pure => x * x;
>>> }
>>
>> I see no gain from that syntax.
>
> Issue 7176 has currently seven votes, so someone seems to like it.

A feature without a solid rationale is no good in spite of how many votes it has.


> Now some D code is written in a functional style, this means many function
> bodies are very small, and sometimes they contain just a UFCS chain.
> Usually editors (and Phobos style guides) format that bar function like:
>
> int bar(int x) pure
> {
>      return x * x;
> }
>
> So now you have 4 lines instead of 1 line of the lambda-like syntax. Generally
> the presence of a  "return" is regarded as a "code smell" in functional-style code.

D has a nice inline lamda syntax, which was needed. It is not needed for separate functions.


>> I suggest using 'pure' and passing the globals you actually need as ref
>> parameters.
>
> This is what I usually do in D, but it has some small disadvantages:
> - It increases the number of function arguments (they are 8 bytes each),
> increasing the size of the function, adding some stack management instructions.
> This slows the function a little, if the function is performance-critical.

If the function is small enough that parameter setup time is significant, it is likely to be inlined anyway which will erase the penalty.

Such arguments can also be passed as template alias parameters, which are zero cost.

> - Sometimes you can't use "pure", for various reasons, like Phobos functions not
> yet pure, I/O action in your function, or other causes.

Then you really aren't encapsulating the globals the function uses, anyway, and the feature is useless.


> - If your pure function foo receives two global argument as out and ref, the
> function bar that calls it needs to access to global variables or it too needs
> those two ref/out arguments. The current design of @outer() is not transitive,
> so only foo needs to state what global variables are in/out/inout.

Being global variables, they are accessible from everywhere :-) which is why they're an encapsulation problem in the first place.


> - @outer is more DRY, because you don't need to specify the type of the global
> variable received by ref, you just need to know its name.

That's why gawd invented templates.


> - With @outer you can tighten some old code, without changing the signature of a
> function. If you have an old D module (or a C function converted to C) you often
> can't (or you don't want) to change the function signature to add the global
> arguments passed by ref. With @outer() the function signature doesn't change, so
> you can improve your legacy code. It allows a simpler refactoring of code.

You can always wrap it with a template and pass the global by alias.


> More notes:
> - SPARK language has added a feature similar to @outer, but more verbose. See
> comment 5 in issue 5007.
> - @outer() is optional and it's fiddly because not it's not meant for small D
> script-like programs, it's meant as a help for medium-integrity D programs
> (where you may think about using Ada language instead).

Better encapsulation is intended for larger programs - I agree it is useless for small ones.

September 28, 2014
On 09/28/2014 01:55 AM, Walter Bright wrote:
> On 9/27/2014 4:20 PM, bearophile wrote:
>> Walter Bright:
>>
>>>> It could be nice to have a syntax like lambdas for small
>>>> struct/class methods:
>>>> https://issues.dlang.org/show_bug.cgi?id=7176
>>>>
>>>> struct Foo {
>>>>     int bar(int x) pure { return x * x; }
>>>> }
>>>>
>>>> Becomes something like::
>>>>
>>>> struct Foo {
>>>>     int bar(int x) pure => x * x; // fixed
>>>> }
>>>
>>> I see no gain from that syntax.
>>
>> Issue 7176 has currently seven votes, so someone seems to like it.
>
> A feature without a solid rationale  is no good in spite of how many
> votes it has.

Uniform syntax for parameter list followed by function body.

             (int x){ return 2; }
     function(int x){ return 2; }
auto separate(int x){ return 2; }
             (int x) => 2;
     function(int x) => 2;
auto separate(int x) => 2;

auto curriedAdd(int x) => (int y) => x + y;

It is a simplification that is also convenient.
September 28, 2014
On Saturday, 27 September 2014 at 10:01:05 UTC, Ola Fosheim Grøstad wrote:
> On Friday, 26 September 2014 at 21:19:29 UTC, Walter Bright wrote:
>> I would. The whole point of destructors is to automatically clean up resources when the object goes away, which was (later) dubbed RAII.
>
> Yeah, but RAII takes it to the extreme where you create dummy classes that only consist of constructors/destructors so that the stack unwinding does all cleanup/closing/freeing without any try/catch.
>

This is not necessary in D as we have scope statements.

> Before C++ templates that looked verbose and ugly syntactically, and it is still tedious if you only use the specific resource in one location.  "scope(exit)" is often more transparent IMO.

I guess this is matter of style and various tradeoff. A very common operation to rollback probably deserve its own RAII struct. An uncommon one is better served with scope.