August 07, 2012
Timon Gehr , dans le message (digitalmars.D:174361), a écrit :
> On 08/06/2012 09:42 PM, Christophe Travert wrote:
>> Timon Gehr , dans le message (digitalmars.D:174329), a écrit :
>>> On 08/06/2012 07:20 PM, Christophe Travert wrote:
>>>>
>>>> What do you think?
>>>
>>> Creating byzantine language rules to cater to unimportant or non-existent use cases will slaughter the language.
>>
>> What exactly do you consider byzantine here, whatever that means?
> 
> byzantine means involved. Why deliberately make the language more complicated for no gain whatsoever?
> 
>> Implicit cast is an already defined feature. Clarifying the way parenthesis-less function calls exist by adding a casting rule is making the langage more simple IMHO,
> 
> I don't know what to respond to this. Are you serious?
> 
>> and might improve the current position. Of
>> course, if your point is that parenthesis-less function calls are
>> unimportant or non-existent,
> 
> It isn't. My point is that there actually is no issue that would require some complex solution.

Misha's post reminded me that parenthesis-less function call rules are not that complicated, although I think he omitted one or a few things like assigning a function to an auto parameter or passing a function to a template. I agree that the situation is sufficent can be kept that way, and that there is no big issue.

However, I had the impression from deadalnix' post that what he wanted to discuss was something that would make function real first class types, that you could use, assign, etc, without using function pointers (although there have to be function pointers internally of course). If foo is a function, I think making "auto a = foo;" be a function is something that is expected in a langage where function are first class types. Thus, making parenthesis-less function expressions be functions. I maintain that I don't think that one implicit cast rule is not more complicated than the lines Misha used to describe parenthesis-less function call + some probably missing cases.

I understand the D language does not like implicit cast. The approach was to make as few implicit casts as possible and loosen the rule parsimoniously to avoid to create mess. That rule may be more important than making function first-class types in D, or defining parenthesis-less function call as an implicit cast.

Now, a little off-topic, implicit cast and rewrites are already everywhere in the language. Many feature are already attempts something, if it does not work, rewrite and attempt again. That's how the compiler works in many cases from what I briefly caught. Describing as many language features as possible as rewrites is a way that may make the language easier, and provides a way to describe feature interactions too, by prioritizing or restricting combinaisons of rewrites. Independently of parenthesis-less function call issue, I think that this may be a way to redefine the language, and open doors to clarify a few tricky issues. I may very well be mistaken, but I think this approach should be considered when discussing language features.

-- 
Christophe

August 07, 2012
Le 07/08/2012 07:45, David Piepgrass a écrit :
>>> class A { void B() {} }
>>> auto a = new A().B();
>>> // ^ semicolon expected following auto declaration, not '.'
>>>
>> Obviously. No clue what this snippet is trying to do.
>
> Well I meant "int B() { return 0; }" of course. I think you deliberately
> miss the point.

According to what is described here : http://dlang.org/expression.html this is legal and is a dmd bug.
August 07, 2012
On Monday, 6 August 2012 at 19:45:17 UTC, deadalnix wrote:
> Le 06/08/2012 21:07, Mafi a écrit :
>>> No dereferencing is done in the compiled code anyway. BTW, an «
>>> address of » operation is done on the type mentioned above.
>>>
>>
>> I don't get what you are saying here. For me there's an inherent
>> difference between a fuction and a function pointer. You shouldn't try
>> to conflate them in a system language in my opinion.
>>
>
> On any hardware, a function call will boil down to set up stuff on the stack and branching, jumping, calling or whatever on the ADDRESS of the function's code.
>
> In other term, what is generated always involve the function's instruction address. If you dereference that address, you get instructions, but that hardly something useful to have at higher levels because you can"t do anything with it anyway.
>

It's the same with an int on the stack, isn't it (literally on the stack; not optimized into a register). To access it, one has to dereference its address but you wouldn't like conflating int and int*.
The difference is between the address being a constant (maybe relative to the stack) and being totally unknown. In my opinion this is a big difference, also for functions.

...
>
> Well D also advertise itself as OO and functional. Obviously, decision will have to be made. Because if no design decision is made, you ends up like it is now : micro decision are made when coding, and no overall is followed.
>
>>>> I don't like authorative formal specs. It means most things are set in
>>>> stone and you have to write a new spec every once in a while which slows
>>>> down development of awesome language features.
>>>>
>>>
>>> This isn't about awesome language features. This is about function
>>> calls ! The most basic feature ever.
>>>
>>> BTW, not stabilized feature shouldn't appear in what we call stable
>>> release . . . They should be provided testing versions of the compiler
>>> so they can be tortured and refined to the point everything make sense.
>>
>> This isn't about versioning schemes either! But there have been long
>> discussions recently and at least some things will change with the
>> development after 2.060 afaik.
>>
>
> Yes, that was a digression. When stating that UFCS don't integrate nicely with other features, this showed the need for incubation of feature, and as recent discussions have been made on versioning, I made a bridge.


