• Announcements

    • khawk

      Download the Game Design and Indie Game Marketing Freebook   07/19/17

      GameDev.net and CRC Press have teamed up to bring a free ebook of content curated from top titles published by CRC Press. The freebook, Practices of Game Design & Indie Game Marketing, includes chapters from The Art of Game Design: A Book of Lenses, A Practical Guide to Indie Game Marketing, and An Architectural Approach to Level Design. The GameDev.net FreeBook is relevant to game designers, developers, and those interested in learning more about the challenges in game development. We know game development can be a tough discipline and business, so we picked several chapters from CRC Press titles that we thought would be of interest to you, the GameDev.net audience, in your journey to design, develop, and market your next game. The free ebook is available through CRC Press by clicking here. The Curated Books The Art of Game Design: A Book of Lenses, Second Edition, by Jesse Schell Presents 100+ sets of questions, or different lenses, for viewing a game’s design, encompassing diverse fields such as psychology, architecture, music, film, software engineering, theme park design, mathematics, anthropology, and more. Written by one of the world's top game designers, this book describes the deepest and most fundamental principles of game design, demonstrating how tactics used in board, card, and athletic games also work in video games. It provides practical instruction on creating world-class games that will be played again and again. View it here. A Practical Guide to Indie Game Marketing, by Joel Dreskin Marketing is an essential but too frequently overlooked or minimized component of the release plan for indie games. A Practical Guide to Indie Game Marketing provides you with the tools needed to build visibility and sell your indie games. With special focus on those developers with small budgets and limited staff and resources, this book is packed with tangible recommendations and techniques that you can put to use immediately. As a seasoned professional of the indie game arena, author Joel Dreskin gives you insight into practical, real-world experiences of marketing numerous successful games and also provides stories of the failures. View it here. An Architectural Approach to Level Design This is one of the first books to integrate architectural and spatial design theory with the field of level design. The book presents architectural techniques and theories for level designers to use in their own work. It connects architecture and level design in different ways that address the practical elements of how designers construct space and the experiential elements of how and why humans interact with this space. Throughout the text, readers learn skills for spatial layout, evoking emotion through gamespaces, and creating better levels through architectural theory. View it here. Learn more and download the ebook by clicking here. Did you know? GameDev.net and CRC Press also recently teamed up to bring GDNet+ Members up to a 20% discount on all CRC Press books. Learn more about this and other benefits here.

D Bits

  • entries
  • comments
  • views

D Tip: Use Scope Statements in Proper Scope

Sign in to follow this  
Followers 0


One D construct I often use is the scope guard statement. This allows you to write code that executes when a scope exits under one of three circumstances: an exception is thrown, no exception is thrown, or always. Example:[code=nocode:0]void main() { import std.stdio; scope( failure ) { writeln( "I only execute when the scope exits due to an exception being thrown."); } scope( success ) { writeln( "I only execute when the scope exits normally." ); } scope( exit ) { writeln( "I always execute when the scope exits, exceptions or no." ); }}
In this example, as written, two lines will be printed to the console when the function exits, the ones for the exit and success conditions, since no exception is thrown. The exit condition will be written first, since anything scope statements are executed in the reverse order they are declared. If you add a return statement before the success condition or throw an exception before the failure condition, nothing will be printed -- the scope blocks won't be executed because the code never reached the point where they are declared. Also, you can have more than one statement in each scope block. Here's another example.[code=nocode:0]void main() { import std.stdio; scope( exit ) { writeln( "I'm always going to execute."); writeln( "Because I'm the first scope guard in this scope." ); writeln( "And the scope doesn't exit before I am declared."); writeln( "But I will be the last scope guard to run." ); } int x = 5; int y = 6; scope( success ) writefln( "I won't execute because of the Error thrown below. BTW, x+y = %s", x + y ); scope( exit ) { writeln( "Yes, multiple scope guards of the same type can be declared." ); writeln( "And this scope( exit ) will execute before the one above." ); } if( y - x != 0 ) { throw new Error( "No scopes declared after me will execute." ); } scope( failure ) writeln( "I won't run, since an exception was thrown before this point." ); }
You can run this code online, where you will see this ouput:[quote]
Yes, multiple scope guards of the same type can be declared.
And this scope( exit ) will execute before the one above.
I'm always going to execute.
Because I'm the first scope guard in this scope.
And the scope doesn't exit before I am declared.
But I will be the last scope guard to run.
object.Error: No scopes declared after me will execute.[/quote]

