July 12, 2016
On 07/12/2016 12:55 PM, Shachar Shemesh wrote:
> On 12/07/16 13:25, Walter Bright wrote:
>> On 7/12/2016 12:35 AM, Shachar Shemesh wrote:
[...]
>>> struct A {
>>>      void method() {}
>>> }
>>>
>>> void main() {
>>>      A* a;
>>>
>>>      a.method(); // Okay
>>>      method(a);  // Not okay
>>> }
>>
>> I'm afraid I don't know what you're driving at with those examples.
>>
>
> It is a single example. It shows that when UCFS and the lack of operator
> -> try to play together, the result is no longer as simple and elegant
> as one tries to sell them. It was given as a response to Andrei's
> request for examples of cross-features interference causing complexity.

There is no UFCS in that example, and the -> operator would only affect the "Okay" case.

The "Not okay" case fails because there is no free function "method". It would fail even if D didn't have UFCS and if it had the -> operator.
July 12, 2016
On 7/12/2016 3:55 AM, Shachar Shemesh wrote:
> On 12/07/16 13:25, Walter Bright wrote:
>> On 7/12/2016 12:35 AM, Shachar Shemesh wrote:
>>> UFCS: Anywhere you can do "func(a)" you can also do "a.func()" and vice
>>> versa.
>>>
>>> Operator ->: Not needed, as we know this is a pointer to a struct. We
>>> automatically dereference with the dot operator.
>>>
>>> struct A {
>>>      void method() {}
>>> }
>>>
>>> void main() {
>>>      A* a;
>>>
>>>      a.method(); // Okay
>>>      method(a);  // Not okay
>>> }
>>
>> I'm afraid I don't know what you're driving at with those examples.
>>
>
> It is a single example. It shows that when UCFS and the lack of operator
> -> try to play together, the result is no longer as simple and elegant
> as one tries to sell them. It was given as a response to Andrei's
> request for examples of cross-features interference causing complexity.

I assumed you were talking about UB or unsafe behavior. Thanks for the clarification.

As to the specific case here, the spec doesn't say "vice versa":

"A free function can be called with a syntax that looks as if the function were a member function of its first parameter type."

http://dlang.org/spec/function.html#pseudo-member

Not the other way.
July 12, 2016
On 7/12/2016 3:50 AM, Guillaume Piolat wrote:
> Honestly after writing a toy Scheme interpreter, I've come to think much
> more highly of Javascript.

Javascript isn't quite as easy to implement as it looks :-)
July 12, 2016
On Tuesday, 12 July 2016 at 11:02:04 UTC, Walter Bright wrote:
> On 7/12/2016 3:31 AM, Johan Engelen wrote:
>> With `synchronize` we already have a problematic case of casting away
>> immutability (dmdfe internally) where an optimizing compiler generates
>> bad code. Let's not add more.
>
> Is there a bugzilla issue for this?

Of course there is.
And has been for more than a year.
https://issues.dlang.org/show_bug.cgi?id=14251
July 12, 2016
On 7/12/16 1:33 AM, Andrei Alexandrescu wrote:

> The solution (very ingenious, due to dicebot) in fact does not quite
> cast immutability away. Starting from a possibly immutable pointer, it
> subtracts an offset from it. At that point the memory is not tracked by
> the type system, but known to the allocator to contain metadata
> associated with the pointer that had been allocated with it. After the
> subtraction, the cast exposes the data which is mutable without
> violating the immutability of the object proper. As I said, it's quite
> an ingenious solution.

Ahem: https://forum.dlang.org/post/ft5a6g$1519$1@digitalmars.com

-Steve
July 12, 2016
On 7/12/2016 4:45 AM, Johan Engelen wrote:
> https://issues.dlang.org/show_bug.cgi?id=14251

Thank you.
July 12, 2016
On Tuesday, 12 July 2016 at 10:44:56 UTC, Walter Bright wrote:
> On 7/12/2016 1:41 AM, Ola Fosheim Grøstad wrote:
>> And to be frank D's symbol resolution isn't suitable for programming-in-the-large
>> either.
>
> Explain.

http://forum.dlang.org/thread/skqcudmkvqtejmofxoim@forum.dlang.org

> Frictionless masses are useful for teaching engineering, but are not useful in the real world, which tends to be complicated and dirty, just like useful programming languages.

Languages sometimes get complicated and dirty when they are "patched up" with the requirement that they should not break existing code. C++ and Objective-C are such languages, and the source is both C and lack of initial design considerations.

However, your claim that Prolog has not been useful in the real world is silly. You are making some unstated assumptions about what «useful» means. There are plenty of expert-systems based upon Prolog.

There are plenty of problems that would be much easier to solve in Prolog than in D, and vice versa.

> I asked for one feature originating in Prolog that made its way into mainstream languages.

No you didn't. Unification is Prolog's main feature. C++ template matching uses unification.

> You dismissed C++'s enormous influence in getting languages to adopt OOP

Sure, _anyone_ with any kind of education in computing since the 80s would have learned what OO was way before C++ got mainstream around 1990.

C++ got OO into mainstream application development, that's different. There were plenty of OO languages around before that event.


