In C# there is this using construct:
using(Bitmap image = this.OpenImage("filename.bmp")) {
image.Name = "foo";
//use image like image.sth
}
which is translated to:
{
Bitmap image = this.OpenImage("filename.bmp");
try {
image.Name = "foo";
//use image like image.sth
}
finally {
IDisposable obj = image as IDisposable;
if(obj != null)
obj.Dispose();
}
}
I know that the with statement is different, but it can be
improved so that you can declare things in it like an using
statement:
with(Bitmap image = open("filename.bmp")) {
name = "foo";
//no need to specify image.sth
}
or even a more implicit one:
with(open("filename.bmp")) {
//ditto
}
And both of the above to be translated to:
{
Bitmap temp = expression;
//use bitmap
delete temp; // Call destructor/finallizer of the object
//I'm not sure if delete was the proper way to call a
destructor in D
}
And I hope you got the point. Tell me what you think.

just declare variable as scope, and ti will be destructed as son
as function exits.
void foo ()
{
scope obj = new Object;
} // obj will be destructed here
you can also use it together with anonymous scope (same as c#)
more generally, there is a "scope" statement
http://dlang.org/exception-safe.html that can be used where
normally try/finally (without catch) would be used, to achieve
cleaner code.

That usage of scope has being deprecated...
For Walter: I suggest dmd to give a deprecation message where you
use one of the many deprecated D features, like scope classes,
floating point comparison operators, and so on. Otherwise D
programmers will use those featueres in their code today, and
when those feature become deprecated, those people will become
angry because of too much code to modify/fix.
Bye,
bearophile

That usage of scope has being deprecated...
For Walter: I suggest dmd to give a deprecation message where
you use one of the many deprecated D features, like scope
classes, floating point comparison operators, and so on.
Otherwise D programmers will use those featueres in their code
today, and when those feature become deprecated, those people
will become angry because of too much code to modify/fix.
Bye,
bearophile

It's not a feature I've ever had the need for so far, but what is
the replacement for scope?

cool, thanks. Any particular catches a user should be aware of?
Other than leaking a reference of course.

Quality of implementation of course :) I have not used it much
personally and don't know how good it is, but it creates wrapper
struct and there can be issues with forwarding methods/operators
to wrapped class for some weird corner cases.

That usage of scope has being deprecated...
For Walter: I suggest dmd to give a deprecation message where
you use one of the many deprecated D features, like scope
classes, floating point comparison operators, and so on.
Otherwise D programmers will use those featueres in their code
today, and when those feature become deprecated, those people
will become angry because of too much code to modify/fix.
Bye,
bearophile

Interesting. I didn't knew that it is being deprecated. So my
suggestion could actually be a good replacement of scope.?

just declare variable as scope, and ti will be destructed as
son as function exits.
void foo ()
{
scope obj = new Object;
} // obj will be destructed here
you can also use it together with anonymous scope (same as c#)
more generally, there is a "scope" statement
http://dlang.org/exception-safe.html that can be used where
normally try/finally (without catch) would be used, to achieve
cleaner code.

I think this shoudl be allowed simply for consistency with this:
if(auto a = getfoo()) { use a }

This is good. I think it should too.
But what Bosak proposes is that when "with" statements ends, the
object should be destructed, which is large violation what with
statements if for. Not mentioning breaking all the existing
code...

But what Bosak proposes is that when "with" statements ends,
the object should be destructed

That would happen if the object is a struct, or wrapped in a
struct, since it would go out of scope at the end of the with and
call its destructor then.
So then you could just go
import std.typecons;
with(auto a = Scoped!T()) { ... }
and the Scoped destructor does the deleting.

But what Bosak proposes is that when "with" statements ends,
the object should be destructed

That would happen if the object is a struct, or wrapped in a
struct, since it would go out of scope at the end of the with
and call its destructor then.
So then you could just go
import std.typecons;
with(auto a = Scoped!T()) { ... }
and the Scoped destructor does the deleting.

Exactly. My idea is to add third use case of with. Not there are
2 ways to use with(of witch I know):
1) Declare something and use with to not repeat yourself:
auto foo = new Foo;
with(foo) {
name = "bar"; //foo.name = "bar";
}
In this case it is only used for object construction and setup.
And the with statement doesn't destruct the object or anything
like that.
2) Used with types
struct Foo {
static int bar = 2;
}
with(Foo) {
bar++; //Foo.bar++;
}
Again with doesn't destruct or anything
All of the above are currently available, but I want a third case
to be added:
3) Used when you declare something in the with statement with
scope only in the with statement
with(Foo foo = new Foo) {
name = "bar";
}
After that foo's destructor gets called and since foo was in the
scope of with it goes out of scope and no references are made to
foo. There should be a constraint that you cannot take the
address of foo in the with statement(i.e assign a global to foo)
3.1) Or used with rvalues??
int[] values;
with(new Foo) {
name = "bar";
values = getData(); //foo.getData()
}
//use values taken from foo
I think that in case 3.1 it is very intuitive for using resources
like files. Instead of writing something like:
string text;
auto file = open("myfile.txt", "r");
text = t.readlines();
file.close();
You can write this:
string text;
with(open("myfile.txt", "r")) { //no need to declare variable
text = readlines(); //just use the file to get the data
}//with automaticaly calls close() on the file, even if exception
got thrown
And if the exception got thrown in the declaration of the with
block, then the with block doesn't execute. For example in the
above code if the file didn't exist, an exception would be thrown
from open and no variable would be created.
I hope that I have made my suggestion more clear.

