Recent

Author Topic: Idea of multi-line strings, mantis 35827  (Read 6488 times)

jamie

  • Hero Member
  • *****
  • Posts: 4928
Re: Idea of multi-line strings, mantis 35827
« Reply #45 on: December 29, 2020, 03:12:16 am »
I can see disaster striking with my code now..

I use lots of comments on lines and I use all the variants of the types of comments..

one thing I do which works with a tool I have is i can insert TAG id's in the comments and it goes out and opens a database of much deeper references for that code..
 
   Things like PDF files can be attached to that TAG on the line so I can get a full detail of help in the future when I look at old code..

 all these PDF files are also stored in the project file and I have a data base of indexes that match up with tags and line numbers...

 I can see this spaghetti mess really giving me a bad day..

 screwing with a code editor to turn it into a word processor isn't my cup of tea..

 There better be a switch to turn this OFF!

The only true wisdom is knowing you know nothing

PascalDragon

  • Hero Member
  • *****
  • Posts: 3412
  • Compiler Developer
Re: Idea of multi-line strings, mantis 35827
« Reply #46 on: December 29, 2020, 11:37:51 am »
But as well there is the interpolation feature to add variables inside.

Definitely no.

There better be a switch to turn this OFF!

The multiline string feature is coupled to a modeswitch that's off by default.

But even then: the feature being enabled won't affect your code in any way if you don't use it. And you can't do anything against third party developers that do use the feature and where you use these units (as modeswitches are per-unit).

lainz

  • Hero Member
  • *****
  • Posts: 3852
Re: Idea of multi-line strings, mantis 35827
« Reply #47 on: December 29, 2020, 04:03:38 pm »
But as well there is the interpolation feature to add variables inside.

Definitely no.

I know, I already know, always I get that response from FPC.

Zoran

  • Hero Member
  • *****
  • Posts: 1675
    • http://wiki.lazarus.freepascal.org/User:Zoran
Re: Idea of multi-line strings, mantis 35827
« Reply #48 on: December 29, 2020, 05:03:16 pm »
And about leading whitespace in kotlin there is a method to remove whitespace from left and right

What do you mean?

There are functions in fpc as well (in SysUtils - Trim, TrimLeft, TrimRight, which are also provided as String helper routines). Plus, with LazUtils dependecy, in LazUTF8 unit there is UTF8Trim function with more possibilities...

lainz

  • Hero Member
  • *****
  • Posts: 3852
Re: Idea of multi-line strings, mantis 35827
« Reply #49 on: December 29, 2020, 05:32:06 pm »
And about leading whitespace in kotlin there is a method to remove whitespace from left and right

What do you mean?

There are functions in fpc as well (in SysUtils - Trim, TrimLeft, TrimRight, which are also provided as String helper routines). Plus, with LazUtils dependecy, in LazUTF8 unit there is UTF8Trim function with more possibilities...

I mean this
https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.text/trim-indent.html

Warfley

  • Hero Member
  • *****
  • Posts: 556
Re: Idea of multi-line strings, mantis 35827
« Reply #50 on: December 29, 2020, 09:56:22 pm »
I mean this
https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.text/trim-indent.html
This is not possible in Pascal due to the strict runtime and compiletime separation, which Kotlin simply does not have.

There can't be runtime code in the declaration section. Example:
Code: Pascal  [Select][+][-]
  1. const
  2.   s_const = 'foo'.Trim; // does not work, the expression here must be a compile time expression
  3.   s_static: String = 'foo'.Trim; // does not work, the expression here must be a compile time expression
  4. var
  5.   s: String = 'foo'.Trim; // does not work, the expression here must be a compile time expression
  6. begin
  7.   s := 'foo'.Trim; // works
  8. end.
To use runtime code, like a Trim function, you need to in the implementation block of your function, program, whatever and not in the definition block (where variables, constants, etc. are defined).

Kotlin does not have such a limiation, Kotlin can execute anything anywhere.

