# Immutable declaration

**URL:** https://fortran-lang.discourse.group/t/immutable-declaration/2923
**Category:** Language enhancement
**Created:** [March 9, 2022, 2:53pm UTC](https://fortran-lang.discourse.group/t/immutable-declaration/2923 "2022-03-09T14:53:19Z")
**Posts on this page:** 19
**Page:** 1

<div class="post-metadata">

### Author: ![NormanKirkby](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/normankirkby/32/1091_2.png) [@NormanKirkby](https://fortran-lang.discourse.group/u/NormanKirkby)
#### Post date: [March 9, 2022, 2:53pm UTC](https://fortran-lang.discourse.group/t/immutable-declaration/2923/1 "2022-03-09T14:53:19Z")

</div>

I wonder if it would be useful to have a declaration of “immutable” by which I mean a variable of intrinsic or derived type that can be declared immutable so that once it is first given a value during execution it then behaves as a parameter?

OK, I am not sure “immutable” is quite the right term, and it is longer than I would prefer.

The idea would be that once such a variable had acquired a value once, it could not then be changed without causing a run-time error to be raised.

I find parameters useful but I have plenty of cases where it is inconvenient to have to recompile the program just because I want to change their value from run to run. And my users do not have that option at all.

So once an immutable variable had received its value from a read, from the command line or from an environment variable (to mention just three options) its value was fixed for the remainder of that run.

Of course, it is possible that I have failed to spot a way to emulate this behaviour, but, for instance, ‘protected’ does not quite hit this spot and I am sure this discourse will help me if such functionality is already available.

---

<div class="post-metadata">

### Author: ![Beliavsky](https://avatars.discourse-cdn.com/v4/letter/b/ba8739/32.png) [@Beliavsky](https://fortran-lang.discourse.group/u/Beliavsky)
#### Post date: [March 9, 2022, 3:16pm UTC](https://fortran-lang.discourse.group/t/immutable-declaration/2923/2 "2022-03-09T15:16:40Z")

</div>

You can use ASSOCIATE to create an immutable variable within a block:

```auto
program main
implicit none
integer :: i
i = 5
associate (j => i**2)
print*,"j=",j
! j = 10 ! invalid
end associate
associate (j => i**3)
print*,"j=",j
end associate
end program main

```

If the invalid line is reinstated, gfortran says

```auto
immutable.f90:7:0:

    7 | j = 10 ! invalid
      | 
Error: 'j' at (1) associated to expression cannot be used in a variable definition context (assignment)

```

[It has been proposed](https://github.com/j3-fortran/fortran_proposals/issues/221) to use **let** as shorthand for this use of associate.

---

<div class="post-metadata">

### Author: ![NormanKirkby](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/normankirkby/32/1091_2.png) [@NormanKirkby](https://fortran-lang.discourse.group/u/NormanKirkby)
#### Post date: [March 9, 2022, 3:32pm UTC](https://fortran-lang.discourse.group/t/immutable-declaration/2923/3 "2022-03-09T15:32:44Z")

</div>

That is a work around and I was not aware that the associate construct could be used that way to associate a variable with an expression as in your example, I have only ever used associate a bit like a preprocessor to contract a long derived type to something locally more readable.

Thanks and useful.

---

<div class="post-metadata">

### Author: ![NormanKirkby](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/normankirkby/32/1091_2.png) [@NormanKirkby](https://fortran-lang.discourse.group/u/NormanKirkby)
#### Post date: [March 9, 2022, 3:34pm UTC](https://fortran-lang.discourse.group/t/immutable-declaration/2923/4 "2022-03-09T15:34:44Z")

</div>

And subject for a tweet? Or have I missed that tweet?

---

<div class="post-metadata">

### Author: ![Beliavsky](https://avatars.discourse-cdn.com/v4/letter/b/ba8739/32.png) [@Beliavsky](https://fortran-lang.discourse.group/u/Beliavsky)
#### Post date: [March 9, 2022, 4:06pm UTC](https://fortran-lang.discourse.group/t/immutable-declaration/2923/5 "2022-03-09T16:06:59Z")

</div>

Tips are listed by topic [here](https://github.com/Beliavsky/FortranTip/blob/main/topics.md). I mentioned this use of ASSOCIATE on Dec 19.

---

<div class="post-metadata">

### Author: ![Arjen](https://avatars.discourse-cdn.com/v4/letter/a/b9bd4f/32.png) [@Arjen](https://fortran-lang.discourse.group/u/Arjen)
#### Post date: [March 9, 2022, 4:22pm UTC](https://fortran-lang.discourse.group/t/immutable-declaration/2923/6 "2022-03-09T16:22:29Z")

</div>

What also works, is:

```auto
x = 1.0
associate ( xx => (x) ) 
    xx = 3.0
end associate

```

Via the parentheses you create an expression with the value of the variable. And you cannot change the value of an expression.

---

<div class="post-metadata">

### Author: ![NormanKirkby](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/normankirkby/32/1091_2.png) [@NormanKirkby](https://fortran-lang.discourse.group/u/NormanKirkby)
#### Post date: [March 9, 2022, 6:54pm UTC](https://fortran-lang.discourse.group/t/immutable-declaration/2923/8 "2022-03-09T18:54:25Z")

</div>

In reply to @kargl : thanks, but this is one of the cases I really wanted to avoid because the protected variable can be changed any number of times in the module in which is is declared, but, as my marbles deteriorate, more and more protections become necessary.  
The associate to expression, constant or otherwise, is a solution, but does not make things quite so explicit, and I will use this.  
Thanks to all, I learnt something today.

---

<div class="post-metadata">

### Author: ![gattica](https://avatars.discourse-cdn.com/v4/letter/g/db5fbb/32.png) [@gattica](https://fortran-lang.discourse.group/u/gattica)
#### Post date: [March 9, 2022, 8:50pm UTC](https://fortran-lang.discourse.group/t/immutable-declaration/2923/10 "2022-03-09T20:50:37Z")

</div>

.All the features you asked for are possible using the method suggested by @kargl. One possible expansion would be

```fortran
module M_immutable
implicit none
private
public guarded, init, single_set
type init
    integer :: i1=10
    integer :: i2=20
    real :: r1=30.0
    real :: r2=40.0
end type init
type(init),save,protected :: guarded
contains
subroutine single_set(pin)
type(init),intent(in) :: pin
logical, save :: firsttime=.true. ! can only call once
! guarded=init(1,2,3.0,4.0) ! could read from command line or config file (NAMELIST?) ...
if(firsttime)then
   guarded=pin
firsttime=.false.
else
   write(*,*)'nevermore'
   stop
endif
end subroutine single_set
end module M_immutable
program testit
use M_immutable, only : guarded, init, single_set
write(*,*)guarded%i1, guarded%i2, guarded%r1,guarded%3 ! they have defaults
call single_set(init(1,2,3.0,4.0)) ! you can set them only once
!guarded%1=10 ! this would be caught at compile time
write(*,*)guarded
call single_set(init(11,22,33.0,44.0)) ! setting it twice stops program at runtime
end program testit

```

sans typos (no compiler handy) this catches changing them at compile time (better than asked for) lets them only be set once at run time, sets initial values but lets them be changed by setting them (which could be by command line parameters or config files or any other method).

In this version, just add a value to the type and init it to add a new guarded value, and it it a matter of taste, but the guarded%NAME syntax makes it clear it is one of your guarded values,and makes name collisions unlikely.

you can use parameter names on the init to make it clearer what is being set and depending on taste could make FIRSTIME global in the module and have different init methods like “read from NAMELIST file” or “read from command line” as well as the “pass in values method” and they could see if any of the others had been called and only allow one initialization; but I am not sure if that is what you meant, or make the input PIN be optional and use another method if not set, … and so on.

My problem with ASSOCIATE is having to potentially put it in a lot of routines, and that it also requires an associated (:\>) END ASSOCIATE. If there are not a lot of routines using these values (that I assume are in some respect global, as you mention reading them from a config file or the command line)) that might not be an issue; ASSOCIATE could work nicely if all read in early in the main routine and then passed only as parameters to the rest of the procedures.

---

<div class="post-metadata">

### Author: ![urbanjost](https://avatars.discourse-cdn.com/v4/letter/u/0ea827/32.png) [@urbanjost](https://fortran-lang.discourse.group/u/urbanjost)
#### Post date: [March 10, 2022, 2:21am UTC](https://fortran-lang.discourse.group/t/immutable-declaration/2923/11 "2022-03-10T02:21:49Z")

</div>

So the module can set defaults and does not need recompiled for the calling program(s) to change the values. The user can subsequently change the values  
by name on the command line. Values can be changed only via a call to SINGLE\_SET(), which can be called only once. Trying to set the values anywhere in the user program is caught as an error at compile time.

```bash
 ./a.out times=100 width=200
           1 2 3.00000000 4.00000000    
         100 2 200.000000 20.0000000  

```

perhaps not as nice as a new variable properly like “IMMUTABLE”, but not too bad in less than one page of code.

```fortran
module m_immutable
implicit none
private
public guarded , init , single_set
type :: init
   integer :: times = 1, flag = 2
   real :: width = 3.0, height = 4.0
end type init
type (init) , save , protected :: guarded
contains

subroutine single_set(pin)
implicit none
type (init) , intent(in) :: pin
logical , save :: firsttime = .true. ! flag so can only call once
namelist /args/ guarded
character(len=256) :: input(3)=[character(len=256) :: '&args','','/']
character(len=256) :: message
integer :: i, ios
   if ( firsttime ) then
      guarded=pin ! apply values from call
      ! read arguments from command line
      do i=1,command_argument_count()
         call get_command_argument(i,input(2))
         input(2)='guarded%'//adjustl(input(2))
         read(input,nml=args,iostat=ios,iomsg=message)
         if(ios.ne.0)then
            write(*,*)'ERROR:'//trim(message)
            stop 2
         endif
      enddo
      firsttime = .false.
   else
      write (*,*) 'nevermore'
      stop
   endif
end subroutine single_set
end module m_immutable

program testit
use m_immutable , only: g=>guarded , init , single_set
implicit none
   write (*,*) g%times , g%flag , g%width, g%height
   call single_set(init(width=10.0,height=20.0))
   write (*,*) g
end program testit

```

And for fun, add reading a config file called “.config” from the current directory in  
NAMELIST format, like:

```nohighlight
&args
guarded%width=1000.0
guarded%height=2000.0
/

```

> **add reading a config file**
>
> ```fortran
> module m_immutable
> implicit none
> private
> public guarded , init , single_set
> type :: init
> integer :: times = 1, flag = 2
> real :: width = 3.0, height = 4.0
> end type init
> type (init) , save , protected :: guarded
> contains
> 
> subroutine single_set(pin)
> implicit none
> type (init) , intent(in) :: pin
> logical , save :: firsttime = .true. ! flag so can only call once
> namelist /args/ guarded
> character(len=256) :: input(3)=[character(len=256) :: '&args','','/']
> character(len=256) :: message
> integer :: i, ios, lun
> logical :: exist
> if ( firsttime ) then
> guarded=pin ! apply values from call
> inquire(file='.config',exist=exist)
> if(exist)then
> open(file='.config',newunit=lun,iostat=ios,iomsg=message)
> call checkios()
> read(lun,nml=args,iostat=ios,iomsg=message)
> call checkios()
> endif
> ! read arguments from command line
> do i=1,command_argument_count()
> call get_command_argument(i,input(2))
> input(2)='guarded%'//adjustl(input(2))
> read(input,nml=args,iostat=ios,iomsg=message)
> call checkios()
> enddo
> firsttime = .false.
> else
> write (*,*) 'nevermore'
> stop
> endif
> contains
> subroutine checkios()
> if(ios.ne.0)then
> write(*,*)'ERROR:',trim(message)
> stop
> endif
> end subroutine checkios
> end subroutine single_set
> end module m_immutable
> 
> program testit
> use m_immutable , only: g=>guarded , init , single_set
> implicit none
> write (*,*) g%times , g%flag , g%width, g%height
> call single_set(init(width=10.0,height=20.0))
> write (*,*) g
> end program testit
> 
> ```

---

<div class="post-metadata">

### Author: ![Arjen](https://avatars.discourse-cdn.com/v4/letter/a/b9bd4f/32.png) [@Arjen](https://fortran-lang.discourse.group/u/Arjen)
#### Post date: [March 10, 2022, 7:47am UTC](https://fortran-lang.discourse.group/t/immutable-declaration/2923/12 "2022-03-10T07:47:23Z")

</div>

As remarked by @Beliavsky, the code is invalid: it is trying to change the value of an expression. If you compile it (add declarations and such as necessary/desirable), the compiler will complain about that, showing that you cannot change the value of xx. This shows it is not necessary to come up with an arithmetic expression like x+0.0 to force this behaviour.

Then again, the protected attribute is well worth considering - see the rest of the thread.

---

<div class="post-metadata">

### Author: ![NormanKirkby](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/normankirkby/32/1091_2.png) [@NormanKirkby](https://fortran-lang.discourse.group/u/NormanKirkby)
#### Post date: [March 10, 2022, 9:14am UTC](https://fortran-lang.discourse.group/t/immutable-declaration/2923/13 "2022-03-10T09:14:52Z")

</div>

@urbanjost I like the single\_set solution. @Arjen thank you, useful comments.

---

<div class="post-metadata">

### Author: ![wclodius](https://avatars.discourse-cdn.com/v4/letter/w/87869e/32.png) [@wclodius](https://fortran-lang.discourse.group/u/wclodius)
#### Post date: [March 12, 2022, 1:33pm UTC](https://fortran-lang.discourse.group/t/immutable-declaration/2923/14 "2022-03-12T13:33:40Z")

</div>

FWIW the Eiffel language has the ONCE attribute for variables like that.

---

<div class="post-metadata">

### Author: ![urbanjost](https://avatars.discourse-cdn.com/v4/letter/u/0ea827/32.png) [@urbanjost](https://fortran-lang.discourse.group/u/urbanjost)
#### Post date: [March 12, 2022, 5:28pm UTC](https://fortran-lang.discourse.group/t/immutable-declaration/2923/15 "2022-03-12T17:28:02Z")

</div>

Nice name for it, like that much better than IMMUTABLE. Anyone know of any other language with that attribute? I do not think I ever looked for it, but that would give more weight to adding a new attribute to types.

PS: It occurred to me later that the ASSOCIATED method would make it more likely the compiler would optimize the values more like a PARAMETER value than the PROTECTED method.

---

<div class="post-metadata">

### Author: ![Beliavsky](https://avatars.discourse-cdn.com/v4/letter/b/ba8739/32.png) [@Beliavsky](https://fortran-lang.discourse.group/u/Beliavsky)
#### Post date: [March 12, 2022, 9:39pm UTC](https://fortran-lang.discourse.group/t/immutable-declaration/2923/16 "2022-03-12T21:39:05Z")

</div>

> [@urbanjost](#):
>
> Nice name for it, like that much better than IMMUTABLE. Anyone know of any other language with that attribute? I do not think I ever looked for it, but that would give more weight to adding a new attribute to types.

What about `const` as in C and C++? In C++ you can write

```auto
#include <iostream>
#include <cstdlib>
#include <ctime>

int main()
{
	srand(time(0));
	int i = rand();
	const int j = i + 1;
	std::cout << i << " " << j;
	// invalid: j = j + 1;
}

```

---

<div class="post-metadata">

### Author: ![msz59](https://avatars.discourse-cdn.com/v4/letter/m/3d9bf3/32.png) [@msz59](https://fortran-lang.discourse.group/u/msz59)
#### Post date: [March 12, 2022, 9:50pm UTC](https://fortran-lang.discourse.group/t/immutable-declaration/2923/17 "2022-03-12T21:50:48Z")

</div>

IMHO C/C++ `const` is pretty much the same as Fortran `PARAMETER`

---

<div class="post-metadata">

### Author: ![Beliavsky](https://avatars.discourse-cdn.com/v4/letter/b/ba8739/32.png) [@Beliavsky](https://fortran-lang.discourse.group/u/Beliavsky)
#### Post date: [March 12, 2022, 10:01pm UTC](https://fortran-lang.discourse.group/t/immutable-declaration/2923/18 "2022-03-12T22:01:39Z")

</div>

> [@msz59](#):
>
> IMHO C/C++ `const` is pretty much the same as Fortran `PARAMETER`

It is more flexible, as shown in my example. I believe a Fortran PARAMETER must be known at compile time.

---

<div class="post-metadata">

### Author: ![msz59](https://avatars.discourse-cdn.com/v4/letter/m/3d9bf3/32.png) [@msz59](https://fortran-lang.discourse.group/u/msz59)
#### Post date: [March 12, 2022, 10:17pm UTC](https://fortran-lang.discourse.group/t/immutable-declaration/2923/19 "2022-03-12T22:17:06Z")

</div>

Yes, you’re right. So the `PARAMETER` is more like C’s `#define`-d macro.

Maybe the `protected` atribute could serve for that purpose inside a procedure?

---

<div class="post-metadata">

### Author: ![Beliavsky](https://avatars.discourse-cdn.com/v4/letter/b/ba8739/32.png) [@Beliavsky](https://fortran-lang.discourse.group/u/Beliavsky)
#### Post date: [March 14, 2022, 2:13am UTC](https://fortran-lang.discourse.group/t/immutable-declaration/2923/20 "2022-03-14T02:13:37Z")

</div>

For the case where a program reads command line arguments that are never changed, the program could be a shell that just gets the command line arguments and passes them to a subroutine where they are `intent(in)` arguments. That subroutine acts like a main program, calling other procedures to do the work. Below, by declaring the `main` subroutine `impure elemental`, it is easy to have many runs of the programs with different inputs, a common scenario.

```auto
module main_mod
implicit none
contains
impure elemental subroutine main(c1,c2)
real, intent(in) :: c1,c2
print*,"in subroutine main, c1, c2 =",c1,c2
! rest of program will be here, including calls to other procedures
end subroutine main
end module main_mod

program get_arg
use main_mod
implicit none
integer, parameter :: narg = 2
character (len=100) :: arg
real :: c1,c2
call get_command_argument(1,arg)
read (arg,*) c1
call get_command_argument(2,arg)
read (arg,*) c2
call main(c1,c2)
end program get_arg

```

---

<div class="post-metadata">

### Author: ![dwwork](https://avatars.discourse-cdn.com/v4/letter/d/71e660/32.png) [@dwwork](https://fortran-lang.discourse.group/u/dwwork)
#### Post date: [March 14, 2022, 2:03pm UTC](https://fortran-lang.discourse.group/t/immutable-declaration/2923/21 "2022-03-14T14:03:40Z")

</div>

There are many versions of `const` in C & C++:

These are basically a PARAMETER in Fortran (each with its own nuances):

```cpp
/* C and C++ */
#define SOME_CONSTANT 1
const int SOME_CONSTANT = 1; 
enum {
    SOME_CONSTANT = 1
};

// C++ only
constinit int SOME_CONSTANT = 1;
constexpr int SOME_CONSTANT = 1;
consteval int SOME_CONSTANT = 1;

```

In a function body, you can declare a variable as `const` by creating the variable when you need it. There are some schools of thought that espouse making this the default.

```cpp
void some_function() {
    const int immutable_variable = function_returning_an_int();
    ...
}

```

In a struct/class, you can declare a member to be `const` and it has to be set when the struct is created. (Ignoring the ability to cast away ‘constness’, which is almost always a code smell and can cause bad things to happen when it hits the compiler).

```cpp
typedef struct {
    const int immutable_variable;
} SomeStruct;

SomeStruct s = {1};

```

And I won’t go into `const` member functions of structs/classes in C++, `const` pointers/references, or `const` function arguments.

Rust makes all variables `const` by default, using the `let` keyword, and you have to ‘opt-in’ to mutability using the `mut` keyword:

```nohighlight
let immutable_variable = function_returning_an_int();   
let mut mutable_variable = function_returning_an_int();

```

And it also has PARAMETER like constants:

```nohighlight
const SOME_CONSTANT: int = 1;

```

One interesting feature of Rust allows you to separate the declaration from the definition of the variable, even though the variable is immutable:

```nohighlight
let immutable_variable;
// Lots of other stuff happens
immutable_variable = function_returning_an_int();

```

The rust compiler does an analysis of the function to make sure that the immutable variable can only be set once, through all code paths, and will complain otherwise.