What you propose is rather unwelcome for classes (destruction of
GC-managed objects is non-deterministic) and closest thing for
IDisposable D has is "destroy" which is not something that is
expected to be called silently.
However, I do like proposed extension of `with` syntax to allow
declarations. It perfectly matches `if` and allows to emulate C#
behavior via `scoped`. That will improve language consistency.

What you propose is rather unwelcome for classes (destruction
of GC-managed objects is non-deterministic) and closest thing
for IDisposable D has is "destroy" which is not something that
is expected to be called silently.
However, I do like proposed extension of `with` syntax to allow
declarations. It perfectly matches `if` and allows to emulate
C# behavior via `scoped`. That will improve language
consistency.

Oh yes using scoped to achieve that is a good solution. So if I
write
with(File file = open("filename"))
{
//setup file
type = Types.Text; //etc.
}
string text = file.read(); //file still usable after with, but
explicitly
And if I write the scoped version:
with(scoped!File file = open("filename"))
{
//retrieve data from file or whatever
}
//file is out of scope and is not usable after
You say that D's destroy is not like C#'s IDisposable. Then why
doesn't D then declare that kind of interface:
interface Disposable {
void dispose();
}
And include it in the object module? That way some classes can
implement this dispose method that will just dispose any used
resources(and not to replace destructor's role). It is a very
small(but core) change that is even not connected with the
compiler, but only with phobos.
For example std file structs can just implement the interface
like this:
//...in File class/struct that implements Disposable
void dispose() {
this.close();
}
And if you don't like the idea of adding an interface to the core
module, then the same thing could be achieved if a special
opDispose function is declared. This is a more D-way of doing it,
since there exist opApply that is used only in the foreach
construct and the opCall that is used to call classes like
functions.
And then the with implementation is mostly straightforward.
Depending on weather the declared variable is scoped or not, with
behaves differently. If it is scoped it first checks if the
object has dispose/opDispose method in it calls it and then
destroys(or whatever the compiler does to scoped variables) it.
And if it is not scoped then it doesn't dispose it and it acts
just like with acts now(just the ability to declare the variable
right in the with statement).
That way you explicitly specify that the variable is scoped and
you know that it will be destroyed when it goes out of scope. In
addition to that it dipposes "savely".
Maybe opDispose shouldn't be only used in with statement, but
EVERYWHERE a scoped variable is declared? Here is a more complete
example:
class Resource { //can be any resource from files to streams to
anything
Resource[] used;
void opDispose() {
writeln("Resource disposed!");
//in opDispose the resource should dispose all it's
resources too
foreach(res; used)
res.opDispose();
}
static Resource open(string name){
return new Resource;
}
}
with(auto resource = Resource.open("res1")){
//set properties of resource and call setup/init functions
}
resource.doStuff(); //use resource later too
resource.opDispose(); //you can manually dispose it
//or a scoped variant:
string[] data;
with(scoped!Resource res = Resource.open("res2")){
data = res.getData();
}//res gets out of scope and opDispose is called
if(cond){
scoped!Resource res = Resource.open("res3");
//do sth with res
}//get out of scope opDispose gets called and res gets destroyed
I think this dispose thing should be added to D, because it is a
very common practice in C#(and not only). In the book I used to
learn C# long ago I remember how they sayed like 100 of times:
"If you use an object that implements IDisposable ALLWAYS use it
in an using statement". It is not a strange or not-intuitive
feature. In fact it can make the "scoped" variables idea more
popular. And instead of explicitly adding an using statement you
just declare your variable as scoped and the compiler takes care
of calling it's dispose automatically when it gets out of scope.
I think that's everything for now.

You say that D's destroy is not like C#'s IDisposable.Then why
doesn't D then declare that kind of interface:
interface Disposable {
void dispose();
}

It _is_ similar but not exact match. 2 key differences:
1) destroy works on variety of types, not only classes
2) it puts the object into some invalid state
But you can still use class destructor instead of `dispose()`
method.
But destroy() is considered a power tool that should be used only
when absolutely needed. The very necessity to deterministically
call some method opposes the concept of garbage collection - it
is a sign of bad design and clear indicator that one should do a
proper RAII here. I really think D approach here is much cleaner
than C# one.

You say that D's destroy is not like C#'s IDisposable.Then why
doesn't D then declare that kind of interface:
interface Disposable {
void dispose();
}

