3

I have some tabular data:

Foo       Bar
-------------
fooes     42
bars      666 
...

So, I declare the entity structure:

type TFoo = record
  Foo: string;
  Bar: Integer
end;

and the table of entities:

const FOOES = array [M..N] of TFoo = (
  // Have to specify the field names for each record...
  (Foo: 'fooes'; Bar:  42),
  (Foo: 'bars';  Bar: 666)
  { so on }
);

As you see, this looks quite verbose and redundant, and it is because I initialize all of the fields for all of the records. And there is a lot of editing if I copy tabular data prepared elsewhere. I'd prefer to not enumerate all of the fields and stick to the more laconic C style, that is, constants only. And here comes the record constructor...

Can record constructors help me in this case?

Here's an example in C. You'll notice that we don't have to specify the field names in each declaration:

#include <stdio.h>

typedef struct {
        char    foo[10];
        int     bar;
} foo;

int main(void) {
        /* Look here */
        foo FOOES[2] = {{"foo", 42}, {"bar", 666}};
        int i = 0;
        for (; i < 2; i++) {
                printf("%s\t%d\n", FOOES[i].foo, FOOES[i].bar);
        }
        return 0;
}
Uli Gerhardt
  • 13,748
  • 1
  • 45
  • 83
OnTheFly
  • 2,059
  • 5
  • 26
  • 61
  • 1
    Can you provide an example of this C style that you're hoping for? – Marcus Adams Nov 28 '11 at 22:55
  • @Marcus Adams, a trick question? In C its pretty straightforward: http://ideone.com/SYkLQ – OnTheFly Nov 28 '11 at 23:32
  • 1
    When copying your data from another source, so don't always need "a lot of editing." Record a macro of the keystrokes required to convert one row into the Delphi syntax, and then replay the macro on each of the other lines. You could also store your data in some other format and load it at run time. For more ideas, please consider asking a more open-ended question: How can I express constant data concisely? What you've asked is a simple yes-no question, so answers aren't going to be very helpful or interesting. – Rob Kennedy Nov 28 '11 at 23:46
  • 1
    Expecting people to go to an off-site URL to see what it is you want instead of adding it to your question is not a good idea. Please edit your question and add it there, so people can easily see what you're asking; you'll probably get an answer much faster that way. – Ken White Nov 28 '11 at 23:48
  • Meh, @Rob Kennedy, complaint about "table disability" was rather important :-) I mean, if we keep quiet about problems - no one will ever do something about it. Your version represents header row pretty well, indeed. Re: external file - this is clearly not an option, defeats the essence of the source code constant. Re: keyboard macro - i really dont know, my example is very primitive, real data is quite complex and with strings of variable size (ofc, not pre-quoted for me), eg: i have no idea if i can make IDE to always move caret to the correct position to before inserting the field name... – OnTheFly Nov 29 '11 at 00:16
  • @Rob Kennedy, re: interesting question: maybe a next time when i'll finish this one, i've got one more *constant challenge* with plenty of items to declare :) – OnTheFly Nov 29 '11 at 00:20
  • @Ken White, why? It is not really relevant and directed toward Marcus (or anyone else who curious enough about C counterpart to visit a new website) – OnTheFly Nov 29 '11 at 00:24
  • 1
    It's absolutely relevant. You specifically mentioned "laconic C style", but don't bother to describe what exactly you'd like to do. If you won't put the effort into asking your question, why should we put the effort into trying to answer it? (And you've put far more effort into debating the quality of your question in the comments.) As Rob said, the answer to the question you've asked so far is a simple "yes" or "no". – Ken White Nov 29 '11 at 00:56
  • @Ken White, i do not agree, sorry. Also, no one seconded your motion. And, BTW, you are currently bothering to put even more efforts into continued discussion about quality. Why? – OnTheFly Nov 29 '11 at 01:46
  • @user53, in most similar questions, especially when comparing language syntax, the OP will show examples of what they're trying to do in the other language. I'll edit your question to include the code sample. – Marcus Adams Nov 29 '11 at 06:13
  • irrespective of all this discussion, the question asked still has a simple answer – David Heffernan Nov 29 '11 at 07:19
  • If you want to complain about table features of Stack Overflow, go to Meta; here is not the place for it. – Rob Kennedy Nov 29 '11 at 14:07
  • Whether loading from a file retains the "essence of the source code constant" depends on what you think that essence is. Keep the file in your project directory, check it in to source control, and include it in your build steps. It's now part of your source code. It's not Delphi anymore, but if you insisted on it being Delphi, it would no longer be easily editable because of the syntax limitations discussed here today. Every time you *copy* from the file into your Delphi code, you risk the original data and the Delphi code getting out of sync. Avoid that by loading from the file directly. – Rob Kennedy Nov 29 '11 at 14:11
  • @Rob Kennedy, this is kinda twisted logic for programmer. How constant declared at module X line Y can be different from whatever.dat file whatever format? They are the same, LOL – OnTheFly Nov 30 '11 at 11:33

3 Answers3

3

A const is just a read-only var which is loaded/mapped within the code, when the executable is launched.

You can create a var record (or a const but overriding the writable const option), then initialize it in the initialization section of the unit.

var FOOES = array [M..N] of TFoo;

....

initialization
  SetFooArray(FOOES,['fooes',42,'bar',230]);
  ...
end.

The custom SetFooArray() function will put all array of const parameters into FOOES.

I use this technique sometimes to initialize computable arrays (e.g. conversion or lookup tables). Sometimes, it does make sense to compute once at startup a huge array, saving some KB of const in the source code, with a few lines of code.

But I'm not sure it will be worth it in your case. The default const declaration is a bit verbose, but not a problem if you use Ctrl+C/Ctrl+V or a find and replace. It is the most standard, is secure if you change later the record layout (whereas the C construction may compile without error), and will create a true constant.

Community
  • 1
  • 1
Arnaud Bouchez
  • 42,305
  • 3
  • 71
  • 159
2

Record constructors are runtime only and so for constants your current solution is the only option.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
0

If you want it done in source then what you have already typed is your answer. You could, of course, put the data in separate arrays and initialize them that way, but that can make your code look messy.

You could also store them in an text file (Foo=Bar format) and read them into a TStringList at run-time (SL.LoadFromFile()). But even with a sorted TStringList it will be far less efficient (MyVariable := SL.Values['Foo1']; for example).

There are a million ways to solve this problem outside of source code. Taking it from the other direction, put the data into Excel and create an Excel macro to build the source and put it into the clipboard to paste into your PAS file. This wouldn't be too difficult and probably easier than formatting the Delphi code within the IDE.

Jerry Gagnon
  • 1,131
  • 8
  • 16
  • Finally i finished with this task, resorted to code generation - separate include file with data formatted as pascal style consts. Guess it is both clear and even resilient to changes – OnTheFly Nov 30 '11 at 11:42