Recent

Author Topic: Constant and CASE Types do Not Match  (Read 1326 times)

local-vision

  • Jr. Member
  • **
  • Posts: 77
Constant and CASE Types do Not Match
« on: July 11, 2024, 07:58:14 pm »
So this works with a CASE construct using strings:

Code: Pascal  [Select][+][-]
  1. case C of  
  2.    ’a’ : WriteLn (’A’);  
  3.    ’b’ : WriteLn (’B’);  
  4.    ’c’ : WriteLn (’C’);  
  5. end;

C is a String.

But this does Not work?

Code: Pascal  [Select][+][-]
  1. case C of  
  2.    a : WriteLn (’A’);  
  3.    b : WriteLn (’B’);  
  4.    c : WriteLn (’C’);  
  5. end;

In which a,b and c are declared and initialized Strings.

I get: Error: Constant and CASE types do not match

Did I miss something?
« Last Edit: July 11, 2024, 07:59:57 pm by local-vision »

440bx

  • Hero Member
  • *****
  • Posts: 4731
Re: Constant and CASE Types do Not Match
« Reply #1 on: July 11, 2024, 08:13:52 pm »
What you missed is that the values in the case statement must be constants, that's why it works when you use 'a' and does not work when you use a string variable named a (or any other name for that matter.)

HTH

(FPC v3.0.4 and Lazarus 1.8.2) or (FPC v3.2.2 and Lazarus v3.2) on Windows 7 SP1 64bit.

dsiders

  • Hero Member
  • *****
  • Posts: 1282
Re: Constant and CASE Types do Not Match
« Reply #2 on: July 11, 2024, 08:19:10 pm »
Preview the next Lazarus documentation release at: https://dsiders.gitlab.io/lazdocsnext

MarkMLl

  • Hero Member
  • *****
  • Posts: 8027
Re: Constant and CASE Types do Not Match
« Reply #3 on: July 11, 2024, 08:35:33 pm »
Yes. The documentation.
https://www.freepascal.org/docs-html/ref/refsu56.html
First sentence.

That's unfair, because he says "a,b and c are declared and initialized Strings". So while he can be faulted for relying on that statement and not posting a compilable program, I feel that the point made by the manual needs expansion.

What matters is /how/ they're declared, and /how/ they're initialised: basically

Code: Pascal  [Select][+][-]
  1. const
  2.   a= 'a';
  3.   b= 'b';
  4.   c= 'c';
  5.  

is OK, while neither

Code: Pascal  [Select][+][-]
  1. var
  2.   a: string= 'a';
  3.   b: string= 'b';
  4.   c: string= 'c';
  5.  

nor the precisely-equivalent

Code: Pascal  [Select][+][-]
  1. var
  2.   a, b, c: string;
  3.  
  4. begin
  5.   a := 'a';
  6.   b := 'b';
  7.   c := 'c'
  8. end.
  9.  

is acceptable since in those cases a, b and c are storage locations initialised by runtime code, rather than being constants fully accessible to the compiler. And that rule applies to both case statements operating on ordinals (integer, individual characters etc.) which I believe are implemented by jump tables, ans case statements operating on strings which are basically "syntactic sugar" translated to if-then-else etc.

It could be argued that the compiler should be able to work it out, but basically the developers have to stop somewhere and IMO there's already too much in the core language.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Logitech, TopSpeed & FTL Modula-2 on bare metal (Z80, '286 protected mode).
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

local-vision

  • Jr. Member
  • **
  • Posts: 77
Re: Constant and CASE Types do Not Match
« Reply #4 on: July 11, 2024, 10:42:27 pm »
Appreciated the prompt responses and info.

Important remarks, chewing and digesting.

In the mean time I can imagine that only const are permitted and not var strings as the former is more robust. The latter can break your code more easily.

In other words a var value might change during the course of the run time while the const will always be fixed at its design time value and not change during run time.

Might that be (part of) the reason?
« Last Edit: July 11, 2024, 10:43:58 pm by local-vision »

440bx

  • Hero Member
  • *****
  • Posts: 4731
