Re: DMD won't compile re-init of variable

2020-01-31 Thread Minty Fresh via Digitalmars-d-learn

On Thursday, 30 January 2020 at 21:36:53 UTC, Adam D. Ruppe wrote:

On Thursday, 30 January 2020 at 21:09:41 UTC, Simon wrote:

How do I revert my variable to the init state?


null is the initial state for those.


More generally, .init can be used as to get the initial state for 
any type.


ie.
  m_string2edge = typeof(m_string2edge).init;




Re: CTFE Status 2

2017-05-03 Thread Minty Fresh via Digitalmars-d

On Wednesday, 3 May 2017 at 07:35:56 UTC, Stefan Koch wrote:

On Wednesday, 3 May 2017 at 06:10:22 UTC, Adrian Matoga wrote:

So you're going to reinvent TCP in your debugging protocol?



No. there is no need for a full blown recovery mechanism.

For the typical usecase a lossless orderd connection can be 
assumed.


And most things are not order dependent


The debugger isn't a massive, real-time system that needs to 
service thousands of clients and squeeze as much performance out 
of the network as possible. The overhead incurred by TCP is 
essentially not worth considering for something that's going to 
be run over localhost 90%, and service just the one client.


Reinventing the wheel adds a far bigger overhead: Maintaining 
your new protocol.
TCP implementations are readily available. They're well 
maintained, well documented, and are essentially guaranteed to 
work across platforms.
Implementing a new protocol just adds an extra point of breakage 
for little to no gain. It also incurs the cost of the associated 
development time, and - down the line - any time spent fixing or 
iterating. Not to mention that tests need to be written, 
documentation needs to be put in place.


A classic case of premature optimization.


Re: RFC: patch statement

2017-04-03 Thread Minty Fresh via Digitalmars-d

On Monday, 3 April 2017 at 11:16:57 UTC, Dejan Lekic wrote:
I know people her do not like to see proposals that change (add 
stuff to) the language. However, I strongly feel that for the 
testing purposes D should provide means to patch any object (no 
matter whether it is final or not!). Therefore I wonder what 
people think of adding a `patch(obj) {}` or perhaps change the 
semantics of the `with(obj) {}` so unittest writers can modify 
the object and set values.


The patch keyword would work ONLY inside unittest {} blocks AND 
inside functions annotated with @test annotation.


Imagine we have:

int myFun(Person person) { /* some logic here */ }

unittest {
  auto p = new Person() /* does not really matter which 
constructor we use */

  patch(p) {
// here we can modify ANY attribute, no matter whether it 
is private or public

p.fname = "Nikola"
p.sname = "Tesla"
  }
  auto res = myFun(p)
  // do some assertions here
}

Similarly:

@test
void test_myFun() {
  // same code as in the unittest above.
}

I do not even know if patch() {} statement is even possible, 
that is the whole point of writing this, so people can 
enlighten me... :)


As I said in the introduction paragraph, for this purpose the 
semantics of the with statement could be changed, but I prefer 
a different keyword (patch) to be honest.


It looks like what you're trying to do is set up object mocks for 
unit testing.
In general, I find that well designed libraries provide such 
tools for testing, either in the form of factory functions or 
some other means of constructing mocks for test builds. I try to 
follow such patterns myself.


Getting back to the immediate subject:
You can already grant write access to whatever attributes with a 
bit of conditional compilation. Notably, defining accessors that 
exist only for unittest builds.


You could even go so far as to define a generalized one,
ie.
version(unittest)
{
void patch(string attr, T)(Person p, T value)
{
__traits(getMember, p, attr) = value;
}
}

And then, elsewhere:

// Given p is some Person.
p.patch!"fname" = "Nikola";
p.patch!"sname" = "Tesla";

So long as this is defined in the same module as the type, it'll 
be able to access protected and private fields.


Re: If you needed any more evidence that memory safety is the future...

2017-03-08 Thread Minty Fresh via Digitalmars-d

On Sunday, 5 March 2017 at 11:48:23 UTC, Jacob Carlborg wrote:

On 2017-03-03 16:23, Moritz Maxeiner wrote:

That would be a good next step from an engineering standpoint, 
I agree,
to proceed to minimize the amount of trust in people you need 
to have vs