August 07, 2012
Le 07/08/2012 14:15, Mafi a écrit :
> On Monday, 6 August 2012 at 19:45:17 UTC, deadalnix wrote:
>> Le 06/08/2012 21:07, Mafi a écrit :
>>>> No dereferencing is done in the compiled code anyway. BTW, an «
>>>> address of » operation is done on the type mentioned above.
>>>>
>>>
>>> I don't get what you are saying here. For me there's an inherent
>>> difference between a fuction and a function pointer. You shouldn't try
>>> to conflate them in a system language in my opinion.
>>>
>>
>> On any hardware, a function call will boil down to set up stuff on the
>> stack and branching, jumping, calling or whatever on the ADDRESS of
>> the function's code.
>>
>> In other term, what is generated always involve the function's
>> instruction address. If you dereference that address, you get
>> instructions, but that hardly something useful to have at higher
>> levels because you can"t do anything with it anyway.
>>
>
> It's the same with an int on the stack, isn't it (literally on the
> stack; not optimized into a register). To access it, one has to
> dereference its address but you wouldn't like conflating int and int*.
> The difference is between the address being a constant (maybe relative
> to the stack) and being totally unknown. In my opinion this is a big
> difference, also for functions.
>
> ...

This is basically what is done for objects, and with great benefice.
August 07, 2012
Le 06/08/2012 20:05, David Piepgrass a écrit :
> I'm not sure if I understand your point perfectly, but I definitely feel
> that the way D handles optional parens is awful.

That is the point.

More specifically, the fact that D picks functionality from different paradigm here that totally don't integrate with each other.

 - Like in functional, function are called without ().
 - Purity isn't enforced, so the () is actually important so . . .
 - Function cannot be first class without ambiguities. So they aren't.
 - A first class function exists, and the behavior is different than other functions.
 - Member methods have semantic similar to declared ones.
 - But UFCS don't. They also don't have the behavior of first class object cited above.
 - UFCS include it's own layer of mess.
 - @property does the same.
 - Most of this isn't defined anywhere, except in dmd source code.
 - dmd source code is known to have bugs on the very point, so no spec exists at all. Not even documents describing the intent that can clarify what is a bug and what is feature.

So what ? So it is unlikely that any other tool will have semantic identical to dmd's. At this point, I'm questioning if any tool should even try.
August 07, 2012
You do not seriously expect D to copy exactly how Haskel (or any other similar declarative langauge) treat functions? Does it really have to be an exact copy? I am not trying to defend D language designer(s) here, just trying to say that D should have own style, if there is sense behind it, it does not necessarily have to conform 100% to any paradigm.

The main reason for me to start using D 10 years ago was the obvious PRAGMATIC design of the language. I did not start using it because of (possible) functional orientation. Actually, I would probably turn my back on D if I saw it promotes declarative style more than imperative.

I think the current mix of both worlds is the best direction for D.
August 07, 2012
Le 07/08/2012 17:14, Dejan Lekic a écrit :
> You do not seriously expect D to copy exactly how Haskel (or any other
> similar declarative langauge) treat functions? Does it really have to be
> an exact copy? I am not trying to defend D language designer(s) here,
> just trying to say that D should have own style, if there is sense
> behind it, it does not necessarily have to conform 100% to any paradigm.
>
> The main reason for me to start using D 10 years ago was the obvious
> PRAGMATIC design of the language. I did not start using it because of
> (possible) functional orientation. Actually, I would probably turn my
> back on D if I saw it promotes declarative style more than imperative.
>
> I think the current mix of both worlds is the best direction for D.

The problem isn't about following haskell precisely or not (I think we shouldn't). The problem is wanting to have everything, and resulting in getting nothing.

Let's take haskell as example. Function are all pure. So it doesn't matter when a function get executed or not, and, as a result, haskell don't need a explicit function call like () in D.

Some people find that great, and want it to be the case in D. So D drop () usage.