D also has the try...catch...finally construct, which is what scope guard statements are lowered to by the compiler. While this is extremely useful and eliminates the need for try..catch..finally in many cases, it is not a complete replacement. For one thing, if there is an exception thrown, scope( failure ) does not give you access to the exception object. In practice, I've found that I use the exit condition the most, with success a distant second. I find that I rarely need the failure condition, but it's handy when I do.

This feature may not seem like much on the surface, but as soon as you start to use it you'll fall in love with it. I actually feel disappointed when I find I need to replace a scope guard with a manual try...catch block, as it clutters things up. But what you can't do is add them blindly to your code. The above examples only use the scope guards at function level, but you can put them in any scope. Conditional blocks, loops, anonymous scopes, wherever you want. The statements in the scope guard will execute if they meet the conditions when the scope in which they are declared exits. Like this:void main() { import std.stdio; if( 1 > 0 ) { scope( exit ) writeln( "I'll execute as soon as the if exits."); } for( size_t i=0; i<3; ++i ) { scope( exit ) writeln( "How many times will I execute?" ); } scope( exit ) writeln( "Will the above scopes be run before I am? Yes, they will." ); }
I'll execute as soon as the if exits.
How many times will I execute?
How many times will I execute?
How many times will I execute?
Will the above scopes be run before I am? Yes, they will.[/quote]

The scope guards in the if block and the for loop are declared before the last scope, but in this case all three are in separate scopes, so they aren't executed in reverse order. The first one is executed as soon as the if block exits and the second one is executed each time the for loop scope exits (three times in all). Those scopes exit before the final scope guard is every declared, so it executes last, only when the main function exits.

That brings me to the point of this post. You should always be aware of the scope in which your scope guard is declared, what is visible in that scope, and what happens in any scopes that follow it. I had never had any issues with scope guards until today. Can you spot the error?Config loadConfig( string fileName ) { auto path = Paths.findSettingsFilePath( fileName ); scope( exit ) path.destroy(); if( path !is null ) { auto config = al_load_config_file( path.toCString() ); return new Config( config, fileName ); } else { return createConfig( fileName ); }}
I'm so used to putting a scope guard right after allocation of a resource that, in this case, I didn't pay attention to how that particular resource is used in the function. In this particular case, it is possible for the path instance to be null. Because I declared the scope guard at function scope, it will always execute, regardless of whether the path instance is null or not. If the path object is null, the result is an access violation.

One way to fix this is to add a null check inside the scope guard:scope( exit ) if( path !is null ) path.destroy();
But that's rather silly, since there's already an if block that checks for null. Furthermore, since the existing if block also creates a new scope, and only in the case where the path object is non-null, then the better solution is to move the scope guard to the if block like so:auto path = Paths.findSettingsFilePath( fileName );if( path !is null ) { scope( exit ) path.destroy(); ...}
D's scope guards are quite useful, but always be aware of how you're using them. Like anything else in programming, if you aren't paying attention, you can create bugs for yourself that may not manifest at all during development and could be hard to track down if they show up on a user machine. As I used to hear all the time in the Army, "More attention to detail, soldier!"

Sign in to follow this  
Followers 0


Nice article.

I have watched a few videos about d and the language looks very interesting, I might have to give it a try.


Share this comment

Link to comment

It's a pleasure to work with. It's the only programming language I've ever really *enjoyed* using. 


Share this comment

Link to comment

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now