On Tuesday, 27 October 2015 at 07:55:46 UTC, Kagamin wrote:
On Monday, 26 October 2015 at 16:42:27 UTC, TheFlyingFiddle wrote:
If you instead use pattern matching as in your example you have much better context information that can actually help you do something in the case a value is not there.

Probably possible:

Some!T get(T)(Option!T item) {
    Some!T r;
    //Static guarantee of handling value not present
    item match {
        None() => {
            throw new Exception("empty!");
        }
        Some(t) => {
            r=t;
        }
    }

    return r;
}

Then:
Option!File file;
Some!File s = file.get();

Sure that would work but i don't see that it's different then an enfore since you don't have access the context where get is invoked so you can't really do anything with it.

Contrived Example:

void foo()
{
   Option!File worldFile = getAFile("world.json");
   auto world  = parseJSON(worldFile.get());
   Option!File mapFile = getAFile(world["map"]);
   auto map    = parseJSON(mapFile.get());
   //Other stuff.
}

Let's say we get an NoObjectException, this tells us that either the world.json file did not exist or the map file does not exist. get does not have access to that context so we wouldn't be able to tell. This next example would fix this.

void foo()
{
   Option!File worldFile = getAFile("world.json");
enforce(worldFile.hasValue, "Error while loading file: world.json");
   auto world = parseJSON(worldFile.get());
   Option!File mapFile = getAFile(world["map"]);
enforce(mapFile.hasValue, "Error while loading file: " ~ world["map"]);
   auto map = parseJSON(mapFile.get());
   //Other stuff
}

Now we know which file failed to load. But we bypassed the NoObjectException to do it.

I would prefer this style instead.
void foo()
{
  Option!File worldFile = getAFile("world.json");
  match worldFile {
     Some(value) => {
         auto world          = parseJSON(value);
         Option!File mapFile = getAFile(world["map"]);
         match mapFile {
            Some(mapf) => {
               auto map = parseJSON(mapf);
               //Do something here.
            },
None => enforce(false, "Failed to load: " ~ world["map"]);
         }
     },
     None => enforce(false, "Failed to load: world.json");
   }
}

The reason that I prefer that is not that I like the syntax really. It's just that if the only way to get a value is to pattern match on it then you are forced to consider the case where the value was not there.


Guess a D version without language support would look something like:
void foo()
{
  auto worldFile = getAFile("world.json");
  worldFile.match!(
     (File worldf) {
        auto world = parseJSON(value);
        auto mapFile = getAFile(world["map"]);
        mapFile.match!(
           (File mapf)
           {
              auto map = parseJSON(mapf);
              //Do stuff;
           },
(None) => enforce(false, "Failed to load: " ~ world["map"]);
     },
     (None) => enforce(false, "Failed to load: world.json")
  );
}

The example here is very contrived. Here we just throw exceptions if the file could not load and if that is all we do we should just wrap getAFile instead but i hope you get my point.




Reply via email to