Jump to page: 1 2
Thread overview
'idiomatic' porting of c and or c++ code that does NULL checking
Aug 23, 2014
nikki
Aug 23, 2014
nikki
Aug 23, 2014
ketmar
Aug 23, 2014
nikki
Aug 23, 2014
monarch_dodra
Aug 23, 2014
bearophile
Aug 23, 2014
ketmar
Aug 23, 2014
Kagamin
Aug 23, 2014
ketmar
Aug 23, 2014
Kagamin
Aug 23, 2014
bearophile
Aug 23, 2014
hane
Aug 25, 2014
Mike Parker
Aug 25, 2014
Vladimir Panteleev
Aug 25, 2014
Mike Parker
Aug 27, 2014
Vladimir Panteleev
Aug 27, 2014
eles
Aug 27, 2014
eles
Aug 27, 2014
Mike Parker
August 23, 2014
I am learning SDL by following the lazyfoo SDL2 tuorials, I am alos new to D so I have a question:

I the lazyfoo tutorials there are many functions that have a bool success whiich gets set at various places when something goes wrong to be returned afterwards.

http://lazyfoo.net/tutorials/SDL/02_getting_an_image_on_the_screen/index.php
for example:
[code]

bool init()
{
    //Initialization flag
    bool success = true;

    //Initialize SDL
    if( SDL_Init( SDL_INIT_VIDEO ) < 0 )
    {
        printf( "SDL could not initialize! SDL_Error: %s\n", SDL_GetError() );
        success = false;
    }
    else
    {
        //Create window
        gWindow = SDL_CreateWindow( "SDL Tutorial", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN );
        if( gWindow == NULL )
        {
            printf( "Window could not be created! SDL_Error: %s\n", SDL_GetError() );
            success = false;
        }
        else
        {
            //Get window surface
            gScreenSurface = SDL_GetWindowSurface( gWindow );
        }
    }

    return success;
}


[/code]


in my D code I just change the NULL into null and the printf to a fitting writeln.
But I am wondering if D offers me much cleaner ways of writing this, I am guessing the scope() but what would be the best/D way of writing this function?

How would you write it?
August 23, 2014
Oops well writing the above post made me realise what to look for : http://dlang.org/errors.html
;)
August 23, 2014
On Sat, 23 Aug 2014 10:19:58 +0000
nikki via Digitalmars-d-learn <digitalmars-d-learn@puremagic.com> wrote:

don't use '==' to check for nulls. the right way is:

  if (foo is null) {}
  if (bar !is null) {}

'==' transforms to opEquals call (see 'operator overloading') and 'is'
not.

as for 'best practice' question -- it depends of many things. ;-)


August 23, 2014
On Saturday, 23 August 2014 at 10:29:04 UTC, ketmar via Digitalmars-d-learn wrote:
> On Sat, 23 Aug 2014 10:19:58 +0000
> nikki via Digitalmars-d-learn <digitalmars-d-learn@puremagic.com> wrote:
>
> don't use '==' to check for nulls. the right way is:
>
>   if (foo is null) {}
>   if (bar !is null) {}
>
> '==' transforms to opEquals call (see 'operator overloading') and 'is'
> not.
>
> as for 'best practice' question -- it depends of many things. ;-)

A good to know! thanks.
I'd still be interrested to see the idiomatic D version of that function, what would that depend on ?
August 23, 2014
nikki:

> How would you write it?

I don't know how much idiomatic this is, but you can start cleaning up the code:
- Renaming the function with something more clear;
- using a D enumeration for the various constants.
- I have used a "." before the module-level variables to denote better they are not local;
- I have used an alias and stderror.
- All the code below is untested.


bool initializeSDL()
out {
    assert(.gWindow != null);
    assert(.gScreenSurface != null);
} body {
    alias success = bool;

    if (SDL_Init(SDL.init_video) < 0) {
        stderr.writeln("SDL could not initialize! SDL_Error: ",
                       SDL_GetError);
        return success(false);
    } else {
        .gWindow = SDL_CreateWindow("SDL Tutorial",
                                    SDL.qindowpos_undefined,
                                    SDL.windowpos_undefined,
                                    screen_width,
                                    screen_height,
                                    SDL.window_shown);

        if (.gWindow == null) {
            stderr.writeln("Window could not be created! SDL_Error: ",
                           SDL_GetError);
            return success(false);
        } else {
            .gScreenSurface = SDL_GetWindowSurface(.gWindow);
        }
    }

    return success(true);
}



In D error messages are often given by throwing errors, so this looks a little more idiomatic:


bool initializeSDL() nothrow
out {
    assert(.gWindow != null);
    assert(.gScreenSurface != null);
} body {
    if (SDL_Init(SDL.init_video) < 0) {
        throw new text("SDL could not initialize: ", SDL_GetError).SDL_Error;
    } else {
        .gWindow = SDL_CreateWindow("SDL Tutorial",
                                    SDL.qindowpos_undefined,
                                    SDL.windowpos_undefined,
                                    screen_width,
                                    screen_height,
                                    SDL.window_shown);

        if (.gWindow == null) {
            throw new text("Window could not be created: ", SDL_GetError).SDL_Error;
        } else {
            gScreenSurface = SDL_GetWindowSurface(gWindow);
        }
    }
}


If you can add some more function attributes, like @safe.

Bye,
bearophile
August 23, 2014
ketmar:

> don't use '==' to check for nulls. the right way is:
>
>   if (foo is null) {}
>   if (bar !is null) {}
>
> '==' transforms to opEquals call (see 'operator overloading') and 'is' not.

I use "is" and "!is" for class references and == != for pointers. But now I think you are right, and in D it's better to always use is and !is for both, to avoid present and future bugs (like when a pointer gets replaced by a class reference by successive changes in the code).

