Re: User defined type and foreach

2024-01-25 Thread Jim Balter via Digitalmars-d-learn
On Friday, 19 January 2024 at 18:13:55 UTC, Jonathan M Davis 
wrote:
On Friday, January 19, 2024 3:49:29 AM MST Jim Balter via 
Digitalmars-d-learn wrote:

On Friday, 17 November 2017 at 17:55:30 UTC, Jonathan M Davis

wrote:
> When you have
>
> foreach(e; range)
>
> it gets lowered to something like
>
> for(auto r = range; !r.empty; r.popFront())
> {
>
> auto e = r.front;
>
> }
>
> So, the range is copied when you use it in a foreach.

Indeed, and the language spec says so, but this is quite wrong 
as

it violates the specification and design of ranges ... only
forward ranges are copyable and only via their `save` 
function. I
have an input range that can only be iterated once; if you try 
to
do so again it's empty ... but the foreach implementation 
breaks

that. You should be able to break out of the foreach statement,
then run it again (or another foreach) and it should continue
from where it left off, but copying breaks that. I need to know
how many elements of my range were consumed; copying breaks 
that.

I got around this by having a pointer to my state so only the
pointer gets copied. I would also note that tutorials such as 
Ali
Çehreli's "Programming in D – Tutorial and Reference" are 
unaware

of this breakage:

"
Those three member functions must be named as empty, popFront,
and front, respectively. The code that is generated by the
compiler calls those functions:

 for ( ; !myObject.empty(); myObject.popFront()) {

 auto element = myObject.front();

 // ... expressions ...
 }
"




"No spec is being violated, and the behavior is completely 
expected."


This is not true, and your over-long response that is a lecture I 
didn't ask for and don't need misses my point and is largely 
irrelevant. The specification of ranges, which is independent of 
the D language, says that the way to copy a range is to use 
save(). Input ranges cannot be copied or restarted; that's the 
whole point of the difference between input ranges and forward 
ranges. You go on and on about the semantics of copying, which 
has nothing to do with what I wrote, which is that `foreach` 
copies when it shouldn't; the semantics of copying is not 
relevant to *not copying*. Input ranges are one-shots; they yield 
values once and that's it. `foreach` should have been implemented 
to call `save()` when that is available (when it is a forward 
range), and to do no copying when it is not available. Had that 
been done, then people wouldn't have written a bunch of ranges 
with missing save() functions that are reusable when they 
shouldn't be due to `foreach` making a copy, making `foreach` 
impossible to fix now.


"Basic input ranges cannot be value types (otherwise, they could 
implement save)"


This is not true, and again misses the point. My input range, the 
one I described in my original message, is a value type (a 
struct) which, when passed to functions, is passed by reference. 
It doesn't implement save because it's an input range, not a 
forward range. It's not supposed to be copied or restartable 
because it's an input range, not a forward range. Copying it has 
the wrong consequences because calling popFront on a copy doesn't 
advance the one-shot input range. It would work just fine if 
`foreach` didn't copy it. It works fine if I use it without 
`foreach`, e.g., if I use it in a for loop like in Ali's book:



   for ( ; !myObject.empty(); myObject.popFront()) {

 auto element = myObject.front();

 // ... expressions ...
   }


That works just fine with an input range, which is a range that 
is not restartable.
The only thing that doesn't work with my input range is 
`foreach`, which copies the input range--which, by the 
specification of input ranges, was never intended.


I managed to make it usable with a `foreach` loop by having the 
struct only store a pointer to its state so the `foreach` copy is 
harmless, in effect turning my value type range into a reference 
type and introducing unnecessary overhead.


Re: Error "Outer Function Context is Needed" when class declared in unittest

2024-01-21 Thread Jim Balter via Digitalmars-d-learn

On Thursday, 5 January 2023 at 13:47:24 UTC, Adam D Ruppe wrote:

On Thursday, 5 January 2023 at 13:27:23 UTC, Vijay Nayar wrote:
Why is this error only found when declaring a class in the 
unittest?


A unittest is just a special function, it can run code and have 
local variables.


classes and structs declared inside it have access to those 
local contexts, which it calls the outer function context.


Make the outer class `static` too to lift it out of this and 
your error should go away.


Why doesn't the compiler just create the instance with the 
correct context pointer? And if it won't, how does one provide 
it? I have a template function which creates new instances of a 
type that is an argument to the template, and it fails miserably 
when the type is a nested class. How do I create such instances?