verifiable safety.
I have considered porting something like seL4[1] to Rust, but 
ultimately
this would take a significant amount of time and even if done 
you'd then
have the biggest problem any new kernel faces: Hardware 
support. Driver
development is AFAIK mostly done by people working for the 
hardware
manufacturer and you're going to have a hard (probably closer 
to
impossible) time convincing them to spend money on driver 
development
for you. And if they don't you'll have close to 30 years of 
hardware

support to catch up on by yourself.
But suppose you limit yourself to a single (or at most a 
handful of
homogeneous) platform(s) like [2], e.g. a new AArch64 board. 
Suppose you

even take one where the hardware is open so you can audit its
schematics, then you'll *still* either have to use proprietary 
firmware
for the (partially onboard) periphery (and have unsafe 
interfaces to
them), or - once again - write all the device firmware 
yourself.
And once you've done all of that you're still missing 
userspace, i.e.
you have a nice new OS without any actual use for it (yet). So 
you
either start writing your own incompatible, safe userspace, or 
you're
going to decide to integrate the userspace of existing OSs 
(probably
POSIX?) to your new OS, so you're going to be writing your own 
(safe)
libc, (safe) pthread, etc, exposing (once again) unsafe APIs 
to the top.
It will be safer than what we currently have on e.g Linux 
since you can
probably make sure that unsafe use of them won't result in 
kernel

exploits, though; this will, of course, take even more time.
Finally, at the arduous end of your journey you're likely 
going to
notice what - in my experience - most new OSs I've observed of 
the years
experience: Essentially nobody is interested in actually 
switching to a

volunteer-based OS.
Honestly, I think you need serious corporate backing, a 
dedicated team,
and like 5-10 years (low estimate) of guaranteed development 
time to
have a snowballs chance in hell to pull this off and the only 
possible
sponsors for this I'm both aware of and would currently trust 
not to cut
you off in the middle are either already working on their own 
OS[3], or

have dedicated their R to other things[4].


I agree. The only potential hope I see would be to port Linux 
to a memory safe language.


By Linux, I hope you don't mean the kernel itself. Because 
outside of being an entirely fruitless venture, it shows a lack 
of understanding of what's involved in kernel programming.


Most memory safe languages I know don't take well to using bit 
arithmetic with pointers, deliberately smashing the stack, self 
modifying code, and a whole plethora of things required to work 
with the CPU in a freestanding environment. Within the span of a 
single function call, an address in memory is easily able to 
refer to a different address on physical memory.


Forgive me if I'm wrong, but I don't think you can get that much 
benefit out of memory safety when you change the address of the 
stack pointer manually and start to manually prefill it with new 
values for general registers.


Re: foreach for string[string]AA

2017-03-01 Thread Minty Fresh via Digitalmars-d-learn
On Tuesday, 28 February 2017 at 18:16:45 UTC, Anton Pastukhov 
wrote:
On Tuesday, 28 February 2017 at 17:16:43 UTC, Daniel Kozák 
wrote:

V Tue, 28 Feb 2017 15:15:00 +
Anton Pastukhov via Digitalmars-d-learn
 napsáno:


I can't see the logic in AA foreach order. Consider this code:
...
Output:
three
two
one
four

I was sure output should be
one
two
three
four


https://forum.dlang.org/post/xbanhtkvrizyqjcib...@forum.dlang.org


Thank you for the link, it was informative reading. It's a pity 
that still there is no ordered AA at least as a library type.


Ordered AA isn't that common a use case, and it's not without 
overhead. You essentially need to store an array of keys that 
define iteration order, which requires extra memory allocations 
(and, depending on implementation, may slow down iteration as 
well).


I come from a Ruby background, so I have found key order useful 
in the past, but in most cases I probably could've gotten by just 
fine with an array or set of element pairs.


Introduction of a more convenient tuple type into D might make 
something like this easier.


Re: Getting nice print of struct for debugging

2017-02-24 Thread Minty Fresh via Digitalmars-d-learn

On Saturday, 25 February 2017 at 01:27:09 UTC, Minty Fresh wrote:
On Wednesday, 22 February 2017 at 11:18:15 UTC, Martin 
Tschierschke wrote:

[...]


Since structs are Plain-old Data and don't do inheritance, the 
best option is a template mixin.


ie.

  template mixin PrettyPrint
  {
  string toString()
  {
  // . . .
  }
  }

From there, you can mix it into any struct you want.

  struct MyStruct
  {
  mixin PrettyPrint;
  }

If you're familiar with Rails, this is similar to a Concern.


