Lazarus
Free Pascal => General => Topic started by: Blaazen on May 09, 2014, 05:48:53 pm
-
Hello,
do I have any lack of Pascal languge? Is this possible to write in one line?
I mean some type-saving way to control one item of set with boolean.
type
TOption = (oOne, oTwo, oThree);
TOptions = set of Option;
...
if (Sender as TCheckBox).Checked
then Options:=Options+[oThree]
else Options:=Options-[oThree];
Thanks.
-
Do you refer to the set operators? They are OK.
-
Do you mean something in this way ?
Options[oThree]:=(Sender as TCheckBox).Checked;
if yes, I think this is not possible.
-
personally I have an ever growing set of iif functions to use in such cases eg
function IIF(Check :Boolean; TrueResult, FalseResult :Integer):Integer;overload;inline;
function IIF(Check :Boolean; TrueResult, FalseResult :String):String;overload;inline;
....
implementation
function IIF(Check :Boolean; TrueResult, FalseResult :String):String;overload;inline;
begin
If Check then Result := TrueResult else Result := FalseResult;
end;
......
but in this case I would do something like this.
function IIF(const Check :Boolean; const aSet:TOptions; const aOpt :TOption):TOptions;overload;inline;
begin
Result := aSet;
if Check then Include(Result, aOpt) else Exclude(Resut, aOpt)
end;
And its use looks like Options := iif((Sender as TCheckBox).Checked,Options,oThree);
-
Thanks. In past I used function too, I named it SwitchOption instead of IIF. I hoped there exists some trick with set operators. It seems that Mr. Wirth omitted this. :-[
-
I see no practical use for the following code, and would normally use your form of code, however - the challenge was raised :-)
More set up time, but only one line of code. In your case of course you would use (Sender as TCheckBox).Checked instead of bFlag...
Procedure TForm1.Button1Click(Sender: TObject);
Type
TOption = (oOne, oTwo, oThree);
TOptions = set of TOption;
Var
Options: TOptions;
bFlag: Boolean;
Const
LU_Option: Array[Boolean] of TOptions = ([], [oThree]);
Begin
Options := [oOne, oTwo, oThree];
bFlag := False;
Options := Options - [oThree] + LU_Option[bFlag];
End;
LU is shorthand for Look Up
I don't think Mr Wirth did too bad :-)
-
Nice 8)
-
I observed that other Pascal compiler (Delphi, GNU Pascal) cannot do it too. And it's not possible to hack it via Variant.
-
PByte(@Options + ord(oThree) div 8)^ := (PByte(@Options + ord(oThree) div 8)^ or (1 shl ord(oThree))) and ((ord(bFlag)*$FF or not (1 shl ord(oThree)))) ;
-
:-) Brilliant. I've absolutely no clue how that code works, but at least you can easily change the option you're changing which is a distinct advantage over mine :-)
-
PByte(@Options + ord(oThree) div 8)^
I am not sure this is endian save. So it may not work on all architectures.
-
PByte(@Options + ord(oThree) div 8)^ := (PByte(@Options + ord(oThree) div 8)^ or (1 shl ord(oThree))) and ((ord(bFlag)*$FF or not (1 shl ord(oThree)))) ;
The person that writes this in code that I'm reviewing, gets fired 8)
-
PByte(@Options + ord(oThree) div 8)^ := (PByte(@Options + ord(oThree) div 8)^ or (1 shl ord(oThree))) and ((ord(bFlag)*$FF or not (1 shl ord(oThree)))) ;
The person that writes this in code that I'm reviewing, gets fired 8)
Ahh, but the point wasn't to produce reviewable code, but to get it onto one line. Think of this as the obfuscated pascal competition.
(Sorry Blaazen, I appear to have hijacked your thread. No disrepect was intended, just got excited by the challenge :) )
-
The person that writes this in code that I'm reviewing, gets fired 8)
It is the multiplication, isn't it?
Far too inefficient for this task
Fixed it 8-)
PByte(@Options + ord(oThree) div 8)^ := (PByte(@Options + ord(oThree) div 8)^ or (1 shl ord(oThree))) and not (ord(not bFlag) shl ord(oThree)) ;
oh, crap, forgot the mod:
PByte(@Options + ord(oThree) div 8)^ := (PByte(@Options + ord(oThree) div 8)^ or (1 shl (ord(oThree) mod 8))) and not (ord(not bFlag) shl (ord(oThree) mod 8)) ;
-
1) If it was just about "on one line": Remove the line breaks, keep the original if.
Line breaks are for the human orly, so you can put the whole unit in one line, if you want.
2) from the OP:
I mean some type-saving way to control one item of set with boolean.
Probably meant "to save typing" rather than "save the type" (as in pascal being a strongly typed language).
But in either case: the whole PByte casting stuff, does not do either of that, or does it?
Options:=Options+[oThree]
If Options is a variable then using Include/Exclude may save a tiny bit of typing. But not much.
If you have lots of statements like that, all for the same type, write a helper function, or override an operator, or write a type helper.....
-
But in either case: the whole PByte casting stuff, does not do either of that, or does it?
It does, if you put it in a function
And you only need a single function, not a new one for every set-of-type
-
Here is an Operator based approach. Makes only sense, if you have lots of operations on the same type....
program Project1;
type
TOption = (oOne, oTwo, oThree);
TOptions = set of TOption;
TOptionModifier = record
opt:TOption;
act: Boolean;
end;
operator * (a: TOption; b: Boolean) c:TOptionModifier;
begin
c.opt := a;
c.act := b;
end;
operator + (a: TOptions; b:TOptionModifier) c:TOptions;
begin
if b.act
then c := a + [b.opt]
else c := a - [b.opt];
end;
var options: TOptions;
begin
Options:=[];
Options:=Options+oThree*True;
writeln(oThree in options);
Options:=Options+oThree*False;
writeln(oThree in options);
end.
-
It does, if you put it in a function
And you only need a single function, not a new one for every set-of-type
[/quote]
To make it ONE function, you need either untyped params, or call it with Foo(@Options, ord(OThree).
Either will remove type checking (one of the advantages of pascal), and allow you to specify a enum that does not belong to the same type as used for the set.
Then you may as well choose a language that has no type checking to begin with.
It also will not work, if "Options" is a property. No function will (unless it is a published property, and RTTI is used (specifying property as string/name))