Re: Constant and CASE Types do Not Match
« Reply #5 on: July 11, 2024, 11:08:29 pm »
Might that be (part of) the reason?
The reason for requiring constants and forbidding variables is because of the way the case statement is usually implemented in assembly.  The compiler tries, whenever possible/efficient, to create a jump table to each case.  A jump table can only be created if the case values are constants (enumerable.)

That said, in the case of using string constants, the compiler cannot generate a jump table as string constants are not enumerable therefore cannot be used to produce a jump table.

HTH.
(FPC v3.0.4 and Lazarus 1.8.2) or (FPC v3.2.2 and Lazarus v3.2) on Windows 7 SP1 64bit.

Khrys

  • Full Member
  • ***
  • Posts: 105
Re: Constant and CASE Types do Not Match
« Reply #6 on: July 12, 2024, 07:43:44 am »
[...] the const will always be fixed at its design time value and not change during run time.
Well, about that... :-[

Code: Pascal  [Select][+][-]
  1. const
  2.   FOOBAR: String = 'Hello';
  3.  
  4. procedure Test();
  5.   FOOBAR := 'Goodbye';  // Compiles just fine!
  6.   WriteLn(FOOBAR);      // Output: 'Goodbye'
  7. end;

If the  {$J+}  switch is on (which it is by default in  {$mode objfpc}), then typed constants can be written to. They behave exactly like (static) variables with the difference that they must have an initial value at declaration.
This only applies to constants with an explicit type annotation, though; untyped constants truly are immutable.

local-vision

  • Jr. Member
  • **
  • Posts: 77
Re: Constant and CASE Types do Not Match
« Reply #7 on: July 12, 2024, 10:07:40 am »

Code: Pascal  [Select][+][-]
  1. const
  2.   FOOBAR: String = 'Hello';
  3.  
  4. procedure Test();
  5.   FOOBAR := 'Goodbye';  // Compiles just fine!
  6.   WriteLn(FOOBAR);      // Output: 'Goodbye'
  7. end;


That is so strange. Did not know you could even do that. Or maybe I did but forgot long ago.

I can imagine that as defined as a String it could represent anything. If the constant were defined as a Real then it could only represent numeric values.

But without the Type the const is immutable.

440bx that is what was meant, not "enumerable" but "immutable" correct?

In any case, good point.

440bx

  • Hero Member
  • *****
  • Posts: 4731
Re: Constant and CASE Types do Not Match
« Reply #8 on: July 12, 2024, 11:48:29 am »
440bx that is what was meant, not "enumerable" but "immutable" correct?
with the exception of strings, it must be both, immutable (IOW, constant) and enumerable which means,(have a predictable sequence which ordinals have but strings don't have, e.g, what comes after "ab" ? ... is it "ac" or "abc" or something else ?... they cannot be enumerated but, what comes after the numeral 3, it better be 4. 

The enumerability is what gives the compiler the ability to produce a jump table.
(FPC v3.0.4 and Lazarus 1.8.2) or (FPC v3.2.2 and Lazarus v3.2) on Windows 7 SP1 64bit.

MarkMLl

  • Hero Member
  • *****
  • Posts: 8027
Re: Constant and CASE Types do Not Match
« Reply #9 on: July 12, 2024, 12:37:07 pm »
The mutable consts can be useful to retain state inside functions, where lifetime<>scope (i.e. unlike "traditional" ALGOL/Pascal). But I really wish Borland hadn't reused "const" like that but instead had introduced some sort of static qualifier.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Logitech, TopSpeed & FTL Modula-2 on bare metal (Z80, '286 protected mode).
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

local-vision

  • Jr. Member
  • **
  • Posts: 77
Re: Constant and CASE Types do Not Match
« Reply #10 on: July 12, 2024, 01:53:18 pm »
The enumerability is what gives the compiler the ability to produce a jump table.

That provides some clarity.

But I really wish Borland hadn't reused "const" like that but instead had introduced some sort of static qualifier.

I see your point.

Appreciated the input :)
« Last Edit: July 12, 2024, 07:11:28 pm by local-vision »

 

TinyPortal © 2005-2018