The only possible solution on how to build something like this would be to make trim a compiler intrinsic like sizeof. Or one could just restrict himself to using runtime constructs and don't use that in constants or as initial value for variables. But honestly I think that multiline strings are most useful in constants, so this does not seem like a good solution
« Last Edit: December 29, 2020, 09:58:13 pm by Warfley »

lainz

  • Hero Member
  • *****
  • Posts: 3852
Re: Idea of multi-line strings, mantis 35827
« Reply #51 on: December 29, 2020, 11:42:44 pm »
I see, thanks for the clarification.

So must be an intrinsic trim, and another trimIndent that does different things. One is for a single line, and other for multi lines.
« Last Edit: December 30, 2020, 12:09:45 am by lainz »

MarkMLl

  • Hero Member
  • *****
  • Posts: 3269
Re: Idea of multi-line strings, mantis 35827
« Reply #52 on: December 30, 2020, 11:21:53 am »
To use runtime code, like a Trim function, you need to in the implementation block of your function, program, whatever and not in the definition block (where variables, constants, etc. are defined).

Allowing types to have attributes e.g. "is trimmed on assignment" would probably fix this, but unless the language were completely reengineered to be extensible they'd have to be agreed on in advance.

MarkMLl
Turbo Pascal v1 on CCP/M-86, multitasking with LAN and graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

Warfley

  • Hero Member
  • *****
  • Posts: 556
Re: Idea of multi-line strings, mantis 35827
« Reply #53 on: December 30, 2020, 07:04:44 pm »
Allowing types to have attributes e.g. "is trimmed on assignment" would probably fix this, but unless the language were completely reengineered to be extensible they'd have to be agreed on in advance.
Yeah, I mean compiler magic is always a solution that could be implemented, but I think such things are way to specific to justify having custom compiler makros or so for them. A more general approach, used in other languages like Java, is the defining of custom annotations that influence the code generation during compiletime. E.g.
Code: Java  [Select][+][-]
  1. @Getter @Setter
  2. private String myString;
From the Lombok package automatically generates setMyString and getMyString methods. These can be defined in Java, which is executed during compiletime.

Something like this could allow for defining custom attributes that will be executed during compiletime.

Another option would be compiletime functions. C++ allows for constexpr functions, these are functions of whoom all inputs are constants available during compiletime, that will be evaluated during compiletime. A constexpr TrimIndent could there be implemented that way.

But to be honest, Pascal is probably not the kind of language where such features are going to be implemented. While they can be very neat with regards to usability (like the getter and setter example from above), they add a whole new dimension to the language, where the behavior of every line of code can be completely altered with such annotations, which need to be understood by the maintainer in the first place (and looking at some enterprise Java source, these annotations can look like black magic).

Something that might be more interesting would be if runtime code could be used in the definition segment. I think the ugliest part of pascal that always create really bad code is the use of the initialization and finalization segment.
Very often I use this segment to initialize global variables, like loggers or something like this. This means the logger is defined somewhere in the middle of the file, but the initialization code is at the very bottom, often like 500 lines or more away from the definition of the data the code relates to.
I think there could be a usefull alternative, something like:
Code: Pascal  [Select][+][-]
  1. var
  2.   MyLogger: TLogger initialize MyLogger := TLogger.Create(Output) finalize MyLogger.Free;
with a multiline alternative:
Code: Pascal  [Select][+][-]
  1. var
  2.   MyLogger: TLogger initialize
  3.   begin
  4.     SetConsoleOutputCP(DefaultSystemCodePage);
  5.     SetTextCodePage(Output, DefaultSystemCodePage);
  6.     MyLogger := TLogger.Create(Output);
  7.   end
  8.   finalize
  9.     MyLogger.Free;

In that case the trimming could be done with something like that:
Code: Pascal  [Select][+][-]
  1. var
  2.   mls: String initialize mls := 'foo '.Trim;

But this is just an idea I had some time ago because I really hate the way the initialization and finalization segments work currently.

