Forum > General

Bounded With

(1/15) > >>

AlexK:
One thing that's missing in FPC is object protocols, I mean like with statement in Python.
The with statement already exists in FPC, but it's very simple, syntactic convenience.


--- Code: Python  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---# open returns a "context manager" object that implements methods __enter__ and __exit__, a protocol.with open("file.txt") as f:    data = f.read()    print(data) 
1) with statement calls context manager's __enter__ in order to init some context, if optional "as f" is present, it is assigned to what __enter__ returns.
2) Execute statements in a block
3) call CM's __exit__ to close context. If block raised exception, this method receives exception in its arguments.


--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---// C# has a "Using" statement, but it merely calls a destructor of used object in the end.var TheCustomer: Customer; Using TheCustomer to obj do  // "to obj" is optional    begin    // do something in a created context here    obj.SomeMethod; // obj is returned by __enter__    // compiler calls obj.Destroy here    end; // Where:Customer = class     // implements "context manager" protocol for a Using statement    procedure __enter__;    function __enter__: Sometype; // returned value assigned "to obj" above    procedure __exit__;    procedure __rescue__(ex: Exception);end; 

taazz:

--- Quote from: AlexK on July 09, 2017, 05:38:04 pm ---One thing that's missing in FPC is object protocols, I mean like with statement in Python.
The with statement already exists in FPC, but it's very simple, syntactic convenience.


--- Code: Python  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---# open returns a "context manager" object that implements methods __enter__ and __exit__, a protocol.with open("file.txt") as f:    data = f.read()    print(data) 
1) with statement calls context manager's __enter__ in order to init some context, if optional "as f" is present, it is assigned to what __enter__ returns.
2) Execute statements in a block
3) call CM's __exit__ to close context. If block raised exception, this method receives exception in its arguments.


--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---// C# has a "Using" statement, but it only calls a destructor of used object in the end.var TheCustomer: Customer; Using TheCustomer to obj do  // "to obj" is optional    begin    // do something in a created context here    obj.SomeMethod; // obj is returned by __enter__    // compiler calls obj.Destroy here    end; // Given:Customer = class     // implements "context manager" protocol for a Using statement    procedure __enter__;    function __enter__: Sometype; // returned value assigned "to obj" above    procedure __exit__;    procedure __rescue__(ex: Exception);end; 
--- End quote ---
most of the time they are not needed in pascal eg

--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---function Open(const aFilename:TFilename):TFileStream;begin   result := tfilestream.create(afilename,fmopenreadwriteorfmshareexclusive);end;procedure domytheng;begin  with open("MyDataFile.Dat") do   try    read(Data, size);  finally     free  end;end; but I agree it seems a bit more care free with out all that try/finally stuff ofcourse it shifts the responsibility for a proper destruction to the component writer instead it does not go away and I do not think that any component writer would like to take on more than it is absolutely necessary (my included). Look what happened with the build in for in support do you know many 3rd party controls that have build support?

AlexK:

--- Quote from: taazz on July 09, 2017, 05:55:42 pm ---most of the time they are not needed in pascal eg

--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---function Open(const aFilename:TFilename):TFileStream;begin   result := tfilestream.create(afilename,fmopenreadwriteorfmshareexclusive);end;procedure domytheng;begin  with open("MyDataFile.Dat") do   try    read(Data, size);  finally     free  end;end; but I agree it seems a bit more care free with out all that try/finally stuff ofcourse it shifts the responsibility for a proper destruction to the component writer instead it does not go away and I do not think that any component writer would like to take on more than it is absolutely necessary (my included). Look what happened with the build in for in support do you know many 3rd party controls that have build support?

--- End quote ---

Imagine a complex system where you have to create or use some context before calling some of API functions.
You'll create similar try/finally blocks in different parts of your code. That'll take a lot of line, lower readability and maintainability.
What if you have 2 or more logically unrelated contexts that you have to create or use in one function? All they would go into your one try/finally block.


--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---Using TheCustomer, SomeOtherObject to name1, OtherHelperContext to name2 do    begin    // here needed environment(context) is ensured by these "context managers" above    name1.someMethod;    name2.interestingMethod;    end; 
All objects in a using statement must implement intrinsic interface:


--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---IContextManager = Interface  // the actual type determined at compilation in class implementation  // it can be implemented as a procedure in which case "to name1" suffix will not be allowed  intrinsic __enter__: DeferredType; // RETURNED VALUE ASSIGNED to "name1", "name2" above  procedure __exit__;  procedure __rescue__(ex: Exception); // called when "using" statement raises an exceptionend; 
So, that construction somehow partly replaces RAII of C++, gives some "design by contract" abilities.
Also it can be used to program transactions with rollbacks.
Or using draw procedures in some graphic contexts, or action procedures in a game.

To repeat:
1) Compiler inserts calls to __enter__ implementation when compiling "using" statement, before begin..end, so to speak.
__enter__ implementations can return type that are assigned to name in "using" statement clauses.
2) At the end compiler inserts calls to __exit__ procedures.

If exception occurs, it should call __resque__ procedures.

bylaardt:

--- Quote from: AlexK on July 09, 2017, 05:38:04 pm ---One thing that's missing in FPC is object protocols, I mean like with statement in Python.
The with statement already exists in FPC, but it's very simple, syntactic convenience.


--- Code: Python  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---# open returns a "context manager" object that implements methods __enter__ and __exit__, a protocol.with open("file.txt") as f:    data = f.read()    print(data) 

--- End quote ---

What's wrong with

--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---f:=open("file.txt")?

AlexK:

--- Quote from: bylaardt on July 10, 2017, 04:36:27 am ---What's wrong with

--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---f:=open("file.txt")?

--- End quote ---

Sorry, but you didn't bother to understand my point. It wasn't only about some techniques of opening a file.
I tend to think the task would require writing another compiler without backward compatibility.

For example, an interface that can declare only the name of a procedural type, without actual types:

--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---IContextManager = Interface  deferred __enter__: FuncOrProcType;  procedure __exit__;  procedure __rescue__(ex: Exception);end; 
^^Here, the type of __enter__ would be determined by a compiler at an implementation site, in a class. Only the name is enforced by the interface, this opens an ability to create "object protocols".
__enter__ can be implemented as a function or procedure, with any arguments and return types.

Such interface leads to rich semantics that use those required methods in a compiler:

--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---Using TheCustomer, SomeOtherObject to name1, OtherHelperContext to name2 do    begin    // here needed environment(context) is ensured by these "context managers" above    name1.someMethod;    name2.interestingMethod;    end; 
A compiler would insert calls to __enter__ methods for each object in "TheCustomer, SomeOtherObject to name1, OtherHelperContext to name2", where name1 and name2 would require that __enter__ is implemented as a function rather than a procedure.
On exit for a using statement compiler would insert calls to __exit__ methods.

More organized memory management.

--- Quote ---So, that construction somehow partly replaces RAII of C++, gives some "design by contract" abilities.
Also it can be used to program transactions with rollbacks.
Or using draw procedures in some graphic contexts, or action procedures in a game.

--- End quote ---

Navigation

[0] Message Index

[#] Next page

Go to full version