July 12, 2016
On Tuesday, 12 July 2016 at 10:19:04 UTC, Walter Bright wrote:
> On 7/12/2016 2:40 AM, John Colvin wrote:
>> For the previous statement to be false, you must define cases where
>> casting away immutability *is* defined.
>
> @system programming is, by definition, operating outside of the language guarantees of what happens. It's up to you, the systems programmer, to know what you're doing there.

This is so, so wrong. There's a world of difference between "you have to get this right or you're in trouble" and "the compiler (and especially the optimiser) is free to assume that what you're doing never happens".
Undefined behaviour, as used in practice by modern optimising compilers, is in the second camp. You might have a different definition, but it's not the one everyone else is using and not the one that our two fastest backends understand.

Given the definition of undefined behaviour that everyone else understands, do you actually mean "modifying immutable data by any means is undefined behaviour" instead of "casting away immutable is undefined behaviour"?
July 12, 2016
On 07/12/2016 03:23 AM, deadalnix wrote:
> On Tuesday, 12 July 2016 at 05:33:00 UTC, Andrei Alexandrescu wrote:
>> Amaury failed to produce an example to support his point, aside from a
>> rehash of a bug report from 2013 that is virtually fixed. Do you have
>> any?
>>
>
> Finger moon. I presented maybe 5 exemple of what I'm talking about
> already and it is still not enough. You guys keep wanting to discuss
> every single example to death to avoid doing the hard thinking.
>
>> I think we're in good shape with what we have; mutable has too much
>> freedom and it's good to get away without it.
>>
>
> True but once again, finger, moon, etc...

Indeed I'm not the sharpest tool in the shed, and since it's already been established I'm the idiot and you're the wise man (congratulations - surely enough the great work to substantiate that is very soon to follow) in the proverb, I hope you'll allow me one more pedestrian question.

So I've been looking through this thread for the five examples of what you're talking about (which to my mind is "@safe is just a convention") and the closest I could find is your post on http://forum.dlang.org/post/iysrtqzytdnrxsqtfwvk@forum.dlang.org.

So there you discuss the inconsistency of "alias" which as far as I understand has nothing to do with safety. Then we have:

enum E { A = 1, B = 2 }
E bazinga = A | B;
final switch (bazinga) { case A: ... case B: ... } // Enjoy !

which I pasted with minor changes here: https://dpaste.dzfl.pl/b4f84374c3ae. I'm unclear how that interacts with @safe. It could, if the language would allow executing unsafe code after the switch. But it doesn't. Could you please clarify? And could you please point to the other examples?


Thanks,

Andrei

July 12, 2016
On 07/12/2016 03:35 AM, Shachar Shemesh wrote:
> On 12/07/16 08:33, Andrei Alexandrescu wrote:
>> On 07/12/2016 01:15 AM, Shachar Shemesh wrote:
>>> The topic was reference counting's interaction with immutable (see
>>> deadalnix's comment, to which I completely agree, about inter-features
>>> interactions).
>>
>> Amaury failed to produce an example to support his point, aside from a
>> rehash of a bug report from 2013 that is virtually fixed. Do you have
>> any?
>
>
> UFCS: Anywhere you can do "func(a)" you can also do "a.func()" and vice
> versa.
>
> Operator ->: Not needed, as we know this is a pointer to a struct. We
> automatically dereference with the dot operator.
>
> struct A {
>     void method() {}
> }
>
> void main() {
>     A* a;
>
>     a.method(); // Okay
>     method(a);  // Not okay
> }

Thanks. I must have misunderstood - I was looking for something that's not @safe.

>>> When asked (by me) how you intend to actually solve this,
>>> you said that since you know where the memory comes from, you will cast
>>> away the immutability.
>>>
>>> Casting away immutability is UB in D.
>>
>> I understand. There is an essential detail that sadly puts an
>> anticlimactic end to the telenovela. The unsafe cast happens at
>> allocator level. Inside any memory allocator, there is a point at which
>> behavior outside the type system happens: memory that is untyped becomes
>> typed, and vice versa (during deallocation).
>
> Nah, this is cut and dried. You should just continue being nicely
> turbed. "Casting away immutability has undefined behavior" is what it
> is. [1]

AffixAllocator is not casting away immutability - that's the beauty of it. But I'm all for making the language more precise to allow the kind of work AffixAllocator does portably. Would love some help from you there!

> It is quite okay, and even unavoidable, to go outside the type system
> inside an allocator. It something else entirely to invoke UB.
>
> The C++ definition is quite solid. Casting away constness is UB IFF the
> buffer was originally const.

Yeah, we might relax that in D as well, albeit for different reasons.

> In this case, your allocator does two UBs. One when allocating (casting
> a mutable byte range to immutable reference), and another when
> deallocating. Both are defined as undefined by D, which means the
> compiler is free to wreak havoc in both without you having the right to
> complain.
>
> Which leads me to the conclusion that you cannot write an allocator in
> D. I doubt that's a conclusion you'd stand behind.

Again, your help with improving the language definition would be very welcome. Obviously we do want to have AffixAllocator and other allocators work properly.


Andrei