PS: if we only consider runtime code, one way to handle something like this would be a wrapper type:
Code: Pascal  [Select][+][-]
  1.   { TTrimmedString }
  2.  
  3.   TTrimmedString = record
  4.   private
  5.     Data: String;
  6.   public
  7.     class operator :=(const src: String): TTrimmedString;
  8.     class operator :=(const src: TTrimmedString): String;
  9.   end;
  10.  
  11. { TTrimmedString }
  12.  
  13. class operator TTrimmedString.:=(const src: String): TTrimmedString;
  14. begin
  15.   Result.Data:=src.Trim;
  16. end;
  17.  
  18. class operator TTrimmedString.:=(const src: TTrimmedString): String;
  19. begin
  20.   Result := src.Data;
  21. end;
  22.  
  23. var
  24.   s: TTrimmedString;
  25. begin
  26.   s := '42 ';
  27.   Write(StrToInt(s)); // can be used for any string implicetly
  28.   ReadLn;
  29. end.
But again this is restricted to runtime code only
« Last Edit: December 30, 2020, 07:17:36 pm by Warfley »

MarkMLl

  • Hero Member
  • *****
  • Posts: 3269
Re: Idea of multi-line strings, mantis 35827
« Reply #54 on: December 30, 2020, 07:31:19 pm »
Code: Pascal  [Select][+][-]
  1. var
  2.   MyLogger: TLogger initialize MyLogger := TLogger.Create(Output) finalize MyLogger.Free;

It strikes me that that is not a million miles from the deferred code generation currently being used for templates.

But if a language has to do that sort of thing it's possibly time for a "delete all and insert".

MarkMLl
Turbo Pascal v1 on CCP/M-86, multitasking with LAN and graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

PascalDragon

  • Hero Member
  • *****
  • Posts: 3412
  • Compiler Developer
Re: Idea of multi-line strings, mantis 35827
« Reply #55 on: December 31, 2020, 04:24:18 pm »
Another option would be compiletime functions. C++ allows for constexpr functions, these are functions of whoom all inputs are constants available during compiletime, that will be evaluated during compiletime. A constexpr TrimIndent could there be implemented that way.

But to be honest, Pascal is probably not the kind of language where such features are going to be implemented. While they can be very neat with regards to usability (like the getter and setter example from above), they add a whole new dimension to the language, where the behavior of every line of code can be completely altered with such annotations, which need to be understood by the maintainer in the first place (and looking at some enterprise Java source, these annotations can look like black magic).

J. Gareth Moreton is working on a concept called pure functions which is essentially constexpr for Pascal.

Something that might be more interesting would be if runtime code could be used in the definition segment. I think the ugliest part of pascal that always create really bad code is the use of the initialization and finalization segment.

No. With this you're mixing declarations and code, something that we're already against with Delphi's inline variables and this would simply be the other way round.

Warfley

  • Hero Member
  • *****
  • Posts: 556
Re: Idea of multi-line strings, mantis 35827
« Reply #56 on: January 02, 2021, 08:56:15 pm »
No. With this you're mixing declarations and code, something that we're already against with Delphi's inline variables and this would simply be the other way round.
But then the question arises, is a strict distinction between declaration and code a good thing in this circumstance. Because I don't see any value in purism just for purisms sake. Just because in some circumstances this distinction produces better code, does not mean that in all circumstances it does and should be enforced in all circumstances. If it produces worse code, there is no reason to enforce this.

For example with inline variabes, this makes absolutely sense, because when you read code, and you see a variable, and you want to check what it is, having one region where all the variables are declared makes sense. Also inside your function there is usually only 1 region where variables are declared and only one region where the code is written. So you clearly know where you find the variables and where the code is. This is why for example a lot of C coding guidelines say that non loop variables should be declared at the start of the function.

For global variables this line of reasoning does not work, because global variables can be declared anywhere in a document.
You can have this:
Code: Pascal  [Select][+][-]
  1. procedure Foo;
  2. ...
  3. var
  4.   var1: TMyClass;
  5. procedure Bar;
  6. ...
  7. const
  8.   const1 = 'foo';
  9. type
  10.   TFoo = class
  11.   ...
  12.     procedure Foo;
  13.   end;
  14. var
  15.   var2: String;
  16. procedure TFoo.Foo;
  17. ...
  18.  
  19. function GetVar1: TMyClass;
  20. begin
  21.   if not Assigned(var1) then
  22.     var1 := TMyClass.Create;
  23.   Result := Var1;
  24. end;
  25.  
  26. initialization
  27.   var2 := const1;
  28. end.