Dlang is supposed to be "turtles all the way down", but I keep 
finding that to be far from reality.


Re: User defined type and foreach

2024-01-19 Thread Jim Balter via Digitalmars-d-learn
On Friday, 17 November 2017 at 17:55:30 UTC, Jonathan M Davis 
wrote:



When you have

foreach(e; range)

it gets lowered to something like

for(auto r = range; !r.empty; r.popFront())
{
auto e = r.front;
}

So, the range is copied when you use it in a foreach.


Indeed, and the language spec says so, but this is quite wrong as 
it violates the specification and design of ranges ... only 
forward ranges are copyable and only via their `save` function. I 
have an input range that can only be iterated once; if you try to 
do so again it's empty ... but the foreach implementation breaks 
that. You should be able to break out of the foreach statement, 
then run it again (or another foreach) and it should continue 
from where it left off, but copying breaks that. I need to know 
how many elements of my range were consumed; copying breaks that. 
I got around this by having a pointer to my state so only the 
pointer gets copied. I would also note that tutorials such as Ali 
Çehreli's "Programming in D – Tutorial and Reference" are unaware 
of this breakage:


"
Those three member functions must be named as empty, popFront, 
and front, respectively. The code that is generated by the 
compiler calls those functions:


for ( ; !myObject.empty(); myObject.popFront()) {

auto element = myObject.front();

// ... expressions ...
}
"




Re: What's the proper way to add a local file dependence to dub?

2024-01-06 Thread Jim Balter via Digitalmars-d-learn

On Monday, 12 March 2018 at 10:20:20 UTC, Seb wrote:

On Sunday, 4 March 2018 at 16:46:56 UTC, Marc wrote:

then copy it to sources folder?

let's say I have a small library folder at C:\mylibrary\D 
where I want to use dir.d from it. How do I add that file 
dependence to dub? But I do not want to that file be passed 
directly to dmd, I want to that file be copied to 
application's source folder (so it's easy to distribuite, with 
the dependences together as possible) then compiled. So, what 
I want to some extension is dub work with loca files.
Is this possible to do solely with dub? I know I can easily 
write a script to run before dub which copies the dependence 
files from C:\mylibrary to application's source but I'm 
looking for a more elegant
 approach as possible; I'm afraid of rewriting a makefile-like 
soon (I find cmake/make/makefiles just ugly).


You can also add a simple dub.sdl to your local files and then 
use `dub add-local` to add the package to your dub environment.
Dub will only rebuild the dependency on your local files if 
they changed (or you use a different compiler / build settings).


Why is there no documentation for this? The dub documentation 
should have a filesystem layout page, with examples of how to 
structure local libraries, how to register them, how to add them 
to projects. AFAICT no such documentation exists. I've tried to 
follow the structure of libraries I've loaded into dub's packages 
directory, but it seems to treat local packages differently. And 
dub add-package is useless ... for one thing, it *overwrites* 
local-packages.json rather than adding to it.




Re: Are properties mature enough?

2018-08-21 Thread Jim Balter via Digitalmars-d-learn

On Monday, 20 August 2018 at 00:49:02 UTC, Jonathan M Davis wrote:
On Sunday, August 19, 2018 12:32:17 PM MDT QueenSvetlana via 
Digitalmars-d- learn wrote:

In the D Style Guide, it says:

Properties
https://dlang.org/dstyle.html#properties

Functions should be property functions whenever appropriate. 
In particular, getters and setters should generally be avoided 
in favor of property functions. And in general, whereas 
functions should be verbs, properties should be nouns, just 
like if they were member variables. Getter properties should 
not alter state.


In the Properties function section, it says:

https://dlang.org/spec/function.html#property-functions

WARNING: The definition and usefulness of property functions 
is being reviewed, and the implementation is currently 
incomplete. Using property functions is not recommended until 
the definition is more certain and implementation more mature.


So which is it?


Feel free to use @property or not, but the main point in the 
style guide is about naming functions, not about @property. The 
idea is that functions that wrap or emulate variables should 
act like variables themselves. So, they should be named as if 
they were variables and syntactically used as if they were 
variables rather than prepending their names with get or set 
and calling them as functions. e.g.


struct S
{
int prop() { return _prop; }
int prop(int val) { return _prop = prop; }

private int _prop;
}

with

auto r = s.prop;
s.prop = 42;

instead of

struct S
{
int getProp() { return _prop; }
int setProp(int val) { return _prop = prop; }

private int _prop;
}


