Thread overview
How to declare immutable struct outside of try catch and reference it later
Dec 03, 2017
Fra Mecca
Dec 03, 2017
Jonathan M Davis
Dec 03, 2017
kdevel
Dec 03, 2017
kdevel
Dec 03, 2017
Basile B.
Dec 03, 2017
kdevel
Dec 03, 2017
Basile B.
Dec 04, 2017
kdevel
December 03, 2017
I have this code:
    Configuration conf = void ;
    try {
        conf = parse_config("config.sdl");
    } catch (Exception e) {
        std.stdio.stderr.writeln("Error reading configuration file: ", e.msg);
        exit(1);
    }

// other code
function(value, conf);
// end

I get:
source/app.d(18,3): Error: cannot modify struct conf Configuration with immutable members

Is there a way to declare conf outside of the try catch block and use it later?
I thought void explicitly avoid inizialization.
December 03, 2017
On Sunday, December 03, 2017 05:49:54 Fra Mecca via Digitalmars-d-learn wrote:
> I have this code:
>      Configuration conf = void ;
>      try {
>          conf = parse_config("config.sdl");
>      } catch (Exception e) {
>          std.stdio.stderr.writeln("Error reading configuration
> file: ", e.msg);
>          exit(1);
>      }
>
> // other code
> function(value, conf);
> // end
>
> I get:
> source/app.d(18,3): Error: cannot modify struct conf
> Configuration with immutable members
>
> Is there a way to declare conf outside of the try catch block and
> use it later?
> I thought void explicitly avoid inizialization.

It's not possible to delay initialization with const or immutable variables unless they're member variables (which then have to be initialized in a constructor before they're used), but you can wrap the try-catch block in a function or lambda that returns the struct so that the code is separated out in a way that the variable is then directly initialized.

- Jonathan M Davis

December 03, 2017
On Sunday, 3 December 2017 at 05:49:54 UTC, Fra Mecca wrote:
> I have this code:
>     Configuration conf = void ;
>     try {
>         conf = parse_config("config.sdl");
>     } catch (Exception e) {
>         std.stdio.stderr.writeln("Error reading configuration file: ", e.msg);
>         exit(1);
>     }

Since most programs have more than place where execution must be terminated, you end up dupliating that try-catch-code all over the program making it unreadable. When you try to avoid calling exit this problem will not arise. You can simply write

```
   auto conf = parse_config("config.sdl");
```

The exception unwinds the stack and terminates the program. If a stacktrace on the command line does not suffice I would wrap the main-code in a try-catch block. Your function parse_config should support this coding style by putting a whole sentence into the Exception instead of the mere filename, then the try-catch wrapper in main may look like this:

```
int main ()
{
   try {
      real_main ();
   }
   catch (Exception e) {
      std.stdio.stderr.writeln(e.msg);
      return 1;
   }
   return 0;
}
```

December 03, 2017
On Sunday, 3 December 2017 at 14:16:42 UTC, kdevel wrote:
> int main ()
> {
>    try {
>       real_main ();
>    }
>    catch (Exception e) {
>       std.stdio.stderr.writeln(e.msg);
>       return 1;
>    }
>    return 0;
> }
> ```

This is better:

int main ()
{
   try {
      return real_main ();
   }
   catch (Exception e) {
      std.stdio.stderr.writeln(e.msg);
      return 1;
   }
}
December 03, 2017
On Sunday, 3 December 2017 at 05:49:54 UTC, Fra Mecca wrote:
> I have this code:
>     Configuration conf = void ;
>     try {
>         conf = parse_config("config.sdl");
>     } catch (Exception e) {
>         std.stdio.stderr.writeln("Error reading configuration file: ", e.msg);
>         exit(1);
>     }
>
> // other code
> function(value, conf);
> // end
>
> I get:
> source/app.d(18,3): Error: cannot modify struct conf Configuration with immutable members
>
> Is there a way to declare conf outside of the try catch block and use it later?
> I thought void explicitly avoid inizialization.

In this case i'd go for a typed pointer, e.g

---
immutable struct Configuration
{
    this(string){/*load some file...*/}
    int value;
}

Configuration* config;

void main()
{
    try config = new Configuration("config.sdl");
    catch(Exception){}
    // config.value = 42; // ok, read only
}
---
December 03, 2017
On Sunday, 3 December 2017 at 14:58:03 UTC, Basile B. wrote:
> In this case i'd go for a typed pointer, e.g
>
> ---
> immutable struct Configuration
> {
>     this(string){/*load some file...*/}
>     int value;
> }
>
> Configuration* config;
>
> void main()
> {
>     try config = new Configuration("config.sdl");
>     catch(Exception){}
>     // config.value = 42; // ok, read only
> }
> ---

When config is null, e.g. in case "load some file..." threw, you get a segfault. No error handling at all!
December 03, 2017
On Sunday, 3 December 2017 at 22:33:40 UTC, kdevel wrote:
> On Sunday, 3 December 2017 at 14:58:03 UTC, Basile B. wrote:
>> In this case i'd go for a typed pointer, e.g
>>
>> ---
>> immutable struct Configuration
>> {
>>     this(string){/*load some file...*/}
>>     int value;
>> }
>>
>> Configuration* config;
>>
>> void main()
>> {
>>     try config = new Configuration("config.sdl");
>>     catch(Exception){}
>>     // config.value = 42; // ok, read only
>> }
>> ---
>
> When config is null, e.g. in case "load some file..." threw, you get a segfault. No error handling at all!

I don't follow you...the file thing happens in the __ctor. Exceptions are well handled. Maybe you've missed the try (w/o braces) ?

---
immutable struct Configuration {
    this(string){/*parse_config...*/}
}

Configuration* config;

int main() {
    try {
        config = new Configuration("config.sdl");
        // instead of "conf = parse_config("config.sdl");"
    } catch(Exception e){
        std.stdio.stderr.writeln("Error reading configuration file: ", e.msg);
        return 1;
    }
}
---


December 04, 2017
On Sunday, 3 December 2017 at 23:29:01 UTC, Basile B. wrote:
> On Sunday, 3 December 2017 at 22:33:40 UTC, kdevel wrote:
>> On Sunday, 3 December 2017 at 14:58:03 UTC, Basile B. wrote:
>>> In this case i'd go for a typed pointer, e.g
>>>
>>> ---
>>> immutable struct Configuration
>>> {
>>>     this(string){/*load some file...*/}
>>>     int value;
>>> }
>>>
>>> Configuration* config;
>>>
>>> void main()
>>> {
>>>     try config = new Configuration("config.sdl");
>>>     catch(Exception){}
>>>     // config.value = 42; // ok, read only
>>> }
>>> ---
>>
>> When config is null, e.g. in case "load some file..." threw, you get a segfault. No error handling at all!
>
> I don't follow you...the file thing happens in the __ctor. Exceptions are well handled.

But not in the code you provided first. You used to ignore the exception:

   catch(Exception){}

> Maybe you've missed the try (w/o braces) ?

Not really.

> ---
> immutable struct Configuration {
>     this(string){/*parse_config...*/}
> }
>
> Configuration* config;
>
> int main() {
>     try {
>         config = new Configuration("config.sdl");
>         // instead of "conf = parse_config("config.sdl");"
>     } catch(Exception e){
>         std.stdio.stderr.writeln("Error reading configuration file: ", e.msg);
>         return 1;
>     }
> }
> ---

Are my eyes too weak or is my compiler too old? For this piece of code

test.d
```
immutable struct C {
   this (string filename)
   {
   }
}

void main ()
{
   auto config = new C ("config.sdl");
}
```

it says: test.d(9): Error: immutable method test.C.this is not callable using a mutable object

→ https://issues.dlang.org/show_bug.cgi?id=13628http://forum.dlang.org/thread/mailman.926.1413747186.9932.digitalmars-d-bugs@puremagic.com