I'm trying to filter my logging. If a log (or message) type is in the options, I want to send it to the log, otherwise exit.
The compilation fails on the "if not MessageType in..." line with:
"[dcc32 Error] uMain.pas(2424): E2015 Operator not applicable to this operand type"
I think it must be possible (and reasonably simple) based on the Include/Exclude functions, which I tried looking at but couldn't find anywhere (i.e. Include(MySet, llInfo); ).
My declaration are as follows:
type
TLogLevel = (llDebug, llError, llWarn, llInfo, llException);
TLogOptions = set of TLogLevel;
var
FLogOptions: TLogOptions;
procedure TfrmMain.Log(const s: String; MessageType: TLogLevel;
DebugLevel: Integer; Filter: Boolean = True);
begin
if not MessageType in FLogOptions then
exit;
mmoLog.Lines.Add(s);
end;
You need parentheses around the set operation because of operator precedence. The compiler is parsing it as if not MessageType, which is not a valid operation. If you put parentheses around the set test, the compiler can parse it correctly.
if not (MessageType in FLogOptions) then
This is a common issue, and is not specific to set types. For instance, you can get the same error with the following express as well.
if not 1 = 2 and 2 = 3 then
Adding parentheses around the two equality tests will correct the error.
if not (1 = 2) and (2 = 3) then
For more information, you can see the documentation for Operator Precedence
Related
According to
https://learn.microsoft.com/en-us/aspnet/core/web-api/action-return-types?view=aspnetcore-6.0#actionresultt-type
https://learn.microsoft.com/en-us/aspnet/core/web-api/action-return-types?view=aspnetcore-6.0#asynchronous-action-1
https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.mvc.actionresult-1?view=aspnetcore-6.0#operators
The following F# code should be legitimate:
[<HttpPost("post-data-2")>]
[<ProducesResponseType(StatusCodes.Status200OK)>]
[<ProducesResponseType(StatusCodes.Status500InternalServerError)>]
member this.PostData2(data: string): Task<ActionResult<int>> =
task {
try
return this.Ok(0)
with | x ->
return this.StatusCode(StatusCodes.Status500InternalServerError, -1)
}
Instead I get two compilation errors in the two 'return' lines
Error FS0193 Type constraint mismatch. The type
'OkObjectResult' is not compatible with type
'ActionResult'
and
Error FS0193 Type constraint mismatch. The type
'ObjectResult' is not compatible with type
'ActionResult'
This works however:
[<HttpPost("post-data-1")>]
[<ProducesResponseType(StatusCodes.Status200OK)>]
[<ProducesResponseType(StatusCodes.Status500InternalServerError)>]
member this.PostData1(data: string): Task<ActionResult<int>> =
task {
try
return ActionResult<int>(this.Ok(0))
with | x ->
return ActionResult<int>(this.StatusCode(StatusCodes.Status500InternalServerError, -1))
}
Why are the implicit cast operators not recognized by F#?
Not sure there can be much of an answer besides "because the language designers decided for it to be that way". Implicit conversions are only used in a narrow set of circumstances in F#.
In addition to calling the constructor as you have, you should also be able to explicitly call ActionResult.op_Implicit or define you own implicit conversion operator.
To allow multiselection in a file-open-dialog and to avoid this long expression:
OpenDialogSourceFiles.Options := OpenDialogSourceFiles.Options + [Vcl.Dialogs.fdoAllowMultiSelect]; // works
I tried to use the shorter Include function:
System.Include(OpenDialogSourceFiles.Options, Vcl.Dialogs.fdoAllowMultiSelect); // error
However, the compiler marks this as erroneous.
This is by design. The Include procedure requires a variable as its first argument (it is a var parameter, essentially, even though the procedure is implemented by compiler magic), but TFileOpenDialog.Options is a property.
Hence you must use the verbose alternative. There's nothing you can do about it.
The same thing applies to Inc and TComponent.Tag, for instance.
(But you can write fdoAllowMultiSelect instead of Vcl.Dialogs.fdoAllowMultiSelect, Include instead of System.Include, etc. to make it a bit less verbose.)
I have to access several functions of a DLL written in c from Delphi (currently Delphi7).
I can do it without problems when the parameters are scalar
(thanks to the examples found in this great site!), but I have been stuck for some time when in the parameters there is a pointer to an array of Longs.
This is the definition in the header file of one of the functions:
BOOL __stdcall BdcValida (HANDLE h, LPLONG opcl);
(opcl is an array of longs)
And this is a portion of my Delphi code:
type
TListaOpciones= array of LongInt; //I tried with static array too!
Popcion = ^LongInt; //tried with integer, Cardinal, word...
var
dllFunction: function(h:tHandle; opciones:Popcion):boolean;stdcall;
arrayOPciones:TListaOpciones;
resultado:boolean;
begin
.....
I give values ββto aHandle and array arrayOPciones
.....
resultado:=dllFunction(aHandle, #arrayopciones[0]);
end;
The error message when executing it is:
"Project xxx raised too many consecutive exceptions: access violation
at 0x000 .."
What is the equivalent in Delhpi for LPLONG? Or am I calling the function in an incorrect way?
Thank you!
LONG maps to Longint, and LPLONG maps to ^Longint. So, you have translated that type correctly.
You have translated BOOL incorrectly though. It should be BOOL or LongBool in Delphi. You can use either, the former is an alias for the latter.
Your error lies in code or detail we can't see. Perhaps you didn't allocate an array. Perhaps the array is incorrectly sized. Perhaps the handle is not valid. Perhaps earlier calls to the DLL failed to check for errors.
I'm making a function in Delphi that needs a specific value as parameter, unless it is set when function is called. While te default parameter be overwritten in that case?
example:
function ExampleFunction(b = 3, a){
b*a = c
}
ExampleFunction(15,2)
Will the default parameter(3) be replaced with the given parameter(15)?
Your code does not compile. Its syntax is invalid. It looks rather as though you have written the code in some hybrid of Pascal and C#. I suggest that you fix the question.
What's more, default parameters must appear last in the list. The reason for that is that default parameters allow you to omit an parameter when calling the function. When you do that, the compiler substitutes the missing parameter with the default value. Because parameters are positional, it is not possible to omit a parameter, but then pass another parameter that appears after it in the list.
The documentation, which I urge you to read one more time, says:
Parameters with default values must occur at the end of the parameter list. That is, all parameters following the first declared default value must also have default values.
Now to the question. If you do not omit the parameter, that is if you provide it, then the value you provided is used.
Let's use an example that actually compiles:
function Test(a: Integer; b: Integer = 42): Integer;
begin
Result := a * b;
end;
Then
Test(2) = 84 // parameter b is omitted, default value passed
and
Test(4, 3) = 12
I tried to make my code as simple as possible,but I failed at it.
This is my code:
class function TWS.WinsockSend(s:integer;buffer:pointer;size:word):boolean;
begin
dwError := Send(s,buffer,size,0);
// Debug
if(dwError = SOCKET_ERROR) then
begin
dwError := WSAGetLastError;
CloseSocket(s);
WSACleanup;
case (dwerror) of
//Case statement
else
LogToFile('Unhandled error: ' + IntToStr(dwError) + ' generated by WSASend');
end;
Exit(false);
end;
// if the size of the bytes sent isn't the expected one.
while(dwError <> size) do
dwError:= dwError + Send(s,Ptr(cardinal(buffer) + dwError),size-dwError,0);
Exit(true);
end;
The error is placed at
dwError:= dwError + Send(s,Ptr(cardinal(buffer) + dwError),size-dwError,0);
Error is "Constant object cannot be passed as var parameter"
I understand I need a variable,but isn't there a way I can do it without adding one more line?
When the compiler complains about the way you're passing a parameter, the first thing you need to know is what the parameter expects. Therefore, you should go look at the declaration of Send. If looking at the declaration doesn't immediately give you an idea of what to fix, then you need to include that declaration with the code you post in your question.
I suspect that this actually has nothing to do with incrementing a pointer. Instead, the compiler is complaining about the third parameter, where you are trying to pass the expression size-dwError. I guess the parameter is declared like this:
var buffersize: Word;
The function plans on providing a new value for that parameter β that's what var means β so the thing you pass to that parameter needs to be something that can receive a value. You can't assign a new value to the result of subtracting two variables.
Take a closer look at where the compiler complained about that line. Didn't it place the cursor somewhere near the third parameter? That's a clue that the problem is there.
Decrement size, and then pass it to the function.
Dec(size, dwError);
Inc(dwError, Send(s, Ptr(cardinal(buffer) + dwError), size, 0));
Why do you care about adding another line? Have you reached your quota for the day? Lines are cheap; don't be afraid to use two to express yourself when one won't do. Likewise for variables. When your code doesn't work, saving a byte or two doesn't matter at all.
At the very least, you should have added more lines in order to track down the source of the problem. When you have one line of code that's performing several independent calculations (such as getting a new pointer value, getting a new size, and calling a function), break the line into several separate pieces. That way, if there's a problem with one of them and the compiler complains, you'll know exactly which one to blame.
Correct, this will not work as written. When your dealing with var parameters, you have to build the parameter BEFORE passing it to the procedure/function. When a Var parameter is passed, the procedure is allowed to modify it. If you attempted to copy two variables together on the call, where would this result go?
The other issue is that dwError is not delcared. A class method does NOT have access to the data elements of the object the class defines. If you drop the class, then you will have access to the data elements, but will require that the class first be created.
You should only be using class methods in places where the input and output are completely contained within the method.
How are you allocating your buffer? Internally is it an array?
Sounds like Send has a format parameter (like send (const something;size:integer)
Workaround is using pchar (entirepointerexpression)[0]