Errata on that. Should actually be declared as:

  mixin template PrettyPrint()

This is why I shouldn't make posts from my phone.


Re: Getting nice print of struct for debugging

2017-02-24 Thread Minty Fresh via Digitalmars-d-learn
On Wednesday, 22 February 2017 at 11:18:15 UTC, Martin 
Tschierschke wrote:
On Tuesday, 21 February 2017 at 14:02:54 UTC, Jacob Carlborg 
wrote:

[...]

Yes, this works, I would say this is the simplest:

MyStruct s;

foreach (index, name ; FieldNameTuple!MyStruct)
writefln("%s: %s", name, s.tupleof[index]);

If you want something more close to "send" in Ruby, you need 
to use a string mixin, like this:


foreach (name ; FieldNameTuple!MyStruct)
writefln("%s: %s", name, mixin("s." ~ name));

The string mixin example works for methods, opDispatch and 
similar as well. The tupleof example, the first one, works 
only for fields.

Exactly what I was looking for, **thank you!**
Both ways of accessing the struct elements are very interesting,
giving an impression what is possible with D.


Is it possible to overwrite "toString" for all structs in one 
step?


Regards mt.


Since structs are Plain-old Data and don't do inheritance, the 
best option is a template mixin.


ie.

  template mixin PrettyPrint
  {
  string toString()
  {
  // . . .
  }
  }

From there, you can mix it into any struct you want.

  struct MyStruct
  {
  mixin PrettyPrint;
  }

If you're familiar with Rails, this is similar to a Concern.


Allocators and Containers

2017-02-16 Thread Minty Fresh via Digitalmars-d
A lot of the usefulness of the std.experimental.allocators module 
is lost because no other part of the stdlib actually ties into 
the functionality provided by it.


For example, the Array type defined in std.container relies on 
malloc() directly, so if you wanted to use a type to replace 
built-in arrays with a custom allocator, you'd need to implement 
your own container type.


Would it make sense to allow the std.container types to accept 
IAllocator instances, and to allow custom allocators? (Using 
Mallocator by default.)




Re: Convert struct to set of fields and pass it's to constructor

2017-02-01 Thread Minty Fresh via Digitalmars-d-learn

On Wednesday, 1 February 2017 at 13:37:27 UTC, Suliman wrote:

Class constructor accept only set if fields like
this(string login, string pass)

Can I create structure, fill it, and than pass to constructor?

Like this:
```
import std.stdio;

struct ConnectSettings
{
string login;
string pass;
};
ConnectSettings cs;

void main()
{
 cs.login = "admin";
 cs.pass = "mypass";
}
```

and than pass to constructor it's like:

`... new SomeClass(cs)`


I tried, but get error, that ctor accept only fields list. Can 
I unroll struct to it?


tupleof is probably what you're looking for.
ie.

  new SomeClass(cs.tupleof);

That said, why not have the constructor accept the struct as a 
parameter?




Re: Dlang dynamic compilation

2016-11-22 Thread Minty Fresh via Digitalmars-d-announce

On Monday, 21 November 2016 at 18:59:17 UTC, Ivan Butygin wrote:

Hacked ldc sources are here:
https://github.com/Hardcode84/ldc/tree/runtime_compile


Very cool. Although @runtimeCompile does peeve me, as it seems 
unnecessarily verbose (being longer than any other attribute, I 
think).


I'd have gone with @rtc or similar so as not to clutter function 
and variable declarations, but those are just my thoughts on 
language readability.


Re: Overloading relational operators separately; thoughts?

2016-10-02 Thread Minty Fresh via Digitalmars-d

On Saturday, 1 October 2016 at 17:53:44 UTC, Russel Winder wrote:
On Sat, 2016-10-01 at 14:55 +, Chris Wright via 
Digitalmars-d wrote:



Groovy doesn't allow you to overload comparison operators
individually,
and probably most JVM languages likewise. This is to retain
compatibility
with Java, which has `.compareTo()` instead of `isLessThan()` 
etc.


Yes it does.  http://groovy-lang.org/operators.html

There is *also* compareTo.

Ruby allows you to override individual comparison operators, 
with a

special operator `<=>` for combined comparisons. Nim lets you
overload
arbitrary operators and create your own; some old discussions
suggest
that the Comparable type is based on `<` alone.


Groovy also supports the spaceship operator.