auto r = s.getProp();
s.setProp(42).

Marking property functions with @property is an extremely 
popular thing to do, but all it really does at this point is 
document that the programmer intends for it to be used as a 
property rather than enforce anything.


IMHO, the spec words that bit too strongly, and it should be 
fixed. That bit got added recently, because one of the devs 
didn't understand the @property situation, and when he found 
out what it was, he felt that the spec needed to be clarified 
about it so that folks didn't think that it was what the spec 
was claiming, but clearly, he's just confused matters in a 
different way.


Here's the deal. Using the property syntax with functions 
really has nothing to do with @property. It's just based on the 
signature that a function has. If it's a free function, and it 
has a return value but no arguments, without using UFCS, it can 
be used as a getter


int prop();

auto r = prop;

If it has a single argument, or it returns by ref, then it can 
be used as a setter.


ref int prop();
int prop(int);
void prop(int);

all work with

prop = 42;

though the first two can also be used in chained assignment 
operations, since they also return a value, whereas the third 
can't be. e.g.


auto foo = prop = 19;

works with the first two but not the third.

All of the same signatures as member functions also work in the 
same way except that you then get


auto r = obj.prop;

for the getter and

obj.prop = 42;

for the setter. And if they're free functions, and you want to 
use them with UFCS, then they each need one more parameter. e.g.


int prop(MyObj);

auto r = obj.prop;

for the getter and

ref int prop(MyObj);
int prop(MyObj, int);
void prop(MyObj, int);

obj.prop = 42;

for the setter. All of this works regardless of anything to do 
with @property and has had since well before @property existed 
(well, aside from using it with UFCS, since UFCS came later). 
However, a number of folks thought that it was too messy to 
allow any old function with the right set of parameters to be 
used with the property syntax rather than requiring that it be 
part of the API that it be a property function. Probably the 
most egregious case is that something like


writeln = 42;

works just fine, and writeln is clearly a function, not a 
function emulating a variable (which is what a property 
function is supposed to be). So, to improve the situation, 
@property was proposed.


The idea was that functions marked with @property and the 
correct number of parameters would work as property functions 
and that they would _have_ to use the property syntax when 
being used, whereas functions that weren't marked with 
@property were not allowed to use the property syntax. The 
ad-hoc nature of the whole thing then goes away, and stuff like


writeln = 42;

is then illegal. It also fixes the problem where the function 
returns a callable (e.g. a delegate or a functor). If you have 
the function foo, and it returns a callable, as long as it's 
legal to call the function with the property syntax - foo - or 
without - foo() - there's no way to distinguish when the 
callable that's returned by the function should be called. If 
foo is treated as a property, then foo() would call the 
callable that 

Re: ushort + ushort = int?

2018-08-21 Thread Jim Balter via Digitalmars-d-learn

On Monday, 20 August 2018 at 08:34:56 UTC, Andrey wrote:

Hello,
Here is a code that you can execute using online compiler 
https://run.dlang.io/:



import std.stdio;
void main()
{
   ushort first = 5;
   ushort second = 1000;

   ushort result = first + second;

   writeln(result);
}


I hae this error:
onlineapp.d(7): Error: cannot implicitly convert expression 
cast(int)first + cast(int)second of type int to ushort


Why they are "int" when I declared them as "ushort"???
ushort + ushort = ushort, not int.

In C++ there aren't any such issues...


Only if you make the mistake of compiling without warnings. 
Otherwise, the C++ compiler will warn that you're converting an 
int to a ushort.


Re: Auto keyword and when to use it

2018-08-21 Thread Jim Balter via Digitalmars-d-learn

On Tuesday, 21 August 2018 at 18:18:25 UTC, QueenSvetlana wrote:

On Tuesday, 21 August 2018 at 16:15:32 UTC, XavierAP wrote:

Only if someone
likes "Type x = new Type()" instead of "auto x = new Type()" I 
would say they're clearly wrong.


As you stated it's up to the programmer to decided. I'm in 
favor of Type x = new Type()


There is nothing to recommend such redundancy; don't do it.

because when it comes to constructing a class it usually means 
more code to verify the types


Type inference doesn't require more code.


for example:


Your example has no bearing on any of the above ... it's not an 
example of it.




class Person {
  auto firstName;
  auto lastName;

  // constuctor to set first and last names

}


That code is meaningless and isn't legal. You need to either 
provide explicit types, or they need to be inferable from the 
type of the initializer.


