I'm new to Free Pascal and Lazarus. I'm testing out the new "advanced records" feature and getting what looks to be an unnecessary compiler warning.
The code is very simple, just a record with a single method to initialize the data fields. Something like:
{$mode delphi}
type TTest =
record
a,b: double;
procedure Init(x,y: double);
end
procedure TTest.Init(x,y: double);
begin
test.a := x;
test.b := y;
end;
var t: TTest;
begin
t.Init(0.1,0.2);
That last line shown, "t.Init()", always generates a compiler warning that 'variable "t" does not seem to have been initialized'.
Ok it's only warning, so obviously I can live with it, but I just want to make sure it's not due to some underlying misunderstanding on my part.
EDIT to add new information.
Re the Method verus Constructor point.
Looking into this some more I'm kind of glad that FPC doesn't allow constructors for records. Delphi has constructors but no destructors, and as far as I can tell constructors (for records) do absolutely nothing that a method couldn't do. I'm a minimalist, so to me there is no point to have extra syntax that does nothing more than some existing syntax does.
Particularly for a simple record like this, the very act of declaring it (var t: TTest) does all the "constructing" that this record needs. Anything else (like my Init) is just setting values, it's not constructing anything anyway. So as far as I can see constructors are not the answer, the compiler just needs to drop the warning.
Researching the issue I have come across one other technique that is often used, the so called "factory function". That is, a function outside of the record such as:
function InitTTest(x,y: double): TTest;
begin
Result.a := x;
Result.b := y;
end;
This technique does indeed work, and gets rid of the warning message. I don't like this method however and I wont use it. Advanced records don't have inheritance and other features of classes, encapsulation is all they've got going for them. So I really dislike having to make a "factory function" outside of the record like this.
Please bear in mind the the above is just the opinion of a "noob", after doing just a little research to answer my own question here. So if I'm wrong about anything above I'm quite happy to be corrected. :)
Yes, that is what constructors are for, the following compiles with FPC trunk and produces no warnings:
{$mode delphi}
type TTest =
record
a,b: double;
constructor Init(x,y: double);
end;
constructor TTest.Init(x,y: double);
begin
a := x;
b := y;
end;
var t: TTest;
begin
t.Init(0.1,0.2);
end.
Related
I'm trying to create a function in the for statement. But it didn't work.
Ex:
using SymPy
list=[1,1,-1]
a(x)=2^x
b(x)=3^x
c(x)=4^x
x = symbols("x")
for i=1:length(list)
if list[i]==1
a(x)=a(x)*b(x)
elseif list[i]==-1
a(x)=a(x)*c(x)
end
end
That is to say, I would like to yield,
a(x)=2^x*3^x*3^x*4^x
However, it only returned the original function.
a(x)=2^x
I am not sure is it functional or not.
Thanks :)
This looks like a scoping issue, check the docs here: https://docs.julialang.org/en/v1/manual/variables-and-scoping/
The for loop introduces its own scope, so the global a(x) that you declare outside the loop isn't affected by what's happening in your loop.
You can either wrap everything you do in a function:
function main()
list = [1, 1, -1]
...
return a(x)
end
or annotate the a(x) in your loop as global. Generally global variables are bad for performance and best avoided in Julia, so you should think about how you can structure your code into functions.
(FWIW I get a StackOverflowError for both of the solutions I mentioned here, but that's probably an issue with how you're using SymPy which I know nothing about unfortunately!)
In Delphi is there a way to declare a procedure as an alias of another?
Something like:
function AnAliasToUpperCase(const S: AnsiString): AnsiString = system.AnsiStrings.UpperCase;
and later in the program calling AnAliasToUpperCase or UpperCase must be exactly the same.
Defining it e.g. like a constant declaration:
const
AliasToUpperCase: function(const S: AnsiString): AnsiString = System.AnsiStrings.UpperCase;
might work for your needs.
The proper answer to the question "How to make an alias to a function/procedure" is "You can't".
But there are two workarounds to simulate this which both might introduce a bit of overhead - the first is the const as shown in the other answer.
Additionally to declaring it as const you can also declare it as new inline routine:
function AliasToUpperCase(const S: AnsiString): AnsiString; inline;
begin
Result := System.AnsiStrings.UpperCase(S);
end;
But then you are depending on the compiler settings for inlining and need to also add the AnsiStrings unit to wherever you are calling AliasToUpperCase or you will get the H2443 Inline function has not been expanded because unit is not specified in USES list warning.
For this function signature it works but for other return types you might suffer from missing return value optimization and have extra value copies.
I'm working with a PascalScript innosetup installer, and I fail to see where the control of the following block is flowing.
function Foo(): String;
begin
Result := 'foo';
RaiseException('...');
end;
procedure Test();
var
Z : String;
begin
Z := '';
try
Z := Foo();
except
Log(Z);
end
end;
My installer seems to indicate Z is being set with the Result of the Foo function. My understanding of exceptions in 'most' programming languages tells me the assignment Z := Foo() should not happen in case of exception.
When the Foo function raises, should Z still be assigned to?
Probably it handles result values by reference as implicit first argument. But then this can happen. It could be considered a legal of certain codegeneration/optimization, since it is quite a common way of handling return values.
However what is exactly defined in Object Pascal outside testing what Delphi does is murky territory, since there is only a x86 and x86_64 implementation. And Delphi will return the value in eax, so if you follow that logic this is illegal.
added later:
I tested Delphi with structured types, and while it passes a reference, it creates a copy on the stack to pass it.
This could make it hard to optimize code with structured types though, but a modifier/attribute to declare the return type const could fix that if ever needed.
In Delphi, strings as result values are treated like var parameters. In other words, a function like Foo is in fact compiled as:
procedure Foo(var Result: string);
begin
Result := 'Foo';
RaiseException(...);
end;
This means that Z (through the reference parameter) is assigned the value 'Foo' immediately, i.e. before the exception is raised.
In other words, the function result is not just kept in a local variable called Result and then returned when the function ends -- which would be prevented by the exception -- it is assigned immediately.
I assume this is exactly what happens in PascalScript as well.
So I'm just starting to learn Eiffel. One of the first exercises in the book I'm using says to make a function that does base^exp without using ^. I've copied my code below.
class
APPLICATION
inherit
ARGUMENTS
create
make
feature {NONE} -- Initialization
make
-- Run application.
do
create power(2;3)
printf("2 to the power of 3 is " + answer)
end
power(base : REAL; exp : INTEGER) : REAL
-- computers base raised to the bower of exp without using ^
local
remain : INTEGER
do
remain := exp
if remain = 0 then
result := 1
else
from
until
remain = 0
loop
result := result * result
remain := remain -1
end
end
end
end
How do I use this? Do I need it on the same level as feature{NONE}'s make? I know how I'm calling it is wrong, and I can't find anything in the chapter I just read, or online on how to pass parameters into it or how to use it's results.
There are several issues with the original code:
create is used to create an object, but you are not going to create anything, but to get a result of a computation of the function power by calling it. Therefore the keyword create is not needed.
You are using an entity answer to report the result of evaluation on a screen. However it is not declared anywhere. I believe the proper place would be a local variable declaration section.
The entity answer is not initialized to the result of the function power. This is usually done by an assignment instruction.
Feature arguments are separated by a comma, not by a semicolon.
From the original code it's unclear what is the type of the variable answer. Assuming it matches the type of the function power, before adding it to a string, it needs to be converted to a string. This is done by calling the feature out.
The standard feature for printing a string to a console is print, not printf.
Combining the critical points above, we get
make
-- Run application.
local
answer: REAL
do
answer := power(2, 3)
print ("2 to the power of 3 is " + answer.out)
end
After that the code can be compiled. Now less critical points:
It is a good style to put features to a dedicated feature clauses, so I would add a line like feature -- Basic operations before the feature power.
The implementation of the feature power has at least two problems. I'm not going to detail them here, but would give two hints instead:
by default numeric Result is initialized to 0, this needs to be taken into account for operations that use it without first assigning any other value
even though an argument base is passed to the function power it remains unused in the original version of the code
When writing a function I always have this confusion whether to check for errors first and declare the variables later (or) assign the parameters to local variables and then check for errors. Which of the following way is preferred and why? I usually stick to the first type.
void DoSomething1(Object x, Object y){
// All sort of error checking goes here
if IsError(x) return;
if IsError(y) return;
// Variable declaration
int i,j;
Object z = x;
}
void DoSomething2(Object x, Object y){
// Variable declaration
int i,j;
Object z = x;
// All sort of error checking goes here
if IsError(z) return;
if IsError(y) return;
}
You should follow a proximity rule and declare the variables as late as possible. This localises their creation and use. You should also check parameters for validity at the earliest possible opportunity to minimise the work performed.
Hence I agree that your first one is better but it is subjective. There's possibly arguments for the other approach but I've yet to hear convincing ones, so I consider those two guidelines as best practice.
Since you state "language agnostic" despite the fact your code looks somehow strangely familiar :-), there are almost certainly some languages where you don't get a choice and variables have to be declared at the top.
Declare variables when you need them, that's usually when some intermediate result is ready or when you're just about to enter a loop.
So this does imply that error checks will often come before declarations.