|
I assume you know about the 'fluent api pattern', e.g. in c#, something like:
new MyFluentApi()
.DoThis(x)
.DoThat(y)
.DoAnother(z);
Now, I was looking for that pattern to do a similar thing in Pascal and recognized, that it is allready something like 'build in' since decades
WITH myFluentThing DO BEGIN
DoThis(x);
DoThat(y);
DoAnother(z);
END;
|
|
|
|
|
Yep
Relearning Pascal, Turbo Pascal 3.0 on a RC2014 Z80 hardware running under CP/M 2.2.
Been since college days the last time I even saw any Pascal code. Wrote a couple of simple apps, still learning.
Learning the editor is twice as hard as the code. We sure take modern editors for granite.
If you can't find time to do it right the first time, how are you going to find time to do it again?
PartsBin an Electronics Part Organizer - Release Version 1.4.0 (Many new features) JaxCoder.com
Latest Article: EventAggregator
|
|
|
|
|
To be honest, I don't know Pascal really. I was a Modula2 Guy for decades (Modula also invented by Niklaus Wirth, the Pascal inventor I think).
And yes, I hate the 'WITH' in Pascal/Modula (especally when nested), but now I recoginze, it can be usefull too
|
|
|
|
|
Modula is available to run on CP/M, been thinking about kicking the tires.
Going on vacation tomorrow for a week but may give it a whirl when I get back.
If you can't find time to do it right the first time, how are you going to find time to do it again?
PartsBin an Electronics Part Organizer - Release Version 1.4.0 (Many new features) JaxCoder.com
Latest Article: EventAggregator
|
|
|
|
|
Enjoy your vacation
|
|
|
|
|
I was stunned by "FluentApi" when I heard the term.
I first saw it in modern times in C# unit testing and all these new devs were like "fluent api is so special...oh, wow, this new fluent api is just so amazing."
I was like, "what is fluent api?"
Then I saw it was something we were doing in C++ (specifically MFC/C++) back in 1995 or something.
Ok, so you return an object from the method and then you can call another method on the object immediately.
These new technologies which are 25 years old are so amazing!!
Bell bottoms are in too and they are also amazing new technology that the world has never seen.
|
|
|
|
|
|
I know some Clapton but hadn't heard that song. Great stuff! Sounds great and it's live.
Thanks for sharing.
|
|
|
|
|
Mike Hankey wrote: Been since college days the last time I even saw any Pascal code. Was Pascal already there when you went to college?
Sorry... I could not avoid it
M.D.V.
If something has a solution... Why do we have to worry about?. If it has no solution... For what reason do we have to worry about?
Help me to understand what I'm saying, and I'll explain it better to you
Rating helpful answers is nice, but saying thanks can be even nicer.
|
|
|
|
|
Towards the end, started out with PL/1.
No seriously we would scratch 1s and 0s in the sand and wait for the guy named Alu to come around with his abacus and perform the operation for us.
I'm so old I was the counter for Noah, but I was fired for letting cockroaches on the ship. In my defense I was busy picking out two of the female species to load.
If you can't find time to do it right the first time, how are you going to find time to do it again?
PartsBin an Electronics Part Organizer - Release Version 1.4.0 (Many new features) JaxCoder.com
Latest Article: EventAggregator
|
|
|
|
|
Mike Hankey wrote: I'm so old I was the counter for Noah So you have changed your name since? I mean, if you survived the flood, you must have been one of his sons...
I was busy picking out two of the female species to load Have you noticed that a large fraction of the pictures made of the animals entering the ship, two by two, where the two lions both have large manes? I wonder how we can have lions today...
But then, we are getting close to the yearly rainbow festivals, which is a good occasion to bring up these drawings/paintings.
Religious freedom is the freedom to say that two plus two make five.
|
|
|
|
|
Add to that the fact that 2 individuals are not enough to re-establish a population.
The difficult we do right away...
...the impossible takes slightly longer.
|
|
|
|
|
I guess that my background with Pascal and WITH as a student is a major reason why I never use this.something when programming in OO languages.
As classical Pascal did not have classes, you could not put functions manipulating the object (aka. RECORD) into the object definition itself. For functions that would later, in OO languages, become methods of the class, WITH was a nice way to simulate that you were inside the object definition.
I never understood why some people insist on using this. everywhere. I read it as a warning: The simple identifier would be ambiguous, and this. is a way to resolve the ambiguity. Sort of like always including the full path from the complete namespace name down to the method name when calling it. I guess my negative reaction to both is that I grew up with WITH as standard way to indicate that 'Now I am manipulating this object'.
Religious freedom is the freedom to say that two plus two make five.
|
|
|
|
|
Well, as I mentioned in another reply in this thread, the problem with using "with" is that is you have multiple records/objects with the same names for data (of the same TYPE) or methods/procedures/functions, you can not be sure which one might be called/referred to. So the use of "with" blocks should be deliberate and limited in scope, in order to prevent any ill effects, even if it is that your source won't compile because of the stringent type checking of Pascal. At the very least it requires you to find out which element of which record/object is actually referred to, which then needs to be fixed by adding at least one non-ambiguous prefix to the code line(s).
For example, if you have two records (A and B), which both have a element called C, a "with" block like
with A, B do
begin
C := 1;
C := 0;
end;
Not only looks wrong, but might actually yield unexpected results, if what you actually intended to write is
A.C := 1;
B.C := 0;
The same goes for calling methods of the same name in different objects, so something like
with A, B do
begin
C ("foo");
C ("bar");
end;
when actually is intended to be
A.C ("foo");
B.C ("bar");
With different types of parameters of the methods A.C() and B.C(), this won't compile, but if they happen to have the same parameter (or are parameter-less!), again, the outcome might now be what you have intended...
|
|
|
|
|
Ralf Quint wrote: you have multiple records/objects with the same names for data (of the same TYPE) or methods/procedures/functions, you can not be sure which one might be called/referred to. You have exactly the same problem with instances of a class definition (i.e. objects): When you read the code in the class methods, you cannot know which instance, which object, is being manipulated.
A Pascal "with" isn't very good at hiding it: "with SomeObject do ..." sort of identifies SomeObject as the one being manipulated, doesn't it?
I cannot remember ever listing multiple variables the way you do - it seems like you are doing it specifically to create a problem - one that isn't there, if you follow the Pascal line of thought. Let me construct another example:
procedure P;
var C: integer;
procecdure Q;
var C: integer;
begin
C:= 1;
end;
begin
end; The "C:= 1;" - which C does it refer to? The one declared in Q or the one declared in P? No Pascal programmer would be in doubt.
Let's now write
with A do
with B do
begin
C:= 1;
end; Is it difficult to see whether the "C:= 1;" refers to B.C or to A.C? No Pascal programmer would find it difficult!
with A, B do is just a short form of
with A do
with B do As long as you are within the 'with B do' (in either the short or the long form), the B scope is the innermost. The search for the definition of a symbol always starts in the scope where there reference is made, and the first definition in the outwards search applies. This is always true; it is not particular to nested "with" statements.
If you, in the first example, need to reference P's C from the body of Q, you must rename Q's C. (Pascal has no syntax for explicitly referencing a local variable at an outer procedure level.) If you need to reference A's C from within a 'with B do', then you do have a syntax for it: A.C references A's C (surprise!). "with B do C:= 1" references B's C (surprise!).
This is not any problem, no sort of ambiguity, but plain scoping rules. An inner scope redefines an identically named symbol in an outer scope. If you grew up in a K&R C environment, maybe you don't have statically nested scopes under your skin. A Pascal programmer has.
Religious freedom is the freedom to say that two plus two make five.
|
|
|
|
|
Very interesting that you are trying to explain how Pascal works to someone who is programming in various versions of Pascal, as the main programming language, for 48 years now.
Yes, the "with A, B" is (for decades, nothing new) just a shorter form of writing a nested "with A..with B". That alone is not a problem, never is, never was.
The problem that I was pointing out, and you apparently didn't understand, is that within the nested WITH statements (regardless of how you write it), it IS POSSIBLE to create an unintentional ambiguity, which is NOT guaranteed to be always have the same precedence. If you think that, it clearly shows that you have not worked with a lot of different Pascal implementations.
And the application of scopes within nested procedures/functions, that is completely different issue. THAT is clearly defined. But that would be also not related to the initial post of this thread.
|
|
|
|
|
Ralf Quint wrote: Very interesting that you are trying to explain how Pascal works to someone who is programming in various versions of Pascal, as the main programming language, for 48 years now. I did not intend my post an answer to you personally, but as a post available to the general public. The majority of CP readers are unfamiliar with the semantics of Pascal "with" - a great deal haven't even worked much with statically nested scopes in any sense. Your profile doesn't tell that you have been programming Pascal for 48 years, so I couldn't possibly have adapted my post to that!
within the nested WITH statements (regardless of how you write it), it IS POSSIBLE to create an unintentional ambiguity Are you saying that it not only is POSSIBLE, but you did it? You claim that there is 'an unintentional ambiguity', but I see none.
which is NOT guaranteed to be always have the same precedence What are you saying here? That you have been working with Pascal compilers that did not create an inner scope for B with the short form ("with A, B do")? Did that compiler claim to be conformant to the language standard?
If there were an ambiguity, then there would be two different ways to interpret the semantics of the statement (here: "C:= 1;"). Some Pascal compilers would select one semantic, others would select the other. If you claim that you have seen both, in different Pascal implementations, I would sure like to hear which they are, and which one provides which semantics. Also, I'd like to know if they both claim standard conformance. I am quite sure that they both could!
it clearly shows that you have not worked with a lot of different Pascal implementations Only about half a dozen, on VAX, CDC, ND, IBM, MC68 and x86 machines. It is long ago, so they were all Pascal compilers, and
calling methods of the same name in different objects, so something like
with A, B do
begin
C ("foo");
C ("bar");
end; was not a valid syntax - plain Pascal doesn't have objects, only records, and you cannot "call methods in different objects".
Original Pascal was a well defined, consistent language, defined by people who knew how to define unambiguous grammars. A couple years later, a more successful competitor, as it turned out, was created by people who certainly did not master formal language grammars to the same degree. They were not alone - defining (or extending) good formal languages require experts. Lots of programming languages are defined by people who are not top experts.
I would not be surprised if some of the object extensions of plain Pascal were defined by people who were trying to transfer ideas from competing languages defined by people with less competence in good language design. Maybe that could introduce some ambiguity into the extended language. And, if two independent groups made two independent extensions of the language (effectively creating two languages), they might of course create extensions with differing semantics. That doesn't introduce an 'ambiguity' in the original Pascal!
And the application of scopes within nested procedures/functions, that is completely different issue. THAT is clearly defined. I have been studying only a single Pascal compiler (the FOSS compiler from ETH). That one most certainly used exactly the same inner mechanism for entering an inner scope, whether nested procedures or nested "with" - an array of trees of symbol definitions, with a global index telling which is the current innermost scope. When the parser encounters a symbol, it searches the trees one by one, starting at the highest valid index (the current scope), working backwards through the trees until a definition is found. This is done in one way, identical for record fields, function names or variable names. So it is not 'a completely different issue'.
But that would be also not related to the initial post of this thread. Which may be why I answered to a post in a branch, not directly to the OP. But, the original post was about Pascal "with". Pascal "with" is about scoping, more or less by definition. So we are not that far off track!
Religious freedom is the freedom to say that two plus two make five.
|
|
|
|
|
You just do not want to understand, so I am just leaving it at that. EOT...
|
|
|
|
|
I don't see that there is much more to understand. You claim there is an ambiguity that isn't there. You insist that it nevertheless is there, but refuse to explain when, where and why it is there.
Your 48 years of Pascal experience is not explanation for why it should be ambiguous. Nor is the number of Pascal compilers you have been using. Your unambiguous code snippet is not made ambiguous by your saying that it is.
The only thing that needs explanation is why you claim some sort of ambiguity in these samples. You are the one making the claim, you must provide the arguments for it. You refuse to. Fair enough. Then you are not providing any support for the ambiguity you claim.
You are quite right: I do not understand the ambiguity that isn't there
Religious freedom is the freedom to say that two plus two make five.
|
|
|
|
|
That Pascal code isn't anything fluent at all, it's just a series of method calls. The direct equivalent of the C# code would be (removing the use of WITH as an anti-pattern):
var myFluentThing := TFluentThing.Create
.DoThis(x)
.DoThat(y)
.DoAnother(z);
This is only possible, as is true for C#, if the DoThis and DoThat functions return an instance of the TFluentThing class.
|
|
|
|
|
But at the end comes nearly to the same
|
|
|
|
|
Ermmm, no, because that is like saying 2 + 2 = 3, because 3 is nearly 4
|
|
|
|
|
In the C# chain, methods may return the same or different objects at any stage.
The WITH block just calls the methods on the original object.
IThing thing = new ThingBuilder()
.AddTitle("I'm a Thing!")
.CreatePreciousThing()
.SetPreciousLevel(100);
|
|
|
|
|
Finally it comes up to the same from a user point ...
|
|
|
|
|
Well, no. I must admit that I do not use C#, only know the very basics of it.
"new" in C# is creating an instance of an previously defined object (MyFluentAPI) and executes those 3 methods.
As for "Pascal", you did not mentioned which kind of Pascal you are using.
In "standard" Pascal (including but not limited to ISO7185), the "with" statement is used to set the scope for the statements within the begin...end block, and is used in connection with "records" ("struct" in C) to save on some typing, as you would not have to precede each record element with its associated record name. But in this case, those elements within that record are purely data!
It is purely what sometimes these days is referred to as "syntactic sugar".
But the major difference is that the record (and in extension, this applies mostly to objects/classes in Object Pascal (Delphi/FreePascal) as well) needs to be existing (already instantiated) when you are referring to it using the "with" statement (block).
If you are using the "with" statement in either standard/procedural Pascal or Object Pascal, you need to do this carefully, as, while it saves some typing and the source code lines shorter, it can lead to some nasty side effects/bugs (or features ) if you have elements, like data or methods/procedure/functions with the same names in different records/methods/etc...
|
|
|
|
|