The compiler doesn't know know what firstName or lastName is 
supposed to be and a programmer might make the obvious 
assumption and use them as strings.


The programmer can't make any assumption because the code is not 
remotely legal.


Doing this also means you have reject any type that isn't a 
string which means a private function to check the type that 
was pass to the constructor before initializing it. Where as if 
you declared it as a string to start of with, all you have to 
ensure is that it's not blank or contain illegal characters.


This is all incoherent. D is a statically typed language.

As the answer stated above doing what I showed in my example 
isn't allowed and this is where Python gets frustrating, 
because at any point the types could change. They introduced 
type hints, but it's not enforced, it just makes it more 
readable, you still have to write code to ensure the proper 
types were passed.


Python is not statically typed; D is. Why are you talking about 
Python? You asked whether D's auto is like C#'s var ... it is, 
but it doesn't have C#'s pointless restriction of not being 
allowed for non-local declarations.




Re: Disabling struct destructor illegal?

2018-07-20 Thread Jim Balter via Digitalmars-d-learn

On Thursday, 19 July 2018 at 10:04:34 UTC, RazvanN wrote:

On Thursday, 19 July 2018 at 09:50:32 UTC, Jim Balter wrote:

On Thursday, 19 July 2018 at 08:50:15 UTC, RazvanN wrote:

struct A
{
int a;
@disable ~this() {}
}

void main()
{
A a = A(2);
}

Currently, this code yields:

Error: destructor `A.~this` cannot be used because it is 
annotated with @disable


I was expecting that disabling the destructor would make it 
as if the struct does not have a destructor


Why? That's not the semantics of @disable. And why would you 
want that? What are you actually trying to achieve?


I just don't understand why you would ever mark the destructor 
of a struct with @disable. When is that useful?


I don't know, but that doesn't mean there's no possible reason to.


If it's not,


We haven't established that it's never useful. When you pose a 
conditional like that, it's a logical mistake to just assume that 
the condition is met.



why not just forbit it?


Because the compiler shouldn't be littered with pointless special 
case restrictions that have to be maintained and might interfere 
with a valid use case that you haven't thought of. The fact is 
that you disabled the destructor, then invoked the destructor, 
and got a clear, informative error at the point of invocation, 
rather than at the @disable. This is, IMO, a cleaner, better 
design than the one you're asking for.


And it's not true that you "just" don't understand why one would 
ever @disable the destructor ... in your original post you asked 
"why not make it illegal to disable the destructor if disabling 
it will surely result in errors wherever the struct is used" -- 
it was pointed out that it *doesn't* "surely result in errors 
wherever the struct is used" -- it only results in an error if 
the destructor is invoked, exactly as one would expect. In your 
original post you claimed "The only situation where the code will 
compile is A is never used directly" -- it was pointed out that 
this isn't true, as your own example showed. In your original 
post you said that it was confusing that code that you had just 
erroneously stated wouldn't compile does compile, and it was 
pointed out that there's no reason why it shouldn't compile and 
there's no apparent reason to find it confusing. In your original 
post you asked if that's a bug, and it has been pointed out that 
it's not a bug. I hope everything is clear now and all your 
questions have been answered.




Re: Disabling struct destructor illegal?

2018-07-19 Thread Jim Balter via Digitalmars-d-learn

On Thursday, 19 July 2018 at 08:50:15 UTC, RazvanN wrote:

struct A
{
int a;
@disable ~this() {}
}

void main()
{
A a = A(2);
}

Currently, this code yields:

Error: destructor `A.~this` cannot be used because it is 
annotated with @disable


I was expecting that disabling the destructor would make it as 
if the struct does not have a destructor


Why? That's not the semantics of @disable. And why would you want 
that? What are you actually trying to achieve?


, instead it makes the program not compile. I find this 
behavior odd: why not make it illegal to disable the destructor 
if disabling it will surely result in errors wherever the 
struct is used.


Because it won't surely result in errors wherever the struct is 
used ... you yourself provide an example below where it doesn't.


 The only
situation where the code will compile is A is never used 
directly.


Eh? You immediately give a contrary example:


To make matters even more confusing, this code compiles:

class A
{
int a;
@disable ~this() {}
}

void main()
{
A a = new A();
}


Why is that confusing? Why shouldn't it compile? The A that you 
created is on the heap, so its destructor is never invoked, so 
what would cause it not to compile?





So, is this a bug or am I missing something?

Yoroshiku onegaishimasu,
RazvanN