Here just to find out what var2 and const1 actually is, you need to spot that single line between types and function definitions. Also the initialization does not need to happen in the initialization part, but for example with singletons are usually created when their getter is first called, as shown here with GetVar1.

So if you see a global variable anywhere in the document, you need to scroll all the way down to see if and how it get's initialized, and if you see the usage of a global variable in the initialization or finalization section, you need to search the whole document where it is declared.
This is the exactly the issue that is solved by the distinction of code and declaration on the function level, that is caused by this very same distinction on the unit level.

With the coupeling of inizialization and finalization at the declaration point this would be not an issue. When you see a global variable you instantly see how it is initialized and finalized. Also it solves the dependency issue, because without it you need to initialize and finalize in the correct order if the initialization and finalization depends on other global variables. With the direct initialization the compiler can simply build a dependency graph during compiletime and solve the dependency issue algorithmically without the user having to think about it

J. Gareth Moreton is working on a concept called pure functions which is essentially constexpr for Pascal.
This is great news. With the not so pascallian I meant more like the java like annotations. Because they always look like black magic to me, and I hope something like this never comes to pascal
« Last Edit: January 02, 2021, 09:09:24 pm by Warfley »

Blade

  • Full Member
  • ***
  • Posts: 142
Re: Idea of multi-line strings, mantis 35827
« Reply #57 on: September 18, 2021, 03:46:48 am »
It's more than that.  Using your example and using Akira's multi-line strings, that can be rewritten as:
Code: Pascal  [Select][+][-]
  1. sql := '
  2.         select foo, bar
  3.         from t1
  4.         where foo > bar
  5.        ';
Not only is that easier to read, additions can be made without being encumbered with ' and + thereby lowering the possibility of errors.

I agree with this concept.  What should be avoided is having to add something line by line, versus simply being able to paste some text.  Looks like a matter of just agreeing on something distinct.  I would like to see something like below.

Code: Pascal  [Select][+][-]
  1. sql := '(
  2.         select foo, bar
  3.         from t1
  4.         where foo > bar
  5.         )';
  6.  
« Last Edit: September 18, 2021, 03:48:56 am by Blade »

MarkMLl

  • Hero Member
  • *****
  • Posts: 3269
Re: Idea of multi-line strings, mantis 35827
« Reply #58 on: September 18, 2021, 09:25:57 am »
I agree with this concept.  What should be avoided is having to add something line by line, versus simply being able to paste some text.  Looks like a matter of just agreeing on something distinct.  I would like to see something like below.

I'm somewhat dubious, since generally speaking languages which allow things like "here-documents" do so at a preprocessor stage rather than as an integral part of the syntax.

An alternative would be to leave single-quoted strings alone, since this is the majority usage and checking that strings are properly terminated (i.e. on the same line) is valuable.

Instead, define a double-quoted string as operating on multiple lines, but make := " into a special redefinable operator so that the semantics of the quoted text don't have to be locked-down by the compiler and those used to backslash escapes etc. can use them.

MarkMLl
Turbo Pascal v1 on CCP/M-86, multitasking with LAN and graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

Jurassic Pork

  • Hero Member
  • *****
  • Posts: 1054
Re: Idea of multi-line strings, mantis 35827
« Reply #59 on: September 18, 2021, 02:34:37 pm »
hello,
you can also use the macro editor in the ide with a shortcut to launch the formatting string line function (written in pascalscript) on the selected text.
see demo in attachment (click on the image to see animation).

Friendly, J.P
Jurassic computer : Sinclair ZX81 - Zilog Z80A à 3,25 MHz - RAM 1 Ko - ROM 8 Ko

 

TinyPortal © 2005-2018