It _is_ similar but not exact match. 2 key differences:
1) destroy works on variety of types, not only classes
2) it puts the object into some invalid state
But you can still use class destructor instead of `dispose()`
method.
But destroy() is considered a power tool that should be used
only when absolutely needed. The very necessity to
deterministically call some method opposes the concept of
garbage collection - it is a sign of bad design and clear
indicator that one should do a proper RAII here. I really think
D approach here is much cleaner than C# one.

Well I don't know much stuff about GC and internals and if you
think it is not a good design concept, ok I'm fine with it. I
don't "miss" C#'s using statement or IDisposable. I was just
giving a suggestion that would be discussed and considered with
the community.
At least this with(declaration) syntax might make it into the
language. And probably use the more "strange" one, where you only
give it an rvalue:
with(new Foo) {
name = "Foo"; //same as temp.name
calc(); //same as temp.calc()
writeln(); //and even maybe this to be translated to
temp.writeln() and then to writeln(temp) ?
}
Well that was everything I had to say about with, using, and
dispose. I'm glad that there was a discussion going.

I think this dispose thing should be added to D, because it is a very
common practice in C#(and not only). In the book I used to learn C#
long ago I remember how they sayed like 100 of times: "If you use an
object that implements IDisposable ALLWAYS use it in an using
statement". It is not a strange or not-intuitive feature. In fact it
can make the "scoped" variables idea more popular. And instead of
explicitly adding an using statement you just declare your variable as
scoped and the compiler takes care of calling it's dispose
automatically when it gets out of scope.

But what Bosak proposes is that when "with" statements ends, the
object should be destructed

That would happen if the object is a struct, or wrapped in a struct,
since it would go out of scope at the end of the with and call its
destructor then.
So then you could just go
import std.typecons;
with(auto a = Scoped!T()) { ... }
and the Scoped destructor does the deleting.

Exactly. My idea is to add third use case of with. Not there are 2 ways
to use with(of witch I know):
1) Declare something and use with to not repeat yourself:
auto foo = new Foo;
with(foo) {
name = "bar"; //foo.name = "bar";
}
In this case it is only used for object construction and setup. And the
with statement doesn't destruct the object or anything like that.
2) Used with types
struct Foo {
static int bar = 2;
}
with(Foo) {
bar++; //Foo.bar++;
}
Again with doesn't destruct or anything
All of the above are currently available, but I want a third case to be
added:
3) Used when you declare something in the with statement with scope only
in the with statement
with(Foo foo = new Foo) {
name = "bar";
}
After that foo's destructor gets called and since foo was in the scope
of with it goes out of scope and no references are made to foo. There
should be a constraint that you cannot take the address of foo in the
with statement(i.e assign a global to foo)
3.1) Or used with rvalues??
int[] values;
with(new Foo) {
name = "bar";
values = getData(); //foo.getData()
}
//use values taken from foo
I think that in case 3.1 it is very intuitive for using resources like
files. Instead of writing something like:
string text;
auto file = open("myfile.txt", "r");
text = t.readlines();
file.close();
You can write this:
string text;
with(open("myfile.txt", "r")) { //no need to declare variable
text = readlines(); //just use the file to get the data
}//with automaticaly calls close() on the file, even if exception got
thrown
And if the exception got thrown in the declaration of the with block,
then the with block doesn't execute. For example in the above code if
the file didn't exist, an exception would be thrown from open and no
variable would be created.
I hope that I have made my suggestion more clear.

IMO, using statements in C# are annoying. They make otherwise linear
code much harder to read. The *idea* behind them makes total sense, but
I dislike the implementation. Instead of writing this:
public string[] GetLines(string name)
{
string result;
using (var file = new File(name))
{
result = file.ReadText();
}
return result.split('\n');
}
...I would very much like to write this:
public string[] GetLines(string name)
{
autodispose var file = new File(name1);
string result = file.ReadText(); //file disposed after this line,
since it's the last place it's used
return result.split('\n');
}
Another problem with C#'s using (){} is that it doesn't easily scale
from single-method use to object-wide use. For example, would you want
to add "using" statements to every single method in a controller just
because all of them use the same database object?

In C# there is this using construct:
using(Bitmap image = this.OpenImage("filename.bmp")) {
image.Name = "foo";
//use image like image.sth
}
which is translated to:
{
Bitmap image = this.OpenImage("filename.bmp");
try {
image.Name = "foo";
//use image like image.sth
}
finally {
IDisposable obj = image as IDisposable;
if(obj != null)
obj.Dispose();
}
}
I know that the with statement is different, but it can be improved so
that you can declare things in it like an using statement:
with(Bitmap image = open("filename.bmp")) {
name = "foo";
//no need to specify image.sth
}
or even a more implicit one:
with(open("filename.bmp")) {
//ditto
}
And both of the above to be translated to:
{
Bitmap temp = expression;
//use bitmap
delete temp; // Call destructor/finallizer of the object
//I'm not sure if delete was the proper way to call a destructor in D
}
And I hope you got the point. Tell me what you think.