Now, as D don't enforce purity, when does the function get executed is important. As a result, complicated scheme is implemented to know when does the function get executed, wand when it doesn't (You'll notice *4* families of scheme for that in D).

As a result, the design is overly complex, and defined nowhere. Just to have that haskell feature, that work well in haskell because of some other properties of the language D don't have.
August 07, 2012
On Tuesday, 7 August 2012 at 15:14:09 UTC, Dejan Lekic wrote:
> You do not seriously expect D to copy exactly how Haskel (or any other similar declarative langauge) treat functions? Does it really have to be an exact copy? I am not trying to defend D language designer(s) here, just trying to say that D should have own style, if there is sense behind it, it does not necessarily have to conform 100% to any paradigm.
>
> The main reason for me to start using D 10 years ago was the obvious PRAGMATIC design of the language. I did not start using it because of (possible) functional orientation. Actually, I would probably turn my back on D if I saw it promotes declarative style more than imperative.
>
> I think the current mix of both worlds is the best direction for D.

 I'm not arguing, but going to give my two or three cents on the matter; I can't recall if someone already mentioned all this.

 Other than 0-1 arguments being allowed to operate with or without parentheses, functionally is there any real reason to disallow or force it? Aside from variables being unable to use ()'s there seems to be no real difference otherwise. In some respects that's a good thing, but you can also take a built-in type and seamlessly replace it with functions or properties depending on the needs; The only difference is certain options (like .init or .min/.max) no longer are accessible.

 D can be a terse language, and building up from other language's mistakes and faults to make something newer, more robust, more useful. So what if there  might be 3 different ways to call something, that doesn't make any one of them wrong compared to another. One way of calling it may be simpler or better than another, and having parentheses unnecessarily (be it property or otherwise) seems silly.

 assuming definition: string strip(string input);

 string x = "something";
 auto y1 = x.strip;
 auto y2 = x.strip();
 auto y3 = strip(x);

 All do the same thing. Since strip isn't a property, more restrictive may prevent y1 from working. But if you want to chain commands, the ()'s just seem ugly and don't help much. So what if it's a function?

 assuming definition: string replace(string input, string from, string to);

 auto y1 = x.strip.replace("from", "to");
 auto y2 = x.strip().replace("from", "to");
 auto y3 = strip(x).replace("from", "to"));
 auto y4 = replace(x.strip, "from", "to"));
 auto y5 = replace(x.strip(), "from", "to"));

 If replace was a template, perhaps:

 assuming definition: string replace(string from)(string input, string to);

 auto y1 = x.strip.replace!"from"("to");
 auto y2 = x.strip().replace!"from"("to");
 auto y3 = strip(x.replace!"from"("to"));
 auto y4 = replace!"from"(x.strip, "to"));
 auto y5 = replace!"from"(x.strip(), "to"));

 In the lower two cases #2 seems the ugliest since () only tells us it's a function but we already sort of know that with the chaining. If properties are enforced with only one calling convention, then only #1 or #2 will work at any given time, maybe not even y3. #1 seems the simplest to follow during chaining in this case. #4 & #5 can be followed fairly easily, but seems more verbose than needed.

 Expressiveness is important, and if it feels most natural writing a certain way, or easier to follow then it should be allowed (assuming it has no impact on performance or language structure).

 I guess at this point, I'd almost suggest leaving it as it is; Open for the programmer, but a switch to make it more strict for say libraries, or where there's a potential for it to be a variable in some cases and something else (static if's for types).
August 08, 2012
> The problem isn't about following haskell precisely or not (I think we shouldn't). The problem is wanting to have everything, and resulting in getting nothing.
>
> Let's take haskell as example. Function are all pure. So it doesn't matter when a function get executed or not, and, as a result, haskell don't need a explicit function call like () in D.
>
> Some people find that great, and want it to be the case in D. So D drop () usage.
>
> Now, as D don't enforce purity, when does the function get executed is important. As a result, complicated scheme is implemented to know when does the function get executed, wand when it doesn't (You'll notice *4* families of scheme for that in D).
>
> As a result, the design is overly complex, and defined nowhere. Just to have that haskell feature, that work well in haskell because of some other properties of the language D don't have.

What are the 4 "families of scheme to know when does the function get executed"?
August 08, 2012
On Tuesday, 7 August 2012 at 18:36:28 UTC, deadalnix wrote:
>
> The problem isn't about following haskell precisely or not (I think
> we shouldn't). The problem is wanting to have everything, and
> resulting in getting nothing.
>
> Let's take haskell as example. Function are all pure. So it doesn't
> matter when a function get executed or not, and, as a result,
> haskell don't need a explicit function call like () in D.

That's not a good example. Haskell may not use parentheses for
function parameters, but that has nothing to do with purity, or even
with non-strict evaluation. It's because, syntactically, concatenation
in Haskell represents function application. The Haskell expression:

  f x y z

is equivalent to the Haskell expression:

  (((f x) y) z)

translated into D syntax:

  ((f(x))(y))(z),  or just f(x)(y)(z).

Graham

1 2 3
Next ›   Last »