So the code I've written becomes:

bool initializeSDL()
out {
    assert(.gWindow !is null);
    assert(.gScreenSurface !is null);
} body {
    alias success = bool;

    if (SDL_Init(SDL.init_video) < 0) {
        stderr.writeln("SDL could not initialize! SDL_Error: ",
                       SDL_GetError);
        return success(false);
    } else {
        .gWindow = SDL_CreateWindow("SDL Tutorial",
                                    SDL.qindowpos_undefined,
                                    SDL.windowpos_undefined,
                                    .screen_width,
                                    .screen_height,
                                    SDL.window_shown);

        if (.gWindow is null) {
            stderr.writeln("Window could not be created! SDL_Error: ",
                           SDL_GetError);
            return success(false);
        } else {
            .gScreenSurface = SDL_GetWindowSurface(.gWindow);
        }
    }

    return success(true);
}



bool initializeSDL() nothrow
out {
    assert(.gWindow !is null);
    assert(.gScreenSurface !is null);
} body {
    if (SDL_Init(SDL.init_video) < 0) {
        throw new text("SDL could not initialize: ", SDL_GetError).SDL_Error;
    } else {
        .gWindow = SDL_CreateWindow("SDL Tutorial",
                                    SDL.qindowpos_undefined,
                                    SDL.windowpos_undefined,
                                    .screen_width,
                                    .screen_height,
                                    SDL.window_shown);

        if (.gWindow is null) {
            throw new text("Window could not be created: ", SDL_GetError).SDL_Error;
        } else {
            gScreenSurface = SDL_GetWindowSurface(gWindow);
        }
    }
}


Bye,
bearophile
August 23, 2014
On Sat, 23 Aug 2014 10:53:03 +0000
bearophile via Digitalmars-d-learn <digitalmars-d-learn@puremagic.com>
wrote:

> I use "is" and "!is" for class references and == != for pointers. But now I think you are right, and in D it's better to always use is and !is for both, to avoid present and future bugs (like when a pointer gets replaced by a class reference by successive changes in the code).
and "foo is null" is nice to read. ;-)


August 23, 2014
On Saturday, 23 August 2014 at 10:19:59 UTC, nikki wrote:
> I am learning SDL by following the lazyfoo SDL2 tuorials, I am alos new to D so I have a question:
>
> I the lazyfoo tutorials there are many functions that have a bool success whiich gets set at various places when something goes wrong to be returned afterwards.
>
> http://lazyfoo.net/tutorials/SDL/02_getting_an_image_on_the_screen/index.php
> for example:
> [code]
>
> bool init()
> {
>     //Initialization flag
>     bool success = true;
>
>     //Initialize SDL
>     if( SDL_Init( SDL_INIT_VIDEO ) < 0 )
>     {
>         printf( "SDL could not initialize! SDL_Error: %s\n", SDL_GetError() );
>         success = false;
>     }
>     else
>     {
>         //Create window
>         gWindow = SDL_CreateWindow( "SDL Tutorial", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN );
>         if( gWindow == NULL )
>         {
>             printf( "Window could not be created! SDL_Error: %s\n", SDL_GetError() );
>             success = false;
>         }
>         else
>         {
>             //Get window surface
>             gScreenSurface = SDL_GetWindowSurface( gWindow );
>         }
>     }
>
>     return success;
> }
>
>
> [/code]
>
>
> in my D code I just change the NULL into null and the printf to a fitting writeln.
> But I am wondering if D offers me much cleaner ways of writing this, I am guessing the scope() but what would be the best/D way of writing this function?
>
> How would you write it?

How about this?

----
import std.exception; // enforce() is declared in std.exception

void init()
{
	// enforce() throws an exception if condition is false
	enforce(SDL_Init( SDL_INIT_VIDEO ) >= 0, "SDL could not initialize!");

	// enforce() throws if SDL_CreateWindow returns null
	gWindow = SDL_CreateWindow(/* ... */).enforce("Window could not be created!");

	// ditto
	gScreenSurface = SDL_GetWindowSurface(gWindow).enforce("Surface could not be created!");
}
----
August 23, 2014
On Saturday, 23 August 2014 at 10:33:02 UTC, nikki wrote:
> A good to know! thanks.
> I'd still be interrested to see the idiomatic D version of that function, what would that depend on ?

Honestly, I wouldn't change it much. If it didn't throw exceptions before, then it probably would have trouble handling them now.

What I *would* do is use multiple returns though. This style of if/else invariably leads to the dreaded "diagonal line of death" (http://geekandpoke.typepad.com/geekandpoke/2009/12/geek-for-dummies-chapter-2.html)

Once you've done that, any resource you'd have otherwise needed to Un-conditionally release, I'd do with a scope.

bool init()
{
    //Initialize SDL
    if( SDL_Init( SDL_INIT_VIDEO ) < 0 )
    {
        printf( "SDL could not initialize! SDL_Error: %s\n",
SDL_GetError() );
        return false;
    }

    //Create window
    gWindow = SDL_CreateWindow( "SDL Tutorial",
SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH,
SCREEN_HEIGHT, SDL_WINDOW_SHOWN );
    if( gWindow == NULL )
    {
        printf( "Window could not be created! SDL_Error:
%s\n", SDL_GetError() );
        return false;
    }

    //Get window surface
    gScreenSurface = SDL_GetWindowSurface( gWindow );

    return true;
}

Now, once you've adopted this kind of style, migrating to exceptions (should you so wish to do so) should much easier.
August 23, 2014
On Saturday, 23 August 2014 at 11:07:23 UTC, ketmar via Digitalmars-d-learn wrote:
> and "foo is null" is nice to read. ;-)

Meh, looks like a guest from pascal or basic.
« First   ‹ Prev
1 2