`<=>` exists for the general case, which is what `opCmp` covers 
in D. Overloading each relational operator individually is made 
possible to address any sort of special cases.
The issue being, in D there is no room for any manner of special 
case.


Re: Overloading relational operators separately; thoughts?

2016-10-01 Thread Minty Fresh via Digitalmars-d

On Friday, 30 September 2016 at 23:31:19 UTC, Sai wrote:
Genuine question: In the post Java languages, how many 
languages allowed unrestricted operator overloading and did 
that cause any similar mess?


Thanks in advance for any answers.


Although there maybe a bit of bias here, but I'd say Rub does it 
quite well (although the syntax for unary operator overloads is a 
bit bizarre), since I work with the language on a daily basis.


But going a step further there's languages like Haskell that 
allow defining completely new operators.


Both of the aforementioned have amassed an exceedingly large 
following at this point.


Re: Overloading relational operators separately; thoughts?

2016-10-01 Thread Minty Fresh via Digitalmars-d

On Friday, 30 September 2016 at 22:38:07 UTC, Walter Bright wrote:

On 9/30/2016 1:14 PM, Minty Fresh wrote:

Metathesiophobia


Repeatedly suggesting people who don't agree with you have 
mental disorders does not advance your case and is not 
appreciated here.


Metathesiophobia is not a mental disorder, it's a phobia. There's 
quite a bit of distinction there.
Specifically it's an ungrounded fear or dislike of change. It's 
altogether not uncommon, actually.


A more productive way forward is for you (and those who agree 
with you) to prepare a formal DIP and submit it. It's the way 
significant language change proposals are done.


That was sort of the initial intent of this thread. To test the 
waters and see if the idea would have support.

But it seems the community is extremely torn on the matter.


Re: Overloading relational operators separately; thoughts?

2016-09-30 Thread Minty Fresh via Digitalmars-d

On Friday, 30 September 2016 at 19:46:35 UTC, bachmeier wrote:
Claiming that operator overloading only applies to a specific 
user-defined type makes it worse. Having it work one way for 
three types, a different way for four other types, and a third 
way for yet another type doesn't sound like a minor thing.


But operators already behave in different way for different 
types. Built-in types inclusive. The most trivial and nit-picky 
difference would be between integer types and floating point 
types.


ie. Division between two integers yields an integer, division 
between two floats yields a float, but then division between an 
integer and a float also yields a float.
Alternatively, the bit-shift operators `<<` and `>>` don't 
function at all for floats.
But then we have also wonderful floating point values like `NaN` 
and `Infinity` for which arithmetic and relational operators 
behave differently altogether.


Another would static arrays, versus dynamic arrays, versus 
associative arrays. The first two support concatenation via `~`, 
only the second supports in-place concatenation `~=`, and the 
last has no notion of concatenation at all.


A counter argument that might be raised is that those are 
different types altogether. They are intended to behave in 
different ways entirely. Completely different data structures. 
Their similarities are only superficial.


And such a counter argument would be absolutely correct. Markedly 
so. They are completely different types.
The same is true of user-defined types. Their behavior should not 
be equated to (nor expected to be like) the behaviors of types 
they only resemble superficially.


But have fun debating design decisions that were made long ago 
and aren't going to change.


That's exactly the kind of decision making you see in C++ and 
PHP. Metathesiophobia would be one way of describing it. Stubborn 
blindness to real world usage is more contextually appropriate 
though, I feel.


Re: Overloading relational operators separately; thoughts?

2016-09-30 Thread Minty Fresh via Digitalmars-d
On Friday, 30 September 2016 at 00:50:54 UTC, Jonathan M Davis 
wrote:


Except that it kind of is. It's an example of a language 
allowing you to mess with too much and make it so that it 
doesn't function as expected, which is what happens when you 
overload operators to act in a way inconsistent with how they 
work with the built-in types. The perl example is more extreme, 
but the point still stands that having normal, common 
constructs operate in a way that's inconsistent with how they 
normally work tends to make code harder to read and maintain. 
Certainly, it can result in very unexpected behavior when 
mixing it with generic code that uses those operations.


- Jonathan M Davis


It's up to the developer to ensure that their code works 
correctly with existing facilities, not the language. I can 
already write code that will work in amazing and ridiculous ways 
with generic code in the standard library. It does not follow 
that the language is responsible or at fault for the code 
behaving in ways that are unexpected.


Furthermore, it's completely reasonable to write code that works 
with the generic facilities in the standard library, even if it 
doesn't behave exactly like a built in type.


ie.

  foo.reduce!"a + b"; // => produces an integer
  bar.reduce!"a + b"; // => produces an AST node

So long as the types produced by the operation are correct, this 
will work just fine.


Re: Overloading relational operators separately; thoughts?

2016-09-29 Thread Minty Fresh via Digitalmars-d

On Thursday, 29 September 2016 at 22:27:50 UTC, bachmeier wrote:
You're looking for https://www.perl.org/ That's a highly viable 
language, where you can do things like bury $[ = 1 somewhere in 
your code to change from 0-indexing to 1-indexing of arrays. 
They take pride in unpredictable, unreadable code.


This is not at all relevant to the current argument.


Re: Overloading relational operators separately; thoughts?

2016-09-29 Thread Minty Fresh via Digitalmars-d
On Thursday, 29 September 2016 at 19:39:35 UTC, Jonathan M Davis 
wrote:
The language can't stop you from doing at least some arbitrary 
stuff with them (like making + do subtraction), but the whole 
goal was for user-defined types to be able to act like the 
built-in types, and as such, it would make no sense to alter 
them towards being treated like symbols that you can do 
whatever you want with.


Having `+` do subtraction isn't something you'd normally see. 
It's not a use case that would normally exist.


Having `+` do addition, but do so in a database layer is a use 
case that actually may exist. The operator still behaves like a 
built-in type. It may perform addition as part of a SQL query, 
for example.


Whether the expression `a + b` is translated into machine 
language, or translated into SQL, both still perform addition. A 
value represented by `a` is added to a value represented by `b`. 
Whether `a` and `b` are variables in D, or columns in a database 
table is irrelevant.


And as it stands, D can already do this. It's the inability to 
perform an equivalent action for the expression `a > b`.


Re: Overloading relational operators separately; thoughts?

2016-09-29 Thread Minty Fresh via Digitalmars-d

On Thursday, 29 September 2016 at 19:11:55 UTC, pineapple wrote:
Relinquish the notion that you or anyone can have the slightest 
idea what any language feature is "supposed to mean and be used 
for".


Basically what led to D's CTFE implementation in the first place, 
IIRC.


Re: Overloading relational operators separately; thoughts?

2016-09-29 Thread Minty Fresh via Digitalmars-d
On Thursday, 29 September 2016 at 18:07:37 UTC, Russel Winder 
wrote:
On Thu, 2016-09-29 at 10:52 -0700, Walter Bright via 
Digitalmars-d wrote:

On 9/29/2016 9:41 AM, Sai wrote:
> 
> If I understand the issue correctly, one will not be able to

> overload <=, >, etc
> for symbolic math, like CAS (mimicking mathematica for 
> example),

> how can I do it
> now?


a.isLessThan(b)


How wonderfully Java.


Personally, I'm amused because this implies the prospect of:

  a.isGreaterThanOrEqualTo(b)

I mean, there is an acceptable level of verbosity. This is not it.


Re: Overloading relational operators separately; thoughts?

2016-09-29 Thread Minty Fresh via Digitalmars-d
On Thursday, 29 September 2016 at 12:54:54 UTC, Jacob Carlborg 
wrote:

BTW, there's a CTFE parser generator for D around somewhere.


And that will handle all that the DMD parser does? I don't 
think so.


I agree with this entirely. Lest you have an entire D compiler 
implemented in CTFE (reductio ad absurdum), you're working with a 
limited subset of the language, and pose additional challenges 
for a developer trying to debug.


Not to mention that string mixins render IDE features like code 
completion and error highlighting essentially unusable.


Re: Overloading relational operators separately; thoughts?

2016-09-29 Thread Minty Fresh via Digitalmars-d
On Thursday, 29 September 2016 at 11:29:55 UTC, Russel Winder 
wrote:
However, this has come up many times, and every time Walter 
says "no, it's wrong". Whilst the C++ iostreams << may have 
problems, using this as a single point argument as to why 
overloading fails in all other cases except numeric arithmetic 
is bad philosophy. In my view this is holding D back.


To add some thoughts to this,

The use of << being bad is purely a matter of opinion.
If you believe that << is to only be used for bit-shifting 
operations, you might hold the view that it is bad.
On the other hand, if you come from a background like Haskell or 
Ruby, you might have a very different opinion.


ie.
In Ruby, << is named the shovel operator. It's uses are things 
like appending an element into an Array.


Hence, a less opinionated point is necessary here.


Re: Overloading relational operators separately; thoughts?

2016-09-28 Thread Minty Fresh via Digitalmars-d
On Thursday, 29 September 2016 at 04:15:32 UTC, Walter Bright 
wrote:

On 9/28/2016 1:40 PM, Timon Gehr wrote:

What's wrong with that usage?


Because then something other than comparison is happening with 
<=, <, >, >= and there'll be nothing in the code to give the 
user a hint.


There's also nothing to give the user a hint that binary 
arithmetic operators may also not do what they expect them to do.
Going further, there may be nothing to give the user a hint that 
a named function doesn't to what its name suggests.


All of the above are shortcomings in documentation, or short 
comings in implementation.


Even with the current system of using `opCmp`, it's still 
possible to implement these operators such that they behave in a 
way that would confound the user (ie. have their results be 
nondeterministic, external side effects, etc.)


D has many very powerful modeling abilities, but so far we've 
tried to stay away from things that make context-free user 
understanding of code unduly difficult. It should not be 
necessary to use an IDE to understand code.


No, you're right. It's not the responsibility of the IDE to 
perform such tasks. It's the responsibility of the documentation. 
D is already is such a state the language is difficult for a 
context-free user without access to documentation.


Even the standard library. Especially the standard library.
Things like `.each` in std.algorithm returning void, whereas the 
bizarrely named `.tee` in std.range actually retuning the input 
range. Things like the `SList` and `DList` types defined in 
std.container requiring explicit initialization to work. Things 
like the behavior and semantics of type tuples (or alias lists). 
Things like the differences between `.byLine` vs `.byLineCopy` in 
std.stdio.
All of these rely on the developer having documentation. There's 
no way around it. D as a language is already way too complex to 
do anything without it.


This applies to operator overloads just like everything else. 
They're just syntactic sugar for functions. Documenting their 
behavior is just as necessary.


Re: Module names shadowing defined functions/templates.

2016-09-28 Thread Minty Fresh via Digitalmars-d

On Thursday, 29 September 2016 at 02:26:15 UTC, Joakim wrote:
I ran into this too, it is annoying. I think you're supposed to 
use different names.


It's a rather painful limitation if that were the case.
Going with the example I gave, what would an alternative name for 
the module be? All it's public members are named `leastsq`.


While I can imagine there are technical challenges that have 
caused this issue to be the way it is, it's still a pretty major 
flaw to try to work around.


Working around shortcomings of a language is never a good place 
to be in.


Re: Module names shadowing defined functions/templates.

2016-09-28 Thread Minty Fresh via Digitalmars-d
As an addendum to the above, the error message I posted was from 
the overload that takes a delegate as a runtime parameter.


Trying to pass template arguments just gives you:

   Error: template instance leastsq!((p) => p) leastsq is not a 
template declaration, it is a import


Module names shadowing defined functions/templates.

2016-09-28 Thread Minty Fresh via Digitalmars-d
I ran into this issue just recently when trying to write a 
least-squares optimization function.

Notably,

  module leastsq;

  T[] leastsq(alias func, T)(T[] vec, . . .)
  {
  . . .
  }

It becomes impossible to import and call this template function 
from outside the module it's declared in. Trying to do so just 
yields:


  Error: function expected before (), not module leastsq of type 
void


This is really inconvenient. `leastsq` has a very long and 
implementation, most of which is not a public API. It makes sense 
to put it into its own module because it and all of the functions 
it uses internally are some 1000 lines long.


I don't really know of any other language that faces this 
limitation.


Re: Overloading relational operators separately; thoughts?

2016-09-28 Thread Minty Fresh via Digitalmars-d

On Wednesday, 28 September 2016 at 20:40:49 UTC, Timon Gehr wrote:

This is not surprising. C++ has no good options.


This is further made worse by some C++'s more inane design 
decisions (ie. allowing overloading of the comma operator).


Re: Overloading relational operators separately; thoughts?

2016-09-28 Thread Minty Fresh via Digitalmars-d
On Wednesday, 28 September 2016 at 20:16:08 UTC, Walter Bright 
wrote:
To reiterate, operator overloading exists in D to support the 
inclusion of arithmetic library types. Any other purpose is 
discouraged, and that includes expression templates and things 
like << for iostreams.


It seeds rather harsh to discourage every possible use case of a 
feature sans one, simply because one does not agree with the 
others.




Re: Overloading relational operators separately; thoughts?

2016-09-28 Thread Minty Fresh via Digitalmars-d
On Wednesday, 28 September 2016 at 04:02:59 UTC, Walter Bright 
wrote:
The use of them to create DSLs (a technique called "expression 
templates" in C++) is discouraged in D, for several reasons. 
The recommended way to create DSLs in D is to parse strings 
using CTFE.


I don't really come from a C++ background. Actually, I have a 
strong distaste for the language. Professionally, I word with 
Ruby.


Again, string DSLs face a number of issues. A few that come to 
mind are:
  1. A parser + code generator must be implemented, which is a 
lot of additional work.

  2. The quality and precision of error messages degrades.
  3. You loose the ability to perform actions like making 
declarations within the context of the DSL (ie. assigning a 
commonly re-used expression to a variable), unless your DSL is 
turing complete.



An excellent example of that is the std.regex package.


You know, if someone had managed to implement a regex DSL using 
operator overloading, something must have gone _terribly_ wrong. 
Regex is traditionally done in strings, lest the language 
supports regex literals.


Re: Overloading relational operators separately; thoughts?

2016-09-27 Thread Minty Fresh via Digitalmars-d
On Wednesday, 28 September 2016 at 03:12:05 UTC, Jonathan M Davis 
wrote:
On Wednesday, September 28, 2016 01:18:58 Minty Fresh via 
Digitalmars-d wrote:
Basically, having them be overloaded separately is error-prone, 
and it leads to folks overloading them in ways that have 
nothing to do with what they mean for the built-in types, which 
makes code harder to read and maintain. D has a concatenation 
operator specifically because Walter thought that it was 
horrible to use + for concatenation.


If you want to write DSLs, then use strings and mixins. D gives 
you a _lot_ of power in that area, and it avoids the problems 
associated with making overloaded operators do things other 
than what those operators are normally intended to do. With 
strings, you can make your DSL look however you want - even 
doing stuff like using various Unicode symbols as operators if 
you want to. Even with how C++ overloads operators, overloading 
operators gives you fairly limited options with what you can do 
with a DSL, whereas you have full freedom with strings - and 
without the problems that come with trying to make your DSL 
look like normal D code.


- Jonathan M Davis


Using strings and mixins does have quite a number of downsides. 
The additional work required to past the DSL aside, you also 
usually lose the scope in which things are declared (especially 
if you wish to reference or declare variables/functions/other 
constructs within your DSL), error reporting becomes much less 
precise, and the transition between the outer code and the inner 
DSL becomes jarring (especially in terms of syntax highlighting).


That said, I love the fact D has a separate operator for 
concatenation. It's extremely useful to not have that ambiguity.


Another thought is, operators not behaving as expected doesn't 
strike me as a failure of the language, given the language 
supports operator overloading. It's a failure in documentation to 
explain what the operators are intended to do, or a failure in 
implementation to behave as they should.


Lastly, if operators are intended to behave so strictly, why does 
this not extend then to binary arithmetic operators (+, -, *, /, 
%, etc.)
They don't follow the same rules as the binary relational 
operators, after all.


Overloading relational operators separately; thoughts?

2016-09-27 Thread Minty Fresh via Digitalmars-d
Currently, D offers fine grained overloading for most of the 
unary and arithmetic binary operators, but at some point a 
decision was made to lump together all of the relational 
operators (and if necessary, the equality operators) into a 
single function `opCmp`.
And while it does add a lot of convenience and consistency to how 
operators behave, it does also put a lot of limitations on what 
they can do.


For example, it's not currently possible to implement comparison 
operators that would behave lazily and only compute a certain 
value once a function call forces the computation.


Similarly, it's not possible to construct a DSL that would 
produce code or a query in another language, by returning values 
behave like AST nodes rather than actually performing a 
comparison.


ie.
  table.users
   .where!((users) => users.joined_on >= 3.days.ago)
   .joins(table.posts)
   .on!((posts, users) => posts.user_id == users.id)
   .limit(10)
   .toSql;

It's a little odd to me that D puts so little focus on DSLs, 
since language features like template constraints, `opDispatch`, 
and even the fact that binary operators are overloadable via a 
single templated function are all very useful tools for 
implementing them.


So, I'm just interested in other people's thoughts are on the 
subject, and whether there are any plans to allow